mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
UI improvements
This commit is contained in:
parent
3f4f9b03dc
commit
c71bfbef34
|
@ -10,7 +10,7 @@ extends Omit<TabProps, 'className' | 'title'> {
|
|||
function ConceptTab({ children, tooltip, className, ...otherProps }: ConceptTabProps) {
|
||||
return (
|
||||
<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}
|
||||
{...otherProps}
|
||||
>
|
||||
|
|
|
@ -5,7 +5,7 @@ interface DividerProps {
|
|||
|
||||
function Divider({ vertical, margins = 'mx-2' }: DividerProps) {
|
||||
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'}`} />
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,13 @@ interface DropdownButtonProps {
|
|||
|
||||
function DropdownButton({ tooltip, onClick, disabled, children }: DropdownButtonProps) {
|
||||
const behavior = (onClick ? 'cursor-pointer disabled:cursor-not-allowed clr-hover' : 'cursor-default');
|
||||
const text = disabled ? 'text-controls' : '';
|
||||
return (
|
||||
<button
|
||||
disabled={disabled}
|
||||
title={tooltip}
|
||||
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}
|
||||
</button>
|
||||
|
|
|
@ -9,10 +9,10 @@ extends IEditorProps, IColorsProps, Omit<TextareaHTMLAttributes<HTMLTextAreaElem
|
|||
}
|
||||
|
||||
function TextArea({
|
||||
id, label, required, tooltip, dense, noBorder, noOutline,
|
||||
id, label, required, tooltip, rows,
|
||||
dense, noBorder, noOutline,
|
||||
dimensions = 'w-full',
|
||||
colors = 'clr-input',
|
||||
rows = 4,
|
||||
...props
|
||||
}: TextAreaProps) {
|
||||
const borderClass = noBorder ? '': 'border';
|
||||
|
|
|
@ -56,7 +56,8 @@ extends Pick<ReactCodeMirrorProps,
|
|||
}
|
||||
|
||||
function RSInput({
|
||||
id, label, innerref, onChange, disabled, noTooltip,
|
||||
id, label, innerref, onChange,
|
||||
disabled, noTooltip,
|
||||
dimensions = 'w-full',
|
||||
...props
|
||||
}: RSInputProps) {
|
||||
|
|
|
@ -72,7 +72,7 @@ function ConstituentaPicker({
|
|||
})
|
||||
], [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(
|
||||
(): IConditionalStyle<IConstituenta>[] => [{
|
||||
|
|
|
@ -158,7 +158,7 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
|||
<MiniButton
|
||||
tooltip='Подставить значение аргумента'
|
||||
icon={<CheckIcon
|
||||
size={6}
|
||||
size={5}
|
||||
color={!argumentValue || !selectedArgument ? 'text-disabled' : 'text-success'}
|
||||
/>}
|
||||
disabled={!argumentValue || !selectedArgument}
|
||||
|
@ -177,6 +177,7 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
|
|||
<RSInput id='result'
|
||||
placeholder='Итоговое определение'
|
||||
height='5.1rem'
|
||||
dimensions='w-full mt-[0.45rem]'
|
||||
value={state.definition}
|
||||
disabled
|
||||
/>
|
||||
|
|
|
@ -86,35 +86,37 @@ function TemplateTab({ state, partialUpdate }: TemplateTabProps) {
|
|||
|
||||
return (
|
||||
<div className='flex flex-col gap-3'>
|
||||
<div className='flex justify-between gap-3'>
|
||||
<SelectSingle
|
||||
className='w-full'
|
||||
options={categorySelector}
|
||||
placeholder='Выберите категорию'
|
||||
value={state.filterCategory && selectedSchema ? {
|
||||
value: state.filterCategory.id,
|
||||
label: state.filterCategory.term_raw
|
||||
} : null}
|
||||
onChange={data => partialUpdate({filterCategory: selectedSchema?.items.find(cst => cst.id === data?.value) })}
|
||||
isClearable
|
||||
/>
|
||||
<SelectSingle
|
||||
className='min-w-[15rem]'
|
||||
options={templateSelector}
|
||||
placeholder='Выберите источник'
|
||||
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>
|
||||
<div className='flex justify-between gap-6'>
|
||||
<SelectSingle
|
||||
className='w-full'
|
||||
options={categorySelector}
|
||||
placeholder='Выберите категорию'
|
||||
value={state.filterCategory && selectedSchema ? {
|
||||
value: state.filterCategory.id,
|
||||
label: state.filterCategory.term_raw
|
||||
} : null}
|
||||
onChange={data => partialUpdate({filterCategory: selectedSchema?.items.find(cst => cst.id === data?.value) })}
|
||||
isClearable
|
||||
/>
|
||||
<SelectSingle
|
||||
className='min-w-[15rem]'
|
||||
options={templateSelector}
|
||||
placeholder='Выберите источник'
|
||||
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>
|
||||
<ConstituentaPicker
|
||||
value={state.prototype}
|
||||
data={filteredData}
|
||||
onSelectValue={cst => partialUpdate( { prototype: cst } )}
|
||||
prefixID={prefixes.cst_template_ist}
|
||||
rows={9}
|
||||
/>
|
||||
<TextArea id='term'
|
||||
rows={1}
|
||||
rows={2}
|
||||
disabled
|
||||
placeholder='Шаблон конституенты не выбран'
|
||||
value={prototypeInfo}
|
||||
|
|
|
@ -239,9 +239,13 @@ function EditorConstituenta({
|
|||
/>
|
||||
<TextArea id='typification' label='Типизация'
|
||||
dense noBorder
|
||||
rows={1}
|
||||
rows={typification.length > 70 ? 2 : 1}
|
||||
value={typification}
|
||||
colors='clr-app'
|
||||
dimensions='w-full'
|
||||
style={{
|
||||
resize: 'none'
|
||||
}}
|
||||
disabled
|
||||
/>
|
||||
<EditorRSExpression id='expression' label='Формальное определение'
|
||||
|
@ -265,7 +269,6 @@ function EditorConstituenta({
|
|||
/>
|
||||
<TextArea id='convention' label='Конвенция / Комментарий'
|
||||
placeholder='Договоренность об интерпретации или пояснение'
|
||||
rows={2}
|
||||
value={convention}
|
||||
disabled={!isEnabled}
|
||||
spellCheck
|
||||
|
|
|
@ -130,7 +130,7 @@ function EditorRSExpression({
|
|||
</div>
|
||||
<RSInput innerref={rsInput}
|
||||
value={value}
|
||||
minHeight='3.5rem'
|
||||
minHeight='3.8rem'
|
||||
disabled={disabled}
|
||||
onChange={handleChange}
|
||||
{...props}
|
||||
|
@ -139,12 +139,12 @@ function EditorRSExpression({
|
|||
disabled={disabled}
|
||||
onEdit={handleEdit}
|
||||
/>
|
||||
<div className='w-full max-h-[5rem] min-h-[5rem] flex'>
|
||||
<div className='flex flex-col'>
|
||||
<div className='w-full max-h-[4.5rem] min-h-[4.5rem] flex'>
|
||||
<div className='flex flex-col text-sm'>
|
||||
<Button
|
||||
tooltip='Проверить формальное определение'
|
||||
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'
|
||||
noOutline
|
||||
onClick={() => handleCheckExpression()}
|
||||
|
|
|
@ -97,6 +97,12 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
|||
<div tabIndex={-1} onKeyDown={handleInput}>
|
||||
<div className='relative flex items-start justify-center w-full'>
|
||||
<div className='absolute flex mt-1'>
|
||||
<MiniButton
|
||||
tooltip='Сохранить изменения'
|
||||
disabled={!isModified || !isEditable}
|
||||
icon={<SaveIcon size={5} color={isModified && isEditable ? 'text-primary' : ''}/>}
|
||||
onClick={() => handleSubmit()}
|
||||
/>
|
||||
<MiniButton
|
||||
tooltip='Поделиться схемой'
|
||||
icon={<ShareIcon size={5} color='text-primary'/>}
|
||||
|
@ -165,14 +171,15 @@ function EditorRSForm({ onDestroy, onClaim, onShare, isModified, setIsModified,
|
|||
setValue={value => setCanonical(value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SubmitButton
|
||||
text='Сохранить изменения'
|
||||
loading={processing}
|
||||
disabled={!isModified || !isEditable}
|
||||
icon={<SaveIcon size={6} />}
|
||||
dimensions='my-2 w-fit'
|
||||
/>
|
||||
<div className='flex justify-center w-full'>
|
||||
<SubmitButton
|
||||
text='Сохранить изменения'
|
||||
loading={processing}
|
||||
disabled={!isModified || !isEditable}
|
||||
icon={<SaveIcon size={6} />}
|
||||
dimensions='my-2 w-fit'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='flex justify-start'>
|
||||
|
|
|
@ -394,7 +394,6 @@ function RSTabs() {
|
|||
onClaim={onClaimSchema}
|
||||
onShare={onShareSchema}
|
||||
onToggleSubscribe={handleToggleSubscribe}
|
||||
onTemplates={onShowTemplates}
|
||||
showCloneDialog={promptClone}
|
||||
showUploadDialog={() => setShowUpload(true)}
|
||||
/>
|
||||
|
@ -402,13 +401,13 @@ function RSTabs() {
|
|||
className='border-x-2'
|
||||
tooltip={`Название схемы: ${schema.title ?? ''}`}
|
||||
>
|
||||
Паспорт схемы
|
||||
Карточка
|
||||
</ConceptTab>
|
||||
<ConceptTab
|
||||
className='border-r-2'
|
||||
tooltip={`Всего конституент: ${schema.stats?.count_all ?? 0}\nКоличество ошибок: ${schema.stats?.count_errors ?? 0}`}
|
||||
>
|
||||
Конституенты
|
||||
Содержание
|
||||
</ConceptTab>
|
||||
<ConceptTab className='border-r-2'>
|
||||
Редактор
|
||||
|
|
|
@ -12,7 +12,7 @@ function ParsingResult({ data, onShowError }: ParsingResultProps) {
|
|||
const warningsCount = data.errors.length - errorCount;
|
||||
|
||||
return (
|
||||
<div className='px-3 py-2'>
|
||||
<div className='px-2 py-1'>
|
||||
<p>Ошибок: <b>{errorCount}</b> | Предупреждений: <b>{warningsCount}</b></p>
|
||||
{data.errors.map((error, index) => {
|
||||
return (
|
||||
|
|
|
@ -81,7 +81,7 @@ function RSFormStats({ stats }: RSFormStatsProps) {
|
|||
/>}
|
||||
{ stats.count_theorem > 0 &&
|
||||
<LabeledText id='count_theorem'
|
||||
label='Теормы '
|
||||
label='Теоремы '
|
||||
text={stats.count_theorem}
|
||||
/>}
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ import Dropdown from '../../../components/Common/Dropdown';
|
|||
import DropdownButton from '../../../components/Common/DropdownButton';
|
||||
import DropdownCheckbox from '../../../components/Common/DropdownCheckbox';
|
||||
import {
|
||||
CloneIcon, DiamondIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon,
|
||||
CloneIcon, DownloadIcon, DumpBinIcon, EditIcon, MenuIcon, NotSubscribedIcon,
|
||||
OwnerIcon, ShareIcon, SmallPlusIcon, SubscribedIcon, UploadIcon
|
||||
} from '../../../components/Icons';
|
||||
import { useAuth } from '../../../context/AuthContext';
|
||||
|
@ -20,12 +20,11 @@ interface RSTabsMenuProps {
|
|||
onShare: () => void
|
||||
onDownload: () => void
|
||||
onToggleSubscribe: () => void
|
||||
onTemplates: () => void
|
||||
}
|
||||
|
||||
function RSTabsMenu({
|
||||
showUploadDialog, showCloneDialog,
|
||||
onDestroy, onShare, onDownload, onClaim, onToggleSubscribe, onTemplates
|
||||
onDestroy, onShare, onDownload, onClaim, onToggleSubscribe
|
||||
}: RSTabsMenuProps) {
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
|
@ -46,11 +45,6 @@ function RSTabsMenu({
|
|||
onDestroy();
|
||||
}
|
||||
|
||||
function handleTemplates() {
|
||||
schemaMenu.hide();
|
||||
onTemplates();
|
||||
}
|
||||
|
||||
function handleDownload () {
|
||||
schemaMenu.hide();
|
||||
onDownload();
|
||||
|
@ -102,12 +96,6 @@ function RSTabsMenu({
|
|||
<p>Клонировать</p>
|
||||
</div>
|
||||
</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}>
|
||||
<div className='inline-flex items-center justify-start gap-2'>
|
||||
<DownloadIcon color='text-primary' size={4}/>
|
||||
|
@ -150,7 +138,7 @@ function RSTabsMenu({
|
|||
<DropdownButton
|
||||
disabled={!user || !isClaimable}
|
||||
onClick={!isOwned ? handleClaimOwner : undefined}
|
||||
tooltip={!user || !isClaimable ? 'Стать владельцем можно только для общей изменяемой схемы' : ''}
|
||||
tooltip={!user || !isClaimable ? 'Взять во владение можно общую изменяемую схему' : ''}
|
||||
>
|
||||
<div className='flex items-center gap-2 pl-1'>
|
||||
<span><OwnerIcon size={5} color={isOwned ? 'text-success' : 'text-controls'} /></span>
|
||||
|
|
Loading…
Reference in New Issue
Block a user