UI improvements

This commit is contained in:
IRBorisov 2023-11-10 15:34:59 +03:00
parent 3f4f9b03dc
commit c71bfbef34
15 changed files with 70 additions and 68 deletions

View File

@ -10,7 +10,7 @@ extends Omit<TabProps, 'className' | 'title'> {
function ConceptTab({ children, tooltip, className, ...otherProps }: ConceptTabProps) { function ConceptTab({ children, tooltip, className, ...otherProps }: ConceptTabProps) {
return ( return (
<Tab <Tab
className={`px-2 py-1 h-full text-sm hover:cursor-pointer clr-tab whitespace-nowrap ${className}`} className={`px-2 py-1 h-full flex justify-center text-sm hover:cursor-pointer clr-tab whitespace-nowrap min-w-[6rem] ${className}`}
title={tooltip} title={tooltip}
{...otherProps} {...otherProps}
> >

View File

@ -5,7 +5,7 @@ interface DividerProps {
function Divider({ vertical, margins = 'mx-2' }: DividerProps) { function Divider({ vertical, margins = 'mx-2' }: DividerProps) {
return ( return (
<div className={`${margins} ${vertical ? 'border-x-2 h-full': 'border-y-2 w-full'}`} /> <div className={`${margins} ${vertical ? 'border-x h-full': 'border-y w-full'}`} />
); );
} }

View File

@ -7,12 +7,13 @@ interface DropdownButtonProps {
function DropdownButton({ tooltip, onClick, disabled, children }: DropdownButtonProps) { function DropdownButton({ tooltip, onClick, disabled, children }: DropdownButtonProps) {
const behavior = (onClick ? 'cursor-pointer disabled:cursor-not-allowed clr-hover' : 'cursor-default'); const behavior = (onClick ? 'cursor-pointer disabled:cursor-not-allowed clr-hover' : 'cursor-default');
const text = disabled ? 'text-controls' : '';
return ( return (
<button <button
disabled={disabled} disabled={disabled}
title={tooltip} title={tooltip}
onClick={onClick} onClick={onClick}
className={`px-3 py-1 text-left overflow-ellipsis ${behavior} whitespace-nowrap`} className={`px-3 py-1 text-left overflow-ellipsis whitespace-nowrap ${behavior} ${text}`}
> >
{children} {children}
</button> </button>

View File

@ -9,10 +9,10 @@ extends IEditorProps, IColorsProps, Omit<TextareaHTMLAttributes<HTMLTextAreaElem
} }
function TextArea({ function TextArea({
id, label, required, tooltip, dense, noBorder, noOutline, id, label, required, tooltip, rows,
dense, noBorder, noOutline,
dimensions = 'w-full', dimensions = 'w-full',
colors = 'clr-input', colors = 'clr-input',
rows = 4,
...props ...props
}: TextAreaProps) { }: TextAreaProps) {
const borderClass = noBorder ? '': 'border'; const borderClass = noBorder ? '': 'border';

View File

@ -56,7 +56,8 @@ extends Pick<ReactCodeMirrorProps,
} }
function RSInput({ function RSInput({
id, label, innerref, onChange, disabled, noTooltip, id, label, innerref, onChange,
disabled, noTooltip,
dimensions = 'w-full', dimensions = 'w-full',
...props ...props
}: RSInputProps) { }: RSInputProps) {

View File

@ -72,7 +72,7 @@ function ConstituentaPicker({
}) })
], [colors, prefixID, describeFunc]); ], [colors, prefixID, describeFunc]);
const size = useMemo(() => (`${0.125 + 1.94*rows}rem`), [rows]); const size = useMemo(() => (`calc(2px + (2px + 1.8rem)*${rows})`), [rows]);
const conditionalRowStyles = useMemo( const conditionalRowStyles = useMemo(
(): IConditionalStyle<IConstituenta>[] => [{ (): IConditionalStyle<IConstituenta>[] => [{

View File

@ -158,7 +158,7 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
<MiniButton <MiniButton
tooltip='Подставить значение аргумента' tooltip='Подставить значение аргумента'
icon={<CheckIcon icon={<CheckIcon
size={6} size={5}
color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'} color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'}
/>} />}
disabled={!argumentValue || !selectedArgument} disabled={!argumentValue || !selectedArgument}
@ -177,6 +177,7 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
<RSInput id='result' <RSInput id='result'
placeholder='Итоговое определение' placeholder='Итоговое определение'
height='5.1rem' height='5.1rem'
dimensions='w-full mt-[0.45rem]'
value={state.definition} value={state.definition}
disabled disabled
/> />

View File

@ -86,35 +86,37 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
return ( return (
<div className='flex flex-col gap-3'> <div className='flex flex-col gap-3'>
<div className='flex justify-between gap-3'> <div>
<SelectSingle <div className='flex justify-between gap-6'>
className='w-full' <SelectSingle
options={categorySelector} className='w-full'
placeholder='Выберите категорию' options={categorySelector}
value={state.filterCategory && selectedSchema ? { placeholder='Выберите категорию'
value: state.filterCategory.id, value={state.filterCategory && selectedSchema ? {
label: state.filterCategory.term_raw value: state.filterCategory.id,
} : null} label: state.filterCategory.term_raw
onChange={data => partialUpdate({filterCategory: selectedSchema?.items.find(cst => cst.id === data?.value) })} } : null}
isClearable onChange={data => partialUpdate({filterCategory: selectedSchema?.items.find(cst => cst.id === data?.value) })}
/> isClearable
<SelectSingle />
className='min-w-[15rem]' <SelectSingle
options={templateSelector} className='min-w-[15rem]'
placeholder='Выберите источник' options={templateSelector}
value={state.templateID ? { value: state.templateID, label: templates.find(item => item.id == state.templateID)!.title }: null} placeholder='Выберите источник'
onChange={data => partialUpdate({templateID: (data ? data.value : undefined)})} value={state.templateID ? { value: state.templateID, label: templates.find(item => item.id == state.templateID)!.title }: null}
onChange={data => partialUpdate({templateID: (data ? data.value : undefined)})}
/>
</div>
<ConstituentaPicker
value={state.prototype}
data={filteredData}
onSelectValue={cst => partialUpdate( { prototype: cst } )}
prefixID={prefixes.cst_template_ist}
rows={9}
/> />
</div> </div>
<ConstituentaPicker
value={state.prototype}
data={filteredData}
onSelectValue={cst => partialUpdate( { prototype: cst } )}
prefixID={prefixes.cst_template_ist}
rows={9}
/>
<TextArea id='term' <TextArea id='term'
rows={1} rows={2}
disabled disabled
placeholder='Шаблон конституенты не выбран' placeholder='Шаблон конституенты не выбран'
value={prototypeInfo} value={prototypeInfo}

View File

@ -239,9 +239,13 @@ function EditorConstituenta({
/> />
<TextArea id='typification' label='Типизация' <TextArea id='typification' label='Типизация'
dense noBorder dense noBorder
rows={1} rows={typification.length > 70 ? 2 : 1}
value={typification} value={typification}
colors='clr-app' colors='clr-app'
dimensions='w-full'
style={{
resize: 'none'
}}
disabled disabled
/> />
<EditorRSExpression id='expression' label='Формальное определение' <EditorRSExpression id='expression' label='Формальное определение'
@ -265,7 +269,6 @@ function EditorConstituenta({
/> />
<TextArea id='convention' label='Конвенция / Комментарий' <TextArea id='convention' label='Конвенция / Комментарий'
placeholder='Договоренность об интерпретации или пояснение' placeholder='Договоренность об интерпретации или пояснение'
rows={2}
value={convention} value={convention}
disabled={!isEnabled} disabled={!isEnabled}
spellCheck spellCheck

View File

@ -130,7 +130,7 @@ function EditorRSExpression({
</div> </div>
<RSInput innerref={rsInput} <RSInput innerref={rsInput}
value={value} value={value}
minHeight='3.5rem' minHeight='3.8rem'
disabled={disabled} disabled={disabled}
onChange={handleChange} onChange={handleChange}
{...props} {...props}
@ -139,12 +139,12 @@ function EditorRSExpression({
disabled={disabled} disabled={disabled}
onEdit={handleEdit} onEdit={handleEdit}
/> />
<div className='w-full max-h-[5rem] min-h-[5rem] flex'> <div className='w-full max-h-[4.5rem] min-h-[4.5rem] flex'>
<div className='flex flex-col'> <div className='flex flex-col text-sm'>
<Button <Button
tooltip='Проверить формальное определение' tooltip='Проверить формальное определение'
text='Проверить' text='Проверить'
dimensions='w-fit h-[3rem] z-pop rounded-none' dimensions='w-[6.75rem] min-h-[3rem] z-pop rounded-none'
colors='clr-btn-default' colors='clr-btn-default'
noOutline noOutline
onClick={() => handleCheckExpression()} onClick={() => handleCheckExpression()}

View File

@ -97,6 +97,12 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
<div tabIndex={-1} onKeyDown={handleInput}> <div tabIndex={-1} onKeyDown={handleInput}>
<div className='relative flex items-start justify-center w-full'> <div className='relative flex items-start justify-center w-full'>
<div className='absolute flex mt-1'> <div className='absolute flex mt-1'>
<MiniButton
tooltip='Сохранить изменения'
disabled={!isModified || !isEditable}
icon={<SaveIcon size={5} color={isModified && isEditable ? 'text-primary' : ''}/>}
onClick={() => handleSubmit()}
/>
<MiniButton <MiniButton
tooltip='Поделиться схемой' tooltip='Поделиться схемой'
icon={<ShareIcon size={5} color='text-primary'/>} icon={<ShareIcon size={5} color='text-primary'/>}
@ -165,14 +171,15 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
setValue={value => setCanonical(value)} setValue={value => setCanonical(value)}
/> />
</div> </div>
<div className='flex justify-center w-full'>
<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' dimensions='my-2 w-fit'
/> />
</div>
<div className='flex flex-col gap-1'> <div className='flex flex-col gap-1'>
<div className='flex justify-start'> <div className='flex justify-start'>

View File

@ -394,7 +394,6 @@ function RSTabs() {
onClaim={onClaimSchema} onClaim={onClaimSchema}
onShare={onShareSchema} onShare={onShareSchema}
onToggleSubscribe={handleToggleSubscribe} onToggleSubscribe={handleToggleSubscribe}
onTemplates={onShowTemplates}
showCloneDialog={promptClone} showCloneDialog={promptClone}
showUploadDialog={() => setShowUpload(true)} showUploadDialog={() => setShowUpload(true)}
/> />
@ -402,13 +401,13 @@ function RSTabs() {
className='border-x-2' className='border-x-2'
tooltip={`Название схемы: ${schema.title ?? ''}`} tooltip={`Название схемы: ${schema.title ?? ''}`}
> >
Паспорт схемы Карточка
</ConceptTab> </ConceptTab>
<ConceptTab <ConceptTab
className='border-r-2' className='border-r-2'
tooltip={`Всего конституент: ${schema.stats?.count_all ?? 0}\nКоличество ошибок: ${schema.stats?.count_errors ?? 0}`} tooltip={`Всего конституент: ${schema.stats?.count_all ?? 0}\nКоличество ошибок: ${schema.stats?.count_errors ?? 0}`}
> >
Конституенты Содержание
</ConceptTab> </ConceptTab>
<ConceptTab className='border-r-2'> <ConceptTab className='border-r-2'>
Редактор Редактор

View File

@ -12,7 +12,7 @@ function ParsingResult({ data, onShowError }: ParsingResultProps) {
const warningsCount = data.errors.length - errorCount; const warningsCount = data.errors.length - errorCount;
return ( return (
<div className='px-3 py-2'> <div className='px-2 py-1'>
<p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p> <p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p>
{data.errors.map((error, index) => { {data.errors.map((error, index) => {
return ( return (

View File

@ -81,7 +81,7 @@ function RSFormStats({ stats }: RSFormStatsProps) {
/>} />}
{ stats.count_theorem > 0 && { stats.count_theorem > 0 &&
<LabeledText id='count_theorem' <LabeledText id='count_theorem'
label='Теормы ' label='Теоремы '
text={stats.count_theorem} text={stats.count_theorem}
/>} />}
</div> </div>

View File

@ -5,7 +5,7 @@ import Dropdown from '../../../components/Common/Dropdown';
import DropdownButton from '../../../components/Common/DropdownButton'; import DropdownButton from '../../../components/Common/DropdownButton';
import DropdownCheckbox from '../../../components/Common/DropdownCheckbox'; import DropdownCheckbox from '../../../components/Common/DropdownCheckbox';
import { import {
CloneIcon, DiamondIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon, CloneIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon,
OwnerIcon, ShareIcon, SmallPlusIcon, SubscribedIcon, UploadIcon OwnerIcon, ShareIcon, SmallPlusIcon, SubscribedIcon, UploadIcon
} from '../../../components/Icons'; } from '../../../components/Icons';
import { useAuth } from '../../../context/AuthContext'; import { useAuth } from '../../../context/AuthContext';
@ -20,12 +20,11 @@ interface RSTabsMenuProps {
onShare: () => void onShare: () => void
onDownload: () => void onDownload: () => void
onToggleSubscribe: () => void onToggleSubscribe: () => void
onTemplates: () => void
} }
function RSTabsMenu({ function RSTabsMenu({
showUploadDialog, showCloneDialog, showUploadDialog, showCloneDialog,
onDestroy, onShare, onDownload, onClaim, onToggleSubscribe, onTemplates onDestroy, onShare, onDownload, onClaim, onToggleSubscribe
}: RSTabsMenuProps) { }: RSTabsMenuProps) {
const navigate = useNavigate(); const navigate = useNavigate();
const { user } = useAuth(); const { user } = useAuth();
@ -45,11 +44,6 @@ function RSTabsMenu({
schemaMenu.hide(); schemaMenu.hide();
onDestroy(); onDestroy();
} }
function handleTemplates() {
schemaMenu.hide();
onTemplates();
}
function handleDownload () { function handleDownload () {
schemaMenu.hide(); schemaMenu.hide();
@ -102,12 +96,6 @@ function RSTabsMenu({
<p>Клонировать</p> <p>Клонировать</p>
</div> </div>
</DropdownButton> </DropdownButton>
<DropdownButton onClick={handleTemplates} disabled={!isEditable} >
<div className='inline-flex items-center justify-start gap-2'>
<DiamondIcon color={isEditable ? 'text-success' : ''} size={4}/>
<p>Банк выражений</p>
</div>
</DropdownButton>
<DropdownButton onClick={handleDownload}> <DropdownButton onClick={handleDownload}>
<div className='inline-flex items-center justify-start gap-2'> <div className='inline-flex items-center justify-start gap-2'>
<DownloadIcon color='text-primary' size={4}/> <DownloadIcon color='text-primary' size={4}/>
@ -150,7 +138,7 @@ function RSTabsMenu({
<DropdownButton <DropdownButton
disabled={!user || !isClaimable} disabled={!user || !isClaimable}
onClick={!isOwned ? handleClaimOwner : undefined} onClick={!isOwned ? handleClaimOwner : undefined}
tooltip={!user || !isClaimable ? 'Стать владельцем можно только для общей изменяемой схемы' : ''} tooltip={!user || !isClaimable ? 'Взять во владение можно общую изменяемую схему' : ''}
> >
<div className='flex items-center gap-2 pl-1'> <div className='flex items-center gap-2 pl-1'>
<span><OwnerIcon size={5} color={isOwned ? 'text-success' : 'text-controls'} /></span> <span><OwnerIcon size={5} color={isOwned ? 'text-success' : 'text-controls'} /></span>