mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor UI elements positioning and minor UI fixes
This commit is contained in:
parent
1dd007a3e6
commit
88a7181695
|
@ -5,7 +5,7 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
dense?: boolean
|
dense?: boolean
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
borderClass?: string
|
borderClass?: string
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ function Button({
|
||||||
dense, disabled,
|
dense, disabled,
|
||||||
borderClass = 'border rounded',
|
borderClass = 'border rounded',
|
||||||
colorClass = 'clr-btn-default',
|
colorClass = 'clr-btn-default',
|
||||||
widthClass = 'w-fit h-fit',
|
dimensions = 'w-fit h-fit',
|
||||||
loading, onClick,
|
loading, onClick,
|
||||||
...props
|
...props
|
||||||
}: ButtonProps) {
|
}: ButtonProps) {
|
||||||
|
@ -27,10 +27,10 @@ function Button({
|
||||||
disabled={disabled ?? loading}
|
disabled={disabled ?? loading}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`inline-flex items-center gap-2 align-middle justify-center select-none ${padding} ${colorClass} ${widthClass} ${borderClass} ${cursor}`}
|
className={`inline-flex items-center gap-2 align-middle justify-center select-none ${padding} ${colorClass} ${dimensions} ${borderClass} ${cursor}`}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{icon && <span>{icon}</span>}
|
{icon && icon}
|
||||||
{text && <span className={'font-semibold'}>{text}</span>}
|
{text && <span className={'font-semibold'}>{text}</span>}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
interface CardProps {
|
|
||||||
title?: string
|
|
||||||
widthClass?: string
|
|
||||||
children: React.ReactNode
|
|
||||||
}
|
|
||||||
|
|
||||||
function Card({ title, widthClass = 'min-w-fit', children }: CardProps) {
|
|
||||||
return (
|
|
||||||
<div className={`border shadow-md py-2 clr-app px-6 ${widthClass}`}>
|
|
||||||
{ title && <h1 className='mb-2 text-xl font-bold whitespace-nowrap'>{title}</h1> }
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Card;
|
|
|
@ -9,7 +9,7 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
|
||||||
label?: string
|
label?: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
|
|
||||||
value: boolean
|
value: boolean
|
||||||
|
@ -18,7 +18,7 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
|
||||||
|
|
||||||
function Checkbox({
|
function Checkbox({
|
||||||
id, required, disabled, tooltip, label,
|
id, required, disabled, tooltip, label,
|
||||||
widthClass = 'w-fit', value, setValue, ...props
|
dimensions = 'w-fit', value, setValue, ...props
|
||||||
}: CheckboxProps) {
|
}: CheckboxProps) {
|
||||||
const cursor = useMemo(
|
const cursor = useMemo(
|
||||||
() => {
|
() => {
|
||||||
|
@ -46,7 +46,7 @@ function Checkbox({
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
id={id}
|
id={id}
|
||||||
className={`flex items-center [&:not(:first-child)]:mt-3 clr-outline focus:outline-dotted focus:outline-1 ${widthClass}`}
|
className={`flex items-center clr-outline focus:outline-dotted focus:outline-1 ${dimensions}`}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
interface DropdownProps {
|
interface DropdownProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
stretchLeft?: boolean
|
stretchLeft?: boolean
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function Dropdown({ children, widthClass = 'w-fit', stretchLeft }: DropdownProps) {
|
function Dropdown({ children, dimensions = 'w-fit', stretchLeft }: DropdownProps) {
|
||||||
return (
|
return (
|
||||||
<div className='relative text-sm'>
|
<div className='relative text-sm'>
|
||||||
<div className={`absolute ${stretchLeft ? 'right-0' : 'left-0'} mt-2 py-1 z-tooltip flex flex-col items-stretch justify-start origin-top-right border divide-y divide-inherit rounded-md shadow-lg clr-input ${widthClass}`}>
|
<div className={`absolute ${stretchLeft ? 'right-0' : 'left-0'} mt-2 py-1 z-tooltip flex flex-col items-stretch justify-start origin-top-right border divide-y divide-inherit rounded-md shadow-lg clr-input ${dimensions}`}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@ function DropdownCheckbox({ tooltip, setValue, disabled, ...props }: DropdownChe
|
||||||
className={`px-4 py-1 text-left overflow-ellipsis ${behavior} w-full whitespace-nowrap`}
|
className={`px-4 py-1 text-left overflow-ellipsis ${behavior} w-full whitespace-nowrap`}
|
||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
widthClass='w-full'
|
dimensions='w-full'
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
setValue={setValue}
|
setValue={setValue}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -9,13 +9,13 @@ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'title'
|
||||||
label: string
|
label: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
acceptType?: string
|
acceptType?: string
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function FileInput({
|
function FileInput({
|
||||||
label, acceptType, tooltip,
|
label, acceptType, tooltip,
|
||||||
widthClass = 'w-fit', onChange,
|
dimensions = 'w-fit', onChange,
|
||||||
...props
|
...props
|
||||||
}: FileInputProps) {
|
}: FileInputProps) {
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
@ -37,7 +37,7 @@ function FileInput({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex flex-col gap-2 py-2 mt-3 items-start ${widthClass}`}>
|
<div className={`flex flex-col gap-2 py-2 items-start ${dimensions}`}>
|
||||||
<input type='file'
|
<input type='file'
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
style={{ display: 'none' }}
|
style={{ display: 'none' }}
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
import Card from './Card';
|
|
||||||
|
|
||||||
interface FormProps {
|
interface FormProps {
|
||||||
title: string
|
title: string
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void
|
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
function Form({ title, onSubmit, widthClass = 'max-w-xs', children }: FormProps) {
|
function Form({ title, onSubmit, dimensions = 'max-w-xs', children }: FormProps) {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-center w-full'>
|
<form
|
||||||
<Card title={title} widthClass={widthClass}>
|
className={`border shadow-md py-2 clr-app px-6 flex flex-col gap-3 ${dimensions}`}
|
||||||
<form onSubmit={onSubmit}>
|
onSubmit={onSubmit}
|
||||||
{children}
|
>
|
||||||
</form>
|
{ title && <h1 className='text-xl font-bold whitespace-nowrap'>{title}</h1> }
|
||||||
</Card>
|
{children}
|
||||||
</div>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
interface MiniButtonProps
|
interface MiniButtonProps
|
||||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'title' > {
|
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'title' |'children' > {
|
||||||
icon?: React.ReactNode
|
icon: React.ReactNode
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
noHover?: boolean
|
noHover?: boolean
|
||||||
|
dimensions?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function MiniButton({ icon, tooltip, children, noHover, tabIndex, ...props }: MiniButtonProps) {
|
function MiniButton({
|
||||||
|
icon, tooltip, noHover, tabIndex, dimensions,
|
||||||
|
...props
|
||||||
|
}: MiniButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button type='button'
|
<button type='button'
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
tabIndex={tabIndex ?? -1}
|
tabIndex={tabIndex ?? -1}
|
||||||
className={`px-1 py-1 font-bold rounded-full cursor-pointer whitespace-nowrap disabled:cursor-not-allowed clr-btn-clear ${noHover ? 'outline-none' : 'clr-hover'}`}
|
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}`}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{icon && <span>{icon}</span>}
|
{icon}
|
||||||
{children}
|
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ function Modal({
|
||||||
<Button
|
<Button
|
||||||
text={submitText}
|
text={submitText}
|
||||||
tooltip={!canSubmit ? submitInvalidTooltip: ''}
|
tooltip={!canSubmit ? submitInvalidTooltip: ''}
|
||||||
widthClass='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
|
dimensions='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
|
||||||
colorClass='clr-btn-primary'
|
colorClass='clr-btn-primary'
|
||||||
disabled={!canSubmit}
|
disabled={!canSubmit}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
|
@ -59,7 +59,7 @@ function Modal({
|
||||||
/>}
|
/>}
|
||||||
<Button
|
<Button
|
||||||
text={readonly ? 'Закрыть' : 'Отмена'}
|
text={readonly ? 'Закрыть' : 'Отмена'}
|
||||||
widthClass='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
|
dimensions='min-w-[6rem] min-h-[2.6rem] w-fit h-fit'
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,17 +4,17 @@ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'child
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
icon?: React.ReactNode
|
icon?: React.ReactNode
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubmitButton({
|
function SubmitButton({
|
||||||
text = 'ОК', icon, disabled, tooltip, loading,
|
text = 'ОК', icon, disabled, tooltip, loading,
|
||||||
widthClass = 'w-fit h-fit'
|
dimensions = 'w-fit h-fit'
|
||||||
}: SubmitButtonProps) {
|
}: SubmitButtonProps) {
|
||||||
return (
|
return (
|
||||||
<button type='submit'
|
<button type='submit'
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-4 py-2 inline-flex items-center gap-2 align-middle justify-center font-semibold select-none disabled:cursor-not-allowed border rounded clr-btn-primary ${widthClass} ${loading ? ' cursor-progress' : ''}`}
|
className={`px-4 py-2 inline-flex items-center gap-2 align-middle justify-center font-semibold select-none disabled:cursor-not-allowed border rounded clr-btn-primary ${dimensions} ${loading ? ' cursor-progress' : ''}`}
|
||||||
disabled={disabled ?? loading}
|
disabled={disabled ?? loading}
|
||||||
>
|
>
|
||||||
{icon && <span>{icon}</span>}
|
{icon && <span>{icon}</span>}
|
||||||
|
|
|
@ -6,27 +6,27 @@ export interface TextAreaProps
|
||||||
extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className' | 'title'> {
|
extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'className' | 'title'> {
|
||||||
label: string
|
label: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextArea({
|
function TextArea({
|
||||||
id, label, required, tooltip,
|
id, label, required, tooltip,
|
||||||
widthClass = 'w-full',
|
dimensions = 'w-full',
|
||||||
colorClass = 'clr-input',
|
colorClass = 'clr-input',
|
||||||
rows = 4,
|
rows = 4,
|
||||||
...props
|
...props
|
||||||
}: TextAreaProps) {
|
}: TextAreaProps) {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-start [&:not(:first-child)]:mt-3'>
|
<div className='flex flex-col items-start gap-2'>
|
||||||
<Label
|
{label && <Label
|
||||||
text={label}
|
text={label}
|
||||||
required={!props.disabled && required}
|
required={!props.disabled && required}
|
||||||
htmlFor={id}
|
htmlFor={id}
|
||||||
/>
|
/>}
|
||||||
<textarea id={id}
|
<textarea id={id}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
className={`px-3 py-2 mt-2 leading-tight border shadow clr-outline ${colorClass} ${widthClass}`}
|
className={`px-3 py-2 leading-tight border shadow clr-outline ${colorClass} ${dimensions}`}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
required={required}
|
required={required}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -5,19 +5,19 @@ extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'title'>
|
||||||
id?: string
|
id?: string
|
||||||
label?: string
|
label?: string
|
||||||
tooltip?: string
|
tooltip?: string
|
||||||
widthClass?: string
|
dimensions?: string
|
||||||
colorClass?: string
|
colorClass?: string
|
||||||
singleRow?: boolean
|
singleRow?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextInput({
|
function TextInput({
|
||||||
id, required, label, singleRow, tooltip,
|
id, required, label, singleRow, tooltip,
|
||||||
widthClass = 'w-full',
|
dimensions = 'w-full',
|
||||||
colorClass = 'clr-input',
|
colorClass = 'clr-input',
|
||||||
...props
|
...props
|
||||||
}: 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 ${singleRow ? 'items-center gap-4 ' + dimensions : 'flex-col items-start gap-2'}`}>
|
||||||
{label && <Label
|
{label && <Label
|
||||||
text={label}
|
text={label}
|
||||||
required={!props.disabled && required}
|
required={!props.disabled && required}
|
||||||
|
@ -25,7 +25,7 @@ function TextInput({
|
||||||
/>}
|
/>}
|
||||||
<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 ? '' : dimensions}`}
|
||||||
required={required}
|
required={required}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -13,7 +13,7 @@ extends Omit<CheckboxProps, 'value' | 'setValue'> {
|
||||||
|
|
||||||
function Tristate({
|
function Tristate({
|
||||||
id, required, disabled, tooltip, label,
|
id, required, disabled, tooltip, label,
|
||||||
widthClass = 'w-fit', value, setValue, ...props
|
dimensions = 'w-fit', value, setValue, ...props
|
||||||
}: TristateProps) {
|
}: TristateProps) {
|
||||||
const cursor = useMemo(
|
const cursor = useMemo(
|
||||||
() => {
|
() => {
|
||||||
|
@ -47,7 +47,7 @@ function Tristate({
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
id={id}
|
id={id}
|
||||||
className={`flex items-center [&:not(:first-child)]:mt-3 clr-outline focus:outline-dotted focus:outline-1 ${widthClass}`}
|
className={`flex items-center clr-outline focus:outline-dotted focus:outline-1 ${dimensions}`}
|
||||||
title={tooltip}
|
title={tooltip}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
|
|
|
@ -5,7 +5,7 @@ function HelpConstituenta() {
|
||||||
return (
|
return (
|
||||||
<div className=''>
|
<div className=''>
|
||||||
<h1>Подсказки</h1>
|
<h1>Подсказки</h1>
|
||||||
<p><b className='text-warning'>Изменения сохраняются ПОСЛЕ нажатия на кнопку снизу или слева вверху</b></p>
|
<p><b className='text-warning'>Изменения сохраняются ПОСЛЕ нажатия на кнопку снизу или справа вверху</b></p>
|
||||||
<p><b>Клик на формальное выражение</b> - обратите внимание на кнопки снизу.<br/>Для каждой есть горячая клавиша в подсказке</p>
|
<p><b>Клик на формальное выражение</b> - обратите внимание на кнопки снизу.<br/>Для каждой есть горячая клавиша в подсказке</p>
|
||||||
<p><b>Список конституент справа</b> - обратите внимание на настройки фильтрации</p>
|
<p><b>Список конституент справа</b> - обратите внимание на настройки фильтрации</p>
|
||||||
<p>- слева от ввода текста настраивается набор атрибутов конституенты</p>
|
<p>- слева от ввода текста настраивается набор атрибутов конституенты</p>
|
||||||
|
|
|
@ -31,7 +31,7 @@ function UserDropdown({ hideDropdown }: UserDropdownProps) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown widthClass='w-36' stretchLeft>
|
<Dropdown dimensions='w-36' stretchLeft>
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
tooltip='Профиль пользователя'
|
tooltip='Профиль пользователя'
|
||||||
onClick={navigateProfile}
|
onClick={navigateProfile}
|
||||||
|
|
|
@ -77,27 +77,29 @@ function CreateRSFormPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RequireAuth>
|
<RequireAuth>
|
||||||
<Form title='Создание концептуальной схемы'
|
<div className='flex justify-center w-full'>
|
||||||
onSubmit={handleSubmit}
|
<Form title='Создание концептуальной схемы'
|
||||||
widthClass='max-w-lg w-full mt-4'
|
onSubmit={handleSubmit}
|
||||||
>
|
dimensions='max-w-lg w-full mt-4'
|
||||||
<div className='relative w-full'>
|
>
|
||||||
<div className='absolute top-[-2.4rem] right-[-1rem] flex'>
|
<div className='relative w-full'>
|
||||||
<input
|
<div className='absolute top-[-2.4rem] right-[-1rem] flex'>
|
||||||
type='file'
|
<input
|
||||||
ref={inputRef}
|
type='file'
|
||||||
style={{ display: 'none' }}
|
ref={inputRef}
|
||||||
accept={EXTEOR_TRS_FILE}
|
style={{ display: 'none' }}
|
||||||
onChange={handleFileChange}
|
accept={EXTEOR_TRS_FILE}
|
||||||
/>
|
onChange={handleFileChange}
|
||||||
<MiniButton
|
/>
|
||||||
tooltip='Загрузить из Экстеор'
|
<MiniButton
|
||||||
icon={<UploadIcon size={5} color='text-primary'/>}
|
tooltip='Загрузить из Экстеор'
|
||||||
onClick={() => inputRef.current?.click()}
|
icon={<UploadIcon size={5} color='text-primary'/>}
|
||||||
/>
|
onClick={() => inputRef.current?.click()}
|
||||||
</div>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col gap-3'>
|
||||||
{ fileName && <Label text={`Загружен файл: ${fileName}`} />}
|
{ fileName && <Label text={`Загружен файл: ${fileName}`} />}
|
||||||
<TextInput id='title' label='Полное название' type='text'
|
<TextInput id='title' label='Полное название' type='text'
|
||||||
required={!file}
|
required={!file}
|
||||||
|
@ -121,22 +123,23 @@ function CreateRSFormPage() {
|
||||||
value={common}
|
value={common}
|
||||||
setValue={value => setCommon(value ?? false)}
|
setValue={value => setCommon(value ?? false)}
|
||||||
/>
|
/>
|
||||||
<div className='flex items-center justify-center gap-4 py-2 mt-4'>
|
<div className='flex items-center justify-center gap-4 py-2'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Создать схему'
|
text='Создать схему'
|
||||||
loading={processing}
|
loading={processing}
|
||||||
widthClass='min-w-[10rem]'
|
dimensions='min-w-[10rem]'
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
text='Отмена'
|
text='Отмена'
|
||||||
onClick={() => handleCancel()}
|
onClick={() => handleCancel()}
|
||||||
widthClass='min-w-[10rem]'
|
dimensions='min-w-[10rem]'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ error && <BackendError error={error} />}
|
{ error && <BackendError error={error} />}
|
||||||
</Form>
|
</div>
|
||||||
</RequireAuth>
|
</Form>
|
||||||
);
|
</div>
|
||||||
|
</RequireAuth>);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CreateRSFormPage;
|
export default CreateRSFormPage;
|
||||||
|
|
|
@ -30,7 +30,7 @@ function PickerStrategy({ value, onChange }: PickerStrategyProps) {
|
||||||
dense
|
dense
|
||||||
tooltip='Фильтры'
|
tooltip='Фильтры'
|
||||||
colorClass='clr-input clr-hover text-btn'
|
colorClass='clr-input clr-hover text-btn'
|
||||||
widthClass='h-full py-1 px-2 border-none'
|
dimensions='h-full py-1 px-2 border-none'
|
||||||
onClick={pickerMenu.toggle}
|
onClick={pickerMenu.toggle}
|
||||||
/>
|
/>
|
||||||
{ pickerMenu.isActive &&
|
{ pickerMenu.isActive &&
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { IUserLoginData } from '../models/library';
|
||||||
function ProcessError({error}: {error: ErrorInfo}): React.ReactElement {
|
function ProcessError({error}: {error: ErrorInfo}): React.ReactElement {
|
||||||
if (axios.isAxiosError(error) && error.response && error.response.status === 400) {
|
if (axios.isAxiosError(error) && error.response && error.response.status === 400) {
|
||||||
return (
|
return (
|
||||||
<div className='mt-2 text-sm select-text text-warning'>
|
<div className='text-sm select-text text-warning'>
|
||||||
На Портале отсутствует такое сочетание имени пользователя и пароля
|
На Портале отсутствует такое сочетание имени пользователя и пароля
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -80,7 +80,7 @@ function LoginPage() {
|
||||||
<Form
|
<Form
|
||||||
title='Вход в Портал'
|
title='Вход в Портал'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
widthClass='w-[24rem]'
|
dimensions='w-[24rem]'
|
||||||
>
|
>
|
||||||
<TextInput id='username'
|
<TextInput id='username'
|
||||||
label='Имя пользователя'
|
label='Имя пользователя'
|
||||||
|
@ -98,14 +98,14 @@ function LoginPage() {
|
||||||
onChange={event => setPassword(event.target.value)}
|
onChange={event => setPassword(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className='flex justify-center w-full gap-2 py-2 mt-4'>
|
<div className='flex justify-center w-full gap-2 py-2'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Вход'
|
text='Вход'
|
||||||
widthClass='w-[12rem]'
|
dimensions='w-[12rem]'
|
||||||
loading={loading}
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col mt-2 text-sm'>
|
<div className='flex flex-col text-sm'>
|
||||||
<TextURL text='Восстановить пароль...' href='/restore-password' />
|
<TextURL text='Восстановить пароль...' href='/restore-password' />
|
||||||
<TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' />
|
<TextURL text='Нет аккаунта? Зарегистрируйтесь...' href='/signup' />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -61,6 +61,7 @@ function DlgCloneRSForm({ hideWindow }: DlgCloneRSFormProps) {
|
||||||
submitText='Создать'
|
submitText='Создать'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
|
<div className='flex flex-col gap-3'>
|
||||||
<TextInput id='title' label='Полное название' type='text'
|
<TextInput id='title' label='Полное название' type='text'
|
||||||
required
|
required
|
||||||
value={title}
|
value={title}
|
||||||
|
@ -69,7 +70,7 @@ function DlgCloneRSForm({ hideWindow }: DlgCloneRSFormProps) {
|
||||||
<TextInput id='alias' label='Сокращение' type='text'
|
<TextInput id='alias' label='Сокращение' type='text'
|
||||||
required
|
required
|
||||||
value={alias}
|
value={alias}
|
||||||
widthClass='max-w-sm'
|
dimensions='max-w-sm'
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextArea id='comment' label='Комментарий'
|
<TextArea id='comment' label='Комментарий'
|
||||||
|
@ -80,6 +81,7 @@ function DlgCloneRSForm({ hideWindow }: DlgCloneRSFormProps) {
|
||||||
value={common}
|
value={common}
|
||||||
setValue={value => setCommon(value)}
|
setValue={value => setCommon(value)}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ function DlgCreateCst({ hideWindow, initial, onCreate }: DlgCreateCstProps) {
|
||||||
canSubmit={validated}
|
canSubmit={validated}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
>
|
>
|
||||||
<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 gap-3'>
|
||||||
<div className='flex justify-center w-full'>
|
<div className='flex justify-center w-full'>
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
className='my-2 min-w-[15rem] self-center'
|
className='my-2 min-w-[15rem] self-center'
|
||||||
|
@ -73,14 +73,12 @@ function DlgCreateCst({ hideWindow, initial, onCreate }: DlgCreateCstProps) {
|
||||||
spellCheck
|
spellCheck
|
||||||
onChange={event => setTerm(event.target.value)}
|
onChange={event => setTerm(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<div className='mt-3'>
|
<RSInput id='expression' label='Формальное выражение'
|
||||||
<RSInput id='expression' label='Формальное выражение'
|
editable
|
||||||
editable
|
height='5.5rem'
|
||||||
height='5.5rem'
|
value={expression}
|
||||||
value={expression}
|
onChange={value => setExpression(value)}
|
||||||
onChange={value => setExpression(value)}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<TextArea id='definition' label='Текстовое определение'
|
<TextArea id='definition' label='Текстовое определение'
|
||||||
placeholder='Лингвистическая интерпретация формального выражения'
|
placeholder='Лингвистическая интерпретация формального выражения'
|
||||||
rows={2}
|
rows={2}
|
||||||
|
|
|
@ -36,14 +36,14 @@ function DlgDeleteCst({ hideWindow, selected, onDelete }: DlgDeleteCstProps) {
|
||||||
>
|
>
|
||||||
<div className='max-w-[60vw] min-w-[20rem]'>
|
<div className='max-w-[60vw] min-w-[20rem]'>
|
||||||
<p>Выбраны к удалению: <b>{selected.length}</b></p>
|
<p>Выбраны к удалению: <b>{selected.length}</b></p>
|
||||||
<div className='px-3 border h-[9rem] overflow-y-auto whitespace-nowrap'>
|
<div className='px-3 border h-[9rem] mt-1 overflow-y-auto whitespace-nowrap'>
|
||||||
{selected.map(id => {
|
{selected.map(id => {
|
||||||
const cst = schema!.items.find(cst => cst.id === id);
|
const cst = schema!.items.find(cst => cst.id === id);
|
||||||
return (cst && <p>{getCstLabel(cst)}</p>);
|
return (cst && <p>{getCstLabel(cst)}</p>);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<p className='mt-4'>Зависимые конституенты: <b>{expansion.length}</b></p>
|
<p className='mt-4'>Зависимые конституенты: <b>{expansion.length}</b></p>
|
||||||
<div className='px-3 border h-[9rem] overflow-y-auto whitespace-nowrap'>
|
<div className='mt-1 mb-3 px-3 border h-[9rem] overflow-y-auto whitespace-nowrap'>
|
||||||
{expansion.map(id => {
|
{expansion.map(id => {
|
||||||
const cst = schema!.items.find(cst => cst.id === id);
|
const cst = schema!.items.find(cst => cst.id === id);
|
||||||
return (cst && <p>{getCstLabel(cst)}</p>);
|
return (cst && <p>{getCstLabel(cst)}</p>);
|
||||||
|
|
|
@ -75,7 +75,7 @@ function DlgGraphOptions({ hideWindow, initial, onConfirm }:DlgGraphOptionsProps
|
||||||
submitText='Применить'
|
submitText='Применить'
|
||||||
>
|
>
|
||||||
<div className='flex gap-2'>
|
<div className='flex gap-2'>
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1>Преобразования</h1>
|
<h1>Преобразования</h1>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Скрыть текст'
|
label='Скрыть текст'
|
||||||
|
@ -102,7 +102,7 @@ function DlgGraphOptions({ hideWindow, initial, onConfirm }:DlgGraphOptionsProps
|
||||||
setValue={ value => setNoTransitive(value) }
|
setValue={ value => setNoTransitive(value) }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex flex-col'>
|
<div className='flex flex-col gap-1'>
|
||||||
<h1>Типы конституент</h1>
|
<h1>Типы конституент</h1>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label={getCstTypeLabel(CstType.BASE)}
|
label={getCstTypeLabel(CstType.BASE)}
|
||||||
|
|
|
@ -5,8 +5,8 @@ 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, getCstTypeLabel, getCstTypePrefix } from '../../utils/staticUI';
|
|
||||||
import { SelectorCstType } from '../../utils/selectors';
|
import { SelectorCstType } from '../../utils/selectors';
|
||||||
|
import { createAliasFor, getCstTypeLabel, getCstTypePrefix } from '../../utils/staticUI';
|
||||||
|
|
||||||
interface DlgRenameCstProps
|
interface DlgRenameCstProps
|
||||||
extends Pick<ModalProps, 'hideWindow'> {
|
extends Pick<ModalProps, 'hideWindow'> {
|
||||||
|
@ -78,7 +78,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
|
||||||
<div>
|
<div>
|
||||||
<TextInput id='alias' label='Имя'
|
<TextInput id='alias' label='Имя'
|
||||||
singleRow
|
singleRow
|
||||||
widthClass='w-[7rem]'
|
dimensions='w-[7rem]'
|
||||||
value={alias}
|
value={alias}
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -45,7 +45,7 @@ function DlgUploadRSForm({ hideWindow }: DlgUploadRSFormProps) {
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
submitText='Загрузить'
|
submitText='Загрузить'
|
||||||
>
|
>
|
||||||
<div className='flex flex-col items-center'>
|
<div className='flex flex-col items-start min-w-[20rem] max-w-[20rem]'>
|
||||||
<FileInput
|
<FileInput
|
||||||
label='Выбрать файл'
|
label='Выбрать файл'
|
||||||
acceptType={EXTEOR_TRS_FILE}
|
acceptType={EXTEOR_TRS_FILE}
|
||||||
|
@ -55,7 +55,7 @@ function DlgUploadRSForm({ hideWindow }: DlgUploadRSFormProps) {
|
||||||
label='Загружать название и комментарий'
|
label='Загружать название и комментарий'
|
||||||
value={loadMetadata}
|
value={loadMetadata}
|
||||||
setValue={value => setLoadMetadata(value)}
|
setValue={value => setLoadMetadata(value)}
|
||||||
widthClass='w-fit pb-2'
|
dimensions='w-fit pb-2'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -136,41 +136,19 @@ function EditorConstituenta({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex items-stretch w-full gap-2 mb-2 justify-stretch'>
|
<div className='flex w-full gap-2 mb-2 justify-stretch'>
|
||||||
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-min px-4 py-2 border-y border-r'>
|
<form onSubmit={handleSubmit} className='min-w-[50rem] max-w-min px-4 py-2 border-y border-r'>
|
||||||
<div className='relative'>
|
<div className='relative w-full'>
|
||||||
<div className='absolute top-0 left-0'>
|
<div className='absolute top-0 right-0 flex items-start justify-between w-full'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Сохранить изменения'
|
tooltip='Редактировать словоформы термина'
|
||||||
disabled={!isModified || !isEnabled}
|
disabled={!isEnabled}
|
||||||
icon={<SaveIcon size={6} color={isModified && isEnabled ? 'text-primary' : ''}/>}
|
dimensions='w-fit pl-[3.2rem] pt-[0.4rem]'
|
||||||
onClick={() => handleSubmit()}
|
noHover
|
||||||
/>
|
onClick={onEditTerm}
|
||||||
</div>
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
</div>
|
/>
|
||||||
<div className='relative'>
|
<div className='flex items-center justify-center w-full gap-1'>
|
||||||
<div className='absolute top-0 right-0 flex justify-end'>
|
|
||||||
<MiniButton
|
|
||||||
tooltip='Удалить редактируемую конституенту'
|
|
||||||
disabled={!isEnabled}
|
|
||||||
onClick={handleDelete}
|
|
||||||
icon={<DumpBinIcon size={5} color={isEnabled ? 'text-warning' : ''} />}
|
|
||||||
/>
|
|
||||||
<MiniButton
|
|
||||||
tooltip='Создать конституенты после данной'
|
|
||||||
disabled={!isEnabled}
|
|
||||||
onClick={handleCreateCst}
|
|
||||||
icon={<SmallPlusIcon size={5} color={isEnabled ? 'text-success' : ''} />}
|
|
||||||
/>
|
|
||||||
<div id='cst-help' className='flex items-center ml-[6px]'>
|
|
||||||
<HelpIcon color='text-primary' size={5} />
|
|
||||||
</div>
|
|
||||||
<ConceptTooltip anchorSelect='#cst-help'>
|
|
||||||
<HelpConstituenta />
|
|
||||||
</ConceptTooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex items-center justify-center w-full gap-1 pr-10'>
|
|
||||||
<div className='font-semibold w-fit'>
|
<div className='font-semibold w-fit'>
|
||||||
<span className=''>Конституента </span>
|
<span className=''>Конституента </span>
|
||||||
<span className='ml-4'>{alias}</span>
|
<span className='ml-4'>{alias}</span>
|
||||||
|
@ -183,17 +161,35 @@ function EditorConstituenta({
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='relative'>
|
<div className='flex justify-end min-w-fit'>
|
||||||
<div className='absolute left-[3.2rem] top-[0.5rem]'>
|
<MiniButton
|
||||||
<MiniButton
|
tooltip='Сохранить изменения'
|
||||||
tooltip='Редактировать словоформы термина'
|
disabled={!isModified || !isEnabled}
|
||||||
disabled={!isEnabled}
|
icon={<SaveIcon size={5} color={isModified && isEnabled ? 'text-primary' : ''}/>}
|
||||||
noHover
|
onClick={() => handleSubmit()}
|
||||||
onClick={onEditTerm}
|
/>
|
||||||
icon={<PenIcon size={4} color={isEnabled ? 'text-primary' : ''} />}
|
<MiniButton
|
||||||
/>
|
tooltip='Создать конституенты после данной'
|
||||||
</div>
|
disabled={!isEnabled}
|
||||||
|
onClick={handleCreateCst}
|
||||||
|
icon={<SmallPlusIcon size={5} color={isEnabled ? 'text-success' : ''} />}
|
||||||
|
/>
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Удалить редактируемую конституенту'
|
||||||
|
disabled={!isEnabled}
|
||||||
|
onClick={handleDelete}
|
||||||
|
icon={<DumpBinIcon size={5} color={isEnabled ? 'text-warning' : ''} />}
|
||||||
|
/>
|
||||||
|
<div id='cst-help' className='px-1 py-1'>
|
||||||
|
<HelpIcon color='text-primary' size={5} />
|
||||||
|
</div>
|
||||||
|
<ConceptTooltip anchorSelect='#cst-help' offset={4}>
|
||||||
|
<HelpConstituenta />
|
||||||
|
</ConceptTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col gap-2 mt-1'>
|
||||||
<ReferenceInput id='term' label='Термин'
|
<ReferenceInput id='term' label='Термин'
|
||||||
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
placeholder='Обозначение, используемое в текстовых определениях данной схемы'
|
||||||
rows={2}
|
rows={2}
|
||||||
|
@ -242,25 +238,25 @@ function EditorConstituenta({
|
||||||
onChange={event => setConvention(event.target.value)}
|
onChange={event => setConvention(event.target.value)}
|
||||||
onFocus={() => setEditMode(EditMode.TEXT)}
|
onFocus={() => setEditMode(EditMode.TEXT)}
|
||||||
/>
|
/>
|
||||||
<div className='flex justify-center w-full mt-4 mb-2'>
|
<div className='flex justify-center w-full mt-2'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Сохранить изменения'
|
text='Сохранить изменения'
|
||||||
disabled={!isModified || !isEnabled}
|
disabled={!isModified || !isEnabled}
|
||||||
icon={<SaveIcon size={6} />}
|
icon={<SaveIcon size={6} />}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
{(windowSize.width ?? 0) >= SIDELIST_HIDE_THRESHOLD &&
|
</form>
|
||||||
<div className='self-stretch w-full pb-1 border'>
|
{(windowSize.width ?? 0) >= SIDELIST_HIDE_THRESHOLD &&
|
||||||
<ViewSideConstituents
|
<div className='self-stretch w-full border'>
|
||||||
expression={expression}
|
<ViewSideConstituents
|
||||||
baseHeight={UNFOLDED_HEIGHT}
|
expression={expression}
|
||||||
activeID={activeID}
|
baseHeight={UNFOLDED_HEIGHT}
|
||||||
onOpenEdit={onOpenEdit}
|
activeID={activeID}
|
||||||
/>
|
onOpenEdit={onOpenEdit}
|
||||||
</div>}
|
/>
|
||||||
</div>
|
</div>}
|
||||||
);
|
</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EditorConstituenta;
|
export default EditorConstituenta;
|
||||||
|
|
|
@ -224,7 +224,7 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
return (<>
|
return (<>
|
||||||
<div
|
<div
|
||||||
id={`${prefixes.cst_list}${cst.alias}`}
|
id={`${prefixes.cst_list}${cst.alias}`}
|
||||||
className='w-full min-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
className='w-full min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
||||||
style={{
|
style={{
|
||||||
borderWidth: "1px",
|
borderWidth: "1px",
|
||||||
borderColor: getCstStatusFgColor(cst.status, colors),
|
borderColor: getCstStatusFgColor(cst.status, colors),
|
||||||
|
@ -251,7 +251,7 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
minSize: 150,
|
minSize: 150,
|
||||||
maxSize: 150,
|
maxSize: 150,
|
||||||
enableHiding: true,
|
enableHiding: true,
|
||||||
cell: props => <div className='text-sm min-w-[8.4rem]'>{props.getValue()}</div>
|
cell: props => <div className='text-sm min-w-[9.3rem] max-w-[9.3rem] break-words'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(cst => cst.term_resolved || cst.term_raw || '', {
|
columnHelper.accessor(cst => cst.term_resolved || cst.term_raw || '', {
|
||||||
id: 'term',
|
id: 'term',
|
||||||
|
@ -265,7 +265,8 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
header: 'Формальное определение',
|
header: 'Формальное определение',
|
||||||
size: 1000,
|
size: 1000,
|
||||||
minSize: 300,
|
minSize: 300,
|
||||||
maxSize: 1000
|
maxSize: 1000,
|
||||||
|
cell: props => <div className='break-words'>{props.getValue()}</div>
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor(cst => cst.definition_resolved || cst.definition_raw || '', {
|
columnHelper.accessor(cst => cst.definition_resolved || cst.definition_raw || '', {
|
||||||
id: 'definition',
|
id: 'definition',
|
||||||
|
@ -283,19 +284,14 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
maxSize: 500,
|
maxSize: 500,
|
||||||
enableHiding: true,
|
enableHiding: true,
|
||||||
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
cell: props => <div className='text-xs'>{props.getValue()}</div>
|
||||||
}),
|
})
|
||||||
], [colors]);
|
], [colors]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full'>
|
<div className='w-full'>
|
||||||
<div
|
<div className='sticky top-0 flex justify-start w-full gap-1 px-2 py-1 border-b items-center h-[2.2rem] select-none clr-app'>
|
||||||
className='sticky top-0 flex justify-start w-full gap-1 px-2 py-1 border-y items-center h-[2.2rem] select-none clr-app'
|
<div className='mr-3 min-w-[9rem] whitespace-nowrap'>
|
||||||
>
|
Выбор {selected.length} из {schema?.stats?.count_all ?? 0}
|
||||||
<div className='mr-3 whitespace-nowrap'>
|
|
||||||
Выбраны
|
|
||||||
<span className='ml-2'>
|
|
||||||
{selected.length} из {schema?.stats?.count_all ?? 0}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center justify-start w-full gap-1'>
|
<div className='flex items-center justify-start w-full gap-1'>
|
||||||
<Button
|
<Button
|
||||||
|
@ -342,7 +338,7 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
text={getCstTypePrefix(type)}
|
text={getCstTypePrefix(type)}
|
||||||
tooltip={getCstTypeShortcut(type)}
|
tooltip={getCstTypeShortcut(type)}
|
||||||
dense
|
dense
|
||||||
widthClass='w-[1.4rem]'
|
dimensions='w-[1.4rem]'
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onClick={() => handleCreateCst(type)}
|
onClick={() => handleCreateCst(type)}
|
||||||
|
@ -378,7 +374,8 @@ function EditorItems({ onOpenEdit, onCreateCst, onDeleteCst }: EditorItemsProps)
|
||||||
<p>Список пуст</p>
|
<p>Список пуст</p>
|
||||||
<p
|
<p
|
||||||
className='cursor-pointer text-primary hover:underline'
|
className='cursor-pointer text-primary hover:underline'
|
||||||
onClick={() => handleCreateCst()}>
|
onClick={() => handleCreateCst()}
|
||||||
|
>
|
||||||
Создать новую конституенту
|
Создать новую конституенту
|
||||||
</p>
|
</p>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -107,7 +107,8 @@ function EditorRSExpression({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const EditButtons = useMemo(() => {
|
const EditButtons = useMemo(() => {
|
||||||
return (<div className='flex items-center justify-between w-full'>
|
return (
|
||||||
|
<div className='flex items-center justify-between w-full'>
|
||||||
<div className='text-sm w-fit'>
|
<div className='text-sm w-fit'>
|
||||||
<div className='flex justify-start'>
|
<div className='flex justify-start'>
|
||||||
<RSTokenButton id={TokenID.NT_DECLARATIVE_EXPR} onInsert={handleEdit}/>
|
<RSTokenButton id={TokenID.NT_DECLARATIVE_EXPR} onInsert={handleEdit}/>
|
||||||
|
@ -185,55 +186,54 @@ function EditorRSExpression({
|
||||||
}, [handleEdit]);
|
}, [handleEdit]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-start [&:not(:first-child)]:mt-3 w-full min-h-[15.75rem]'>
|
<div className='flex flex-col items-start w-full min-h-[15.75rem]'>
|
||||||
<div className='relative w-full'>
|
<div className='relative w-full'>
|
||||||
<div className='absolute top-[-0.3rem] right-0'>
|
<div className='absolute top-[-0.3rem] right-0'>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
isModified={isModified}
|
isModified={isModified}
|
||||||
constituenta={activeCst}
|
constituenta={activeCst}
|
||||||
parseData={parseData}
|
parseData={parseData}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<RSInput innerref={rsInput}
|
|
||||||
className='text-lg'
|
|
||||||
height='10.1rem'
|
|
||||||
value={value}
|
|
||||||
editable={!disabled}
|
|
||||||
onChange={handleChange}
|
|
||||||
onFocus={handleFocusIn}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
<div className='flex w-full gap-4 py-1 mt-1 justify-stretch'>
|
|
||||||
<div className='flex flex-col gap-2'>
|
|
||||||
<Button
|
|
||||||
tooltip='Проверить формальное выражение'
|
|
||||||
text='Проверить'
|
|
||||||
widthClass='h-full w-fit'
|
|
||||||
colorClass='clr-btn-default'
|
|
||||||
onClick={handleCheckExpression}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{isActive && !disabled && EditButtons}
|
|
||||||
</div>
|
|
||||||
{ (isActive || loading || parseData) &&
|
|
||||||
<div className='w-full overflow-y-auto border mt-2 max-h-[14rem] min-h-[4.2rem]'>
|
|
||||||
{ loading && <ConceptLoader size={6} />}
|
|
||||||
{ !loading && parseData &&
|
|
||||||
<ParsingResult
|
|
||||||
data={parseData}
|
|
||||||
onShowAST={ast => onShowAST(getCstExpressionPrefix(activeCst!) + value, ast)}
|
|
||||||
onShowError={onShowError}
|
|
||||||
/>}
|
|
||||||
{ !loading && !parseData &&
|
|
||||||
<input
|
|
||||||
disabled={true}
|
|
||||||
className='w-full h-full px-2 align-middle select-none clr-app'
|
|
||||||
placeholder='Результаты проверки выражения'
|
|
||||||
/>}
|
|
||||||
</div>}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
|
<RSInput innerref={rsInput}
|
||||||
|
className='text-lg'
|
||||||
|
height='10.1rem'
|
||||||
|
value={value}
|
||||||
|
editable={!disabled}
|
||||||
|
onChange={handleChange}
|
||||||
|
onFocus={handleFocusIn}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<div className='flex items-stretch w-full gap-4 py-1 mt-1 justify-stretch'>
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
tooltip='Проверить формальное выражение'
|
||||||
|
text='Проверить'
|
||||||
|
dimensions='h-full w-fit'
|
||||||
|
colorClass='clr-btn-default'
|
||||||
|
onClick={handleCheckExpression}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{isActive && !disabled && EditButtons}
|
||||||
|
</div>
|
||||||
|
{ (isActive || loading || parseData) &&
|
||||||
|
<div className='w-full overflow-y-auto border mt-1 max-h-[14rem] min-h-[4.2rem]'>
|
||||||
|
{ loading && <ConceptLoader size={6} />}
|
||||||
|
{ !loading && parseData &&
|
||||||
|
<ParsingResult
|
||||||
|
data={parseData}
|
||||||
|
onShowAST={ast => onShowAST(getCstExpressionPrefix(activeCst!) + value, ast)}
|
||||||
|
onShowError={onShowError}
|
||||||
|
/>}
|
||||||
|
{ !loading && !parseData &&
|
||||||
|
<input
|
||||||
|
disabled={true}
|
||||||
|
className='w-full h-full px-2 align-middle select-none clr-app'
|
||||||
|
placeholder='Результаты проверки выражения'
|
||||||
|
/>}
|
||||||
|
</div>}
|
||||||
|
</div>);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EditorRSExpression;
|
export default EditorRSExpression;
|
||||||
|
|
|
@ -13,8 +13,8 @@ import { CrownIcon, DownloadIcon, DumpBinIcon, HelpIcon, SaveIcon, ShareIcon } f
|
||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { useRSForm } from '../../context/RSFormContext';
|
import { useRSForm } from '../../context/RSFormContext';
|
||||||
import { useUsers } from '../../context/UsersContext';
|
import { useUsers } from '../../context/UsersContext';
|
||||||
import { IRSFormCreateData } from '../../models/rsform';
|
|
||||||
import { LibraryItemType } from '../../models/library';
|
import { LibraryItemType } from '../../models/library';
|
||||||
|
import { IRSFormCreateData } from '../../models/rsform';
|
||||||
|
|
||||||
interface EditorRSFormProps {
|
interface EditorRSFormProps {
|
||||||
onDestroy: () => void
|
onDestroy: () => void
|
||||||
|
@ -81,39 +81,40 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className='flex-grow max-w-[35.3rem] px-4 py-2 border-y border-r min-w-fit'>
|
<form onSubmit={handleSubmit} className='flex-grow max-w-[35.3rem] px-4 py-2 border-y border-r min-w-fit'>
|
||||||
<div className='relative w-full'>
|
<div className='relative w-full'>
|
||||||
<div className='absolute top-0 right-0 flex'>
|
<div className='absolute top-0 right-0 flex'>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Поделиться схемой'
|
tooltip='Поделиться схемой'
|
||||||
icon={<ShareIcon size={5} color='text-primary'/>}
|
icon={<ShareIcon size={5} color='text-primary'/>}
|
||||||
onClick={onShare}
|
onClick={onShare}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Скачать TRS файл'
|
tooltip='Скачать TRS файл'
|
||||||
icon={<DownloadIcon size={5} color='text-primary'/>}
|
icon={<DownloadIcon size={5} color='text-primary'/>}
|
||||||
onClick={onDownload}
|
onClick={onDownload}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip={isClaimable ? 'Стать владельцем' : 'Невозможно стать владельцем' }
|
tooltip={isClaimable ? 'Стать владельцем' : 'Невозможно стать владельцем' }
|
||||||
icon={<CrownIcon size={5} color={!isClaimable ? '' : 'text-success'}/>}
|
icon={<CrownIcon size={5} color={!isClaimable ? '' : 'text-success'}/>}
|
||||||
disabled={!isClaimable || !user}
|
disabled={!isClaimable || !user}
|
||||||
onClick={onClaim}
|
onClick={onClaim}
|
||||||
/>
|
/>
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Удалить схему'
|
tooltip='Удалить схему'
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
onClick={onDestroy}
|
onClick={onDestroy}
|
||||||
icon={<DumpBinIcon size={5} color={isEditable ? 'text-warning' : ''} />}
|
icon={<DumpBinIcon size={5} color={isEditable ? 'text-warning' : ''} />}
|
||||||
/>
|
/>
|
||||||
<div id='rsform-help' className='py-1 ml-1'>
|
<div id='rsform-help' className='py-1 ml-1'>
|
||||||
<HelpIcon color='text-primary' size={5} />
|
<HelpIcon color='text-primary' size={5} />
|
||||||
</div>
|
|
||||||
<ConceptTooltip anchorSelect='#rsform-help'>
|
|
||||||
<HelpRSFormMeta />
|
|
||||||
</ConceptTooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<ConceptTooltip anchorSelect='#rsform-help'>
|
||||||
|
<HelpRSFormMeta />
|
||||||
|
</ConceptTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col gap-3 mt-2'>
|
||||||
<TextInput id='title' label='Полное название' type='text'
|
<TextInput id='title' label='Полное название' type='text'
|
||||||
required
|
required
|
||||||
value={title}
|
value={title}
|
||||||
|
@ -124,7 +125,7 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
required
|
required
|
||||||
value={alias}
|
value={alias}
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
widthClass='max-w-sm'
|
dimensions='max-w-sm'
|
||||||
onChange={event => setAlias(event.target.value)}
|
onChange={event => setAlias(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<TextArea id='comment' label='Комментарий'
|
<TextArea id='comment' label='Комментарий'
|
||||||
|
@ -135,12 +136,12 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
<div className='flex justify-between whitespace-nowrap'>
|
<div className='flex justify-between whitespace-nowrap'>
|
||||||
<Checkbox id='common' label='Общедоступная схема'
|
<Checkbox id='common' label='Общедоступная схема'
|
||||||
value={common}
|
value={common}
|
||||||
widthClass='w-fit mt-3'
|
dimensions='w-fit'
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
setValue={value => setCommon(value)}
|
setValue={value => setCommon(value)}
|
||||||
/>
|
/>
|
||||||
<Checkbox id='canonical' label='Неизменная схема'
|
<Checkbox id='canonical' label='Неизменная схема'
|
||||||
widthClass='w-fit'
|
dimensions='w-fit'
|
||||||
value={canonical}
|
value={canonical}
|
||||||
tooltip='Только администраторы могут присваивать схемам неизменный статус'
|
tooltip='Только администраторы могут присваивать схемам неизменный статус'
|
||||||
disabled={!isEditable || !isForceAdmin}
|
disabled={!isEditable || !isForceAdmin}
|
||||||
|
@ -148,36 +149,38 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-center justify-between gap-1 py-2 mt-2'>
|
<SubmitButton
|
||||||
<SubmitButton
|
text='Сохранить изменения'
|
||||||
text='Сохранить изменения'
|
loading={processing}
|
||||||
loading={processing}
|
disabled={!isModified || !isEditable}
|
||||||
disabled={!isModified || !isEditable}
|
icon={<SaveIcon size={6} />}
|
||||||
icon={<SaveIcon size={6} />}
|
dimensions='my-2 w-fit'
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex justify-start mt-2'>
|
<div className='flex flex-col gap-1'>
|
||||||
<label className='font-semibold'>Владелец:</label>
|
<div className='flex justify-start'>
|
||||||
<span className='min-w-[200px] ml-2 overflow-ellipsis overflow-hidden whitespace-nowrap'>
|
<label className='font-semibold'>Владелец:</label>
|
||||||
{getUserLabel(schema?.owner ?? null)}
|
<span className='min-w-[200px] ml-2 overflow-ellipsis overflow-hidden whitespace-nowrap'>
|
||||||
</span>
|
{getUserLabel(schema?.owner ?? null)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
<label className='font-semibold'>Отслеживают:</label>
|
||||||
|
<span id='subscriber-count' className='ml-2'>
|
||||||
|
{ schema?.subscribers.length ?? 0 }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
<label className='font-semibold'>Дата обновления:</label>
|
||||||
|
<span className='ml-2'>{schema && new Date(schema?.time_update).toLocaleString(intl.locale)}</span>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-start'>
|
||||||
|
<label className='font-semibold'>Дата создания:</label>
|
||||||
|
<span className='ml-8'>{schema && new Date(schema?.time_create).toLocaleString(intl.locale)}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-start mt-2'>
|
</div>
|
||||||
<label className='font-semibold'>Отслеживают:</label>
|
</form>
|
||||||
<span id='subscriber-count' className='ml-2'>
|
|
||||||
{ schema?.subscribers.length ?? 0 }
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start mt-2'>
|
|
||||||
<label className='font-semibold'>Дата обновления:</label>
|
|
||||||
<span className='ml-2'>{schema && new Date(schema?.time_update).toLocaleString(intl.locale)}</span>
|
|
||||||
</div>
|
|
||||||
<div className='flex justify-start mt-2'>
|
|
||||||
<label className='font-semibold'>Дата создания:</label>
|
|
||||||
<span className='ml-8'>{schema && new Date(schema?.time_create).toLocaleString(intl.locale)}</span>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -376,25 +376,22 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
<div className='flex items-center justify-between py-1'>
|
<div className='flex items-center justify-between py-1'>
|
||||||
<div className='mr-3 whitespace-nowrap text-base'>
|
<div className='mr-3 text-base'>
|
||||||
Выбраны
|
Выбор {allSelected.length} из {schema?.stats?.count_all ?? 0}
|
||||||
<span className='ml-1'>
|
|
||||||
{allSelected.length} из {schema?.stats?.count_all ?? 0}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className='min-w-fit'>
|
||||||
<MiniButton
|
|
||||||
tooltip='Удалить выбранные'
|
|
||||||
icon={<DumpBinIcon color={!nothingSelected ? 'text-warning' : ''} size={5}/>}
|
|
||||||
disabled={!isEditable || nothingSelected}
|
|
||||||
onClick={handleDeleteCst}
|
|
||||||
/>
|
|
||||||
<MiniButton
|
<MiniButton
|
||||||
tooltip='Новая конституента'
|
tooltip='Новая конституента'
|
||||||
icon={<SmallPlusIcon color='text-success' size={5}/>}
|
icon={<SmallPlusIcon color={isEditable ? 'text-success': ''} size={5}/>}
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
onClick={handleCreateCst}
|
onClick={handleCreateCst}
|
||||||
/>
|
/>
|
||||||
|
<MiniButton
|
||||||
|
tooltip='Удалить выбранные'
|
||||||
|
icon={<DumpBinIcon color={isEditable && !nothingSelected ? 'text-warning' : ''} size={5}/>}
|
||||||
|
disabled={!isEditable || nothingSelected}
|
||||||
|
onClick={handleDeleteCst}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center w-full gap-1'>
|
<div className='flex items-center w-full gap-1'>
|
||||||
|
@ -402,7 +399,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
icon={<FilterCogIcon size={7} />}
|
icon={<FilterCogIcon size={7} />}
|
||||||
dense
|
dense
|
||||||
tooltip='Настройки фильтрации узлов и связей'
|
tooltip='Настройки фильтрации узлов и связей'
|
||||||
widthClass='h-full'
|
dimensions='h-full'
|
||||||
onClick={() => setShowOptions(true)}
|
onClick={() => setShowOptions(true)}
|
||||||
/>
|
/>
|
||||||
<SelectSingle
|
<SelectSingle
|
||||||
|
@ -423,6 +420,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
value={layout ? { value: layout, label: mapLayoutLabels.get(layout) } : null}
|
value={layout ? { value: layout, label: mapLayoutLabels.get(layout) } : null}
|
||||||
onChange={data => handleChangeLayout(data?.value ?? SelectorGraphLayout[0].value)}
|
onChange={data => handleChangeLayout(data?.value ?? SelectorGraphLayout[0].value)}
|
||||||
/>
|
/>
|
||||||
|
<div className='flex flex-col gap-1 mt-2'>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label='Скрыть текст'
|
label='Скрыть текст'
|
||||||
value={noTerms}
|
value={noTerms}
|
||||||
|
@ -439,6 +437,7 @@ function EditorTermGraph({ onOpenEdit, onCreateCst, onDeleteCst }: EditorTermGra
|
||||||
value={orbit}
|
value={orbit}
|
||||||
setValue={ value => setOrbit(value) }
|
setValue={ value => setOrbit(value) }
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Divider margins='mt-3 mb-2' />
|
<Divider margins='mt-3 mb-2' />
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ function RSTabsMenu({
|
||||||
tooltip='Действия'
|
tooltip='Действия'
|
||||||
icon={<MenuIcon color='text-controls' size={5}/>}
|
icon={<MenuIcon color='text-controls' size={5}/>}
|
||||||
borderClass=''
|
borderClass=''
|
||||||
widthClass='h-full w-fit'
|
dimensions='h-full w-fit'
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
dense
|
dense
|
||||||
onClick={schemaMenu.toggle}
|
onClick={schemaMenu.toggle}
|
||||||
|
@ -123,7 +123,7 @@ function RSTabsMenu({
|
||||||
<Button
|
<Button
|
||||||
tooltip={'измнение: ' + (isEditable ? '[доступно]' : '[запрещено]')}
|
tooltip={'измнение: ' + (isEditable ? '[доступно]' : '[запрещено]')}
|
||||||
borderClass=''
|
borderClass=''
|
||||||
widthClass='h-full w-fit'
|
dimensions='h-full w-fit'
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
icon={<PenIcon size={5} color={isEditable ? 'text-success' : 'text-warning'}/>}
|
icon={<PenIcon size={5} color={isEditable ? 'text-success' : 'text-warning'}/>}
|
||||||
dense
|
dense
|
||||||
|
@ -169,7 +169,7 @@ function RSTabsMenu({
|
||||||
? <EyeIcon color='text-primary' size={5}/>
|
? <EyeIcon color='text-primary' size={5}/>
|
||||||
: <EyeOffIcon color='text-controls' size={5}/>
|
: <EyeOffIcon color='text-controls' size={5}/>
|
||||||
}
|
}
|
||||||
widthClass='h-full w-fit'
|
dimensions='h-full w-fit'
|
||||||
borderClass=''
|
borderClass=''
|
||||||
style={{outlineColor: 'transparent'}}
|
style={{outlineColor: 'transparent'}}
|
||||||
dense
|
dense
|
||||||
|
|
|
@ -17,7 +17,7 @@ function RSTokenButton({ id, disabled, onInsert }: RSTokenButtonProps) {
|
||||||
onClick={() => onInsert(id)}
|
onClick={() => onInsert(id)}
|
||||||
title={data.tooltip}
|
title={data.tooltip}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={`px-1 cursor-pointer border rounded-none h-7 ${width} clr-outline clr-btn-clear`}
|
className={`px-1 cursor-pointer border rounded-none h-7 ${width} clr-outline clr-hover clr-btn-clear`}
|
||||||
>
|
>
|
||||||
{data.text && <span className='whitespace-nowrap'>{data.text}</span>}
|
{data.text && <span className='whitespace-nowrap'>{data.text}</span>}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -121,7 +121,7 @@ function ViewSideConstituents({ expression, baseHeight, activeID, onOpenEdit }:
|
||||||
return (<>
|
return (<>
|
||||||
<div
|
<div
|
||||||
id={`${prefixes.cst_list}${cst.alias}`}
|
id={`${prefixes.cst_list}${cst.alias}`}
|
||||||
className='w-full px-1 text-center rounded-md whitespace-nowrap'
|
className='min-w-[3.1rem] max-w-[3.1rem] px-1 text-center rounded-md whitespace-nowrap'
|
||||||
style={{
|
style={{
|
||||||
borderWidth: '1px',
|
borderWidth: '1px',
|
||||||
borderColor: getCstStatusFgColor(cst.status, colors),
|
borderColor: getCstStatusFgColor(cst.status, colors),
|
||||||
|
|
|
@ -61,7 +61,7 @@ function RegisterPage() {
|
||||||
<Form
|
<Form
|
||||||
title='Регистрация'
|
title='Регистрация'
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
widthClass='w-[24rem]'
|
dimensions='w-[24rem]'
|
||||||
>
|
>
|
||||||
<TextInput id='username' label='Имя пользователя' type='text'
|
<TextInput id='username' label='Имя пользователя' type='text'
|
||||||
required
|
required
|
||||||
|
@ -104,12 +104,12 @@ function RegisterPage() {
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
text='Регистрировать'
|
text='Регистрировать'
|
||||||
loading={loading}
|
loading={loading}
|
||||||
widthClass='min-w-[10rem]'
|
dimensions='min-w-[10rem]'
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
text='Отмена'
|
text='Отмена'
|
||||||
onClick={() => handleCancel()}
|
onClick={() => handleCancel()}
|
||||||
widthClass='min-w-[10rem]'
|
dimensions='min-w-[10rem]'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ error && <BackendError error={error} />}
|
{ error && <BackendError error={error} />}
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
|
import axios from 'axios';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import BackendError from '../../components/BackendError';
|
import BackendError, { ErrorInfo } from '../../components/BackendError';
|
||||||
import SubmitButton from '../../components/Common/SubmitButton';
|
import SubmitButton from '../../components/Common/SubmitButton';
|
||||||
import TextInput from '../../components/Common/TextInput';
|
import TextInput from '../../components/Common/TextInput';
|
||||||
import { useAuth } from '../../context/AuthContext';
|
import { useAuth } from '../../context/AuthContext';
|
||||||
import { useConceptNavigation } from '../../context/NagivationContext';
|
import { useConceptNavigation } from '../../context/NagivationContext';
|
||||||
import { IUserUpdatePassword } from '../../models/library';
|
import { IUserUpdatePassword } from '../../models/library';
|
||||||
|
|
||||||
|
function ProcessError({error}: {error: ErrorInfo}): React.ReactElement {
|
||||||
|
if (axios.isAxiosError(error) && error.response && error.response.status === 400) {
|
||||||
|
return (
|
||||||
|
<div className='text-sm select-text text-warning'>
|
||||||
|
Неверно введен старый пароль
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (<BackendError error={error} />);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function EditorPassword() {
|
function EditorPassword() {
|
||||||
const { navigateTo } = useConceptNavigation();
|
const { navigateTo } = useConceptNavigation();
|
||||||
|
@ -50,7 +62,7 @@ function EditorPassword() {
|
||||||
return (
|
return (
|
||||||
<div className='flex py-2 border-l-2 max-w-[14rem]'>
|
<div className='flex py-2 border-l-2 max-w-[14rem]'>
|
||||||
<form onSubmit={handleSubmit} className='flex flex-col justify-between px-6 min-w-fit'>
|
<form onSubmit={handleSubmit} className='flex flex-col justify-between px-6 min-w-fit'>
|
||||||
<div>
|
<div className='flex flex-col gap-3'>
|
||||||
<TextInput id='old_password'
|
<TextInput id='old_password'
|
||||||
type='password'
|
type='password'
|
||||||
label='Старый пароль'
|
label='Старый пароль'
|
||||||
|
@ -74,7 +86,7 @@ function EditorPassword() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ error && <BackendError error={error} />}
|
{ error && <ProcessError error={error} />}
|
||||||
<div className='flex justify-center w-full'>
|
<div className='flex justify-center w-full'>
|
||||||
<SubmitButton
|
<SubmitButton
|
||||||
disabled={!canSubmit}
|
disabled={!canSubmit}
|
||||||
|
|
|
@ -50,33 +50,31 @@ function EditorProfile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex py-2'>
|
<form onSubmit={handleSubmit} className='px-6 py-2 flex flex-col gap-8 min-w-[18rem]'>
|
||||||
<form onSubmit={handleSubmit} className='px-6 min-w-[18rem]'>
|
<div className='flex flex-col gap-3'>
|
||||||
<div>
|
<TextInput id='username'
|
||||||
<TextInput id='username'
|
label='Логин'
|
||||||
label='Логин'
|
tooltip='Логин изменить нельзя'
|
||||||
tooltip='Логин изменить нельзя'
|
disabled={true}
|
||||||
disabled={true}
|
value={username}
|
||||||
value={username}
|
onChange={event => setUsername(event.target.value)}
|
||||||
onChange={event => setUsername(event.target.value)}
|
/>
|
||||||
/>
|
<TextInput id='first_name'
|
||||||
<TextInput id='first_name'
|
label='Имя'
|
||||||
label='Имя'
|
value={first_name}
|
||||||
value={first_name}
|
onChange={event => setFirstName(event.target.value)}
|
||||||
onChange={event => setFirstName(event.target.value)}
|
/>
|
||||||
/>
|
<TextInput id='last_name' label='Фамилия' value={last_name} onChange={event => setLastName(event.target.value)}/>
|
||||||
<TextInput id='last_name' label='Фамилия' value={last_name} onChange={event => setLastName(event.target.value)}/>
|
<TextInput id='email' label='Электронная почта' value={email} onChange={event => setEmail(event.target.value)}/>
|
||||||
<TextInput id='email' label='Электронная почта' value={email} onChange={event => setEmail(event.target.value)}/>
|
</div>
|
||||||
</div>
|
<div className='flex justify-center w-full'>
|
||||||
<div className='flex justify-center w-full mt-10'>
|
<SubmitButton
|
||||||
<SubmitButton
|
text='Сохранить данные'
|
||||||
text='Сохранить данные'
|
loading={processing}
|
||||||
loading={processing}
|
disabled={!isModified}
|
||||||
disabled={!isModified}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -458,7 +458,7 @@ export function getTypificationLabel({isValid, resultType, args}: {
|
||||||
return 'N/A';
|
return 'N/A';
|
||||||
}
|
}
|
||||||
if (resultType === '' || resultType === 'LOGIC') {
|
if (resultType === '' || resultType === 'LOGIC') {
|
||||||
resultType = 'Логический';
|
resultType = 'Logical';
|
||||||
}
|
}
|
||||||
if (args.length === 0) {
|
if (args.length === 0) {
|
||||||
return resultType;
|
return resultType;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user