mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactor UI state flags
This commit is contained in:
parent
102f8c2baf
commit
40696fa553
|
@ -1,6 +1,3 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { BiDownvote, BiDuplicate, BiPlusCircle, BiReset, BiTrash, BiUpvote } from 'react-icons/bi';
|
||||
import { FiSave } from 'react-icons/fi';
|
||||
|
||||
|
@ -9,8 +6,8 @@ import Overlay from '@/components/ui/Overlay';
|
|||
import { messages, prepareTooltip } from '@/utils/labels';
|
||||
|
||||
interface ConstituentaToolbarProps {
|
||||
isMutable: boolean;
|
||||
isModified: boolean;
|
||||
disabled: boolean;
|
||||
modified: boolean;
|
||||
|
||||
onSubmit: () => void;
|
||||
onReset: () => void;
|
||||
|
@ -23,8 +20,8 @@ interface ConstituentaToolbarProps {
|
|||
}
|
||||
|
||||
function ConstituentaToolbar({
|
||||
isMutable,
|
||||
isModified,
|
||||
disabled,
|
||||
modified,
|
||||
onSubmit,
|
||||
onReset,
|
||||
onMoveUp,
|
||||
|
@ -33,49 +30,48 @@ function ConstituentaToolbar({
|
|||
onClone,
|
||||
onCreate
|
||||
}: ConstituentaToolbarProps) {
|
||||
const canSave = useMemo(() => isModified && isMutable, [isModified, isMutable]);
|
||||
return (
|
||||
<Overlay position='top-1 right-4 sm:right-1/2 sm:translate-x-1/2' className='flex'>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
||||
disabled={!canSave}
|
||||
icon={<FiSave size='1.25rem' className='icon-primary' />}
|
||||
disabled={disabled || !modified}
|
||||
onClick={onSubmit}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Сбросить несохраненные изменения'
|
||||
disabled={!canSave}
|
||||
onClick={onReset}
|
||||
icon={<BiReset size='1.25rem' className='icon-primary' />}
|
||||
disabled={disabled || !modified}
|
||||
onClick={onReset}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Создать конституенту после данной'
|
||||
disabled={!isMutable}
|
||||
onClick={onCreate}
|
||||
icon={<BiPlusCircle size={'1.25rem'} className='icon-green' />}
|
||||
disabled={disabled}
|
||||
onClick={onCreate}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={isModified ? messages.unsaved : prepareTooltip('Клонировать конституенту', 'Alt + V')}
|
||||
disabled={!isMutable || isModified}
|
||||
onClick={onClone}
|
||||
titleHtml={modified ? messages.unsaved : prepareTooltip('Клонировать конституенту', 'Alt + V')}
|
||||
icon={<BiDuplicate size='1.25rem' className='icon-green' />}
|
||||
disabled={disabled || modified}
|
||||
onClick={onClone}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Удалить редактируемую конституенту'
|
||||
disabled={!isMutable}
|
||||
disabled={disabled}
|
||||
onClick={onDelete}
|
||||
icon={<BiTrash size='1.25rem' className='icon-red' />}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Переместить вверх', 'Alt + вверх')}
|
||||
icon={<BiUpvote size='1.25rem' className='icon-primary' />}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled || modified}
|
||||
onClick={onMoveUp}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Переместить вниз', 'Alt + вниз')}
|
||||
icon={<BiDownvote size='1.25rem' className='icon-primary' />}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled || modified}
|
||||
onClick={onMoveDown}
|
||||
/>
|
||||
</Overlay>
|
||||
|
|
|
@ -8,33 +8,26 @@ import { messages } from '@/utils/labels';
|
|||
|
||||
interface ControlsOverlayProps {
|
||||
constituenta?: IConstituenta;
|
||||
isMutable: boolean;
|
||||
isModified: boolean;
|
||||
disabled: boolean;
|
||||
modified: boolean;
|
||||
processing: boolean;
|
||||
|
||||
onRename: () => void;
|
||||
onEditTerm: () => void;
|
||||
}
|
||||
|
||||
function ControlsOverlay({
|
||||
constituenta,
|
||||
isMutable,
|
||||
isModified,
|
||||
processing,
|
||||
onRename,
|
||||
onEditTerm
|
||||
}: ControlsOverlayProps) {
|
||||
function ControlsOverlay({ constituenta, disabled, modified, processing, onRename, onEditTerm }: ControlsOverlayProps) {
|
||||
return (
|
||||
<Overlay position='top-1 left-[4.1rem]' className='flex select-none'>
|
||||
{isMutable || processing ? (
|
||||
{!disabled || processing ? (
|
||||
<MiniButton
|
||||
title={
|
||||
isModified ? messages.unsaved : `Редактировать словоформы термина: ${constituenta?.term_forms.length ?? 0}`
|
||||
modified ? messages.unsaved : `Редактировать словоформы термина: ${constituenta?.term_forms.length ?? 0}`
|
||||
}
|
||||
noHover
|
||||
onClick={onEditTerm}
|
||||
icon={<LiaEdit size='1rem' className='icon-primary' />}
|
||||
disabled={isModified}
|
||||
disabled={modified}
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
|
@ -42,19 +35,19 @@ function ControlsOverlay({
|
|||
'pt-1 pl-[1.375rem]', // prettier: split lines
|
||||
'text-sm font-medium whitespace-nowrap',
|
||||
'select-text cursor-default',
|
||||
!isMutable && !processing && 'pl-[2.8rem]'
|
||||
disabled && !processing && 'pl-[2.8rem]'
|
||||
)}
|
||||
>
|
||||
<span>Имя </span>
|
||||
<span className='ml-1'>{constituenta?.alias ?? ''}</span>
|
||||
</div>
|
||||
{isMutable || processing ? (
|
||||
{!disabled || processing ? (
|
||||
<MiniButton
|
||||
noHover
|
||||
title={isModified ? messages.unsaved : 'Переименовать конституенту'}
|
||||
title={modified ? messages.unsaved : 'Переименовать конституенту'}
|
||||
onClick={onRename}
|
||||
icon={<LiaEdit size='1rem' className='icon-primary' />}
|
||||
disabled={isModified}
|
||||
disabled={modified}
|
||||
/>
|
||||
) : null}
|
||||
</Overlay>
|
||||
|
|
|
@ -35,8 +35,8 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
const [toggleReset, setToggleReset] = useState(false);
|
||||
|
||||
const disabled = useMemo(
|
||||
() => !activeCst || !controller.isContentEditable,
|
||||
[activeCst, controller.isContentEditable]
|
||||
() => !activeCst || !controller.isContentEditable || controller.isProcessing,
|
||||
[activeCst, controller.isContentEditable, controller.isProcessing]
|
||||
);
|
||||
|
||||
const isNarrow = useMemo(() => !!windowSize.width && windowSize.width <= SIDELIST_LAYOUT_THRESHOLD, [windowSize]);
|
||||
|
@ -79,10 +79,10 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
|
||||
return (
|
||||
<>
|
||||
{controller.isContentEditable || controller.isProcessing ? (
|
||||
{controller.isContentEditable ? (
|
||||
<ConstituentaToolbar
|
||||
isMutable={!disabled}
|
||||
isModified={isModified}
|
||||
disabled={disabled}
|
||||
modified={isModified}
|
||||
onMoveUp={controller.moveUp}
|
||||
onMoveDown={controller.moveDown}
|
||||
onSubmit={initiateSubmit}
|
||||
|
@ -102,7 +102,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
onKeyDown={handleInput}
|
||||
>
|
||||
<FormConstituenta
|
||||
isMutable={!disabled}
|
||||
disabled={disabled}
|
||||
showList={showList}
|
||||
id={globals.constituenta_editor}
|
||||
constituenta={activeCst}
|
||||
|
|
|
@ -21,7 +21,7 @@ import ControlsOverlay from './ControlsOverlay';
|
|||
export const ROW_SIZE_IN_CHARACTERS = 70;
|
||||
|
||||
interface FormConstituentaProps {
|
||||
isMutable: boolean;
|
||||
disabled: boolean;
|
||||
showList: boolean;
|
||||
|
||||
id?: string;
|
||||
|
@ -37,7 +37,7 @@ interface FormConstituentaProps {
|
|||
}
|
||||
|
||||
function FormConstituenta({
|
||||
isMutable,
|
||||
disabled,
|
||||
showList,
|
||||
id,
|
||||
isModified,
|
||||
|
@ -114,8 +114,8 @@ function FormConstituenta({
|
|||
return (
|
||||
<div>
|
||||
<ControlsOverlay
|
||||
isMutable={isMutable}
|
||||
isModified={isModified}
|
||||
disabled={disabled}
|
||||
modified={isModified}
|
||||
processing={processing}
|
||||
constituenta={constituenta}
|
||||
onEditTerm={onEditTerm}
|
||||
|
@ -134,14 +134,14 @@ function FormConstituenta({
|
|||
value={term}
|
||||
initialValue={constituenta?.term_raw ?? ''}
|
||||
resolved={constituenta?.term_resolved ?? ''}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled}
|
||||
onChange={newValue => setTerm(newValue)}
|
||||
/>
|
||||
<TextArea
|
||||
id='cst_typification'
|
||||
dense
|
||||
noBorder
|
||||
disabled
|
||||
disabled={true}
|
||||
label='Типизация'
|
||||
rows={typification.length > ROW_SIZE_IN_CHARACTERS ? 2 : 1}
|
||||
value={typification}
|
||||
|
@ -157,7 +157,7 @@ function FormConstituenta({
|
|||
value={expression}
|
||||
activeCst={constituenta}
|
||||
showList={showList}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled}
|
||||
toggleReset={toggleReset}
|
||||
onToggleList={onToggleList}
|
||||
onChange={newValue => setExpression(newValue)}
|
||||
|
@ -172,7 +172,7 @@ function FormConstituenta({
|
|||
value={textDefinition}
|
||||
initialValue={constituenta?.definition_raw ?? ''}
|
||||
resolved={constituenta?.definition_resolved ?? ''}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled}
|
||||
onChange={newValue => setTextDefinition(newValue)}
|
||||
/>
|
||||
<TextArea
|
||||
|
@ -181,15 +181,15 @@ function FormConstituenta({
|
|||
label='Конвенция / Комментарий'
|
||||
placeholder='Договоренность об интерпретации или пояснение'
|
||||
value={convention}
|
||||
disabled={!isMutable}
|
||||
disabled={disabled}
|
||||
rows={convention.length > 2 * ROW_SIZE_IN_CHARACTERS ? 3 : 2}
|
||||
onChange={event => setConvention(event.target.value)}
|
||||
/>
|
||||
{isMutable || processing ? (
|
||||
{!disabled || processing ? (
|
||||
<SubmitButton
|
||||
text='Сохранить изменения'
|
||||
className='self-center'
|
||||
disabled={!isModified || !isMutable}
|
||||
disabled={disabled || !isModified}
|
||||
icon={<FiSave size='1.25rem' />}
|
||||
/>
|
||||
) : null}
|
||||
|
|
|
@ -118,7 +118,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
|||
/>
|
||||
<div className='flex flex-col'>
|
||||
<Overlay position='top-[-0.25rem] right-[-0.25rem] flex'>
|
||||
{controller.isMutable || (controller.isMutable && controller.isProcessing) ? (
|
||||
{controller.isMutable ? (
|
||||
<>
|
||||
<MiniButton
|
||||
noHover
|
||||
|
@ -152,7 +152,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
|||
label='Комментарий'
|
||||
rows={3}
|
||||
value={comment}
|
||||
disabled={!controller.isContentEditable}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
onChange={event => setComment(event.target.value)}
|
||||
/>
|
||||
<div className='flex justify-between whitespace-nowrap'>
|
||||
|
@ -160,7 +160,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
|||
id='schema_common'
|
||||
label='Общедоступная схема'
|
||||
title='Общедоступные схемы видны всем пользователям и могут быть изменены'
|
||||
disabled={!controller.isContentEditable}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
value={common}
|
||||
setValue={value => setCommon(value)}
|
||||
/>
|
||||
|
@ -168,17 +168,17 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
|
|||
id='schema_immutable'
|
||||
label='Неизменная схема'
|
||||
title='Только администраторы могут присваивать схемам неизменный статус'
|
||||
disabled={!controller.isContentEditable || !user?.is_staff}
|
||||
disabled={!controller.isContentEditable || !user?.is_staff || controller.isProcessing}
|
||||
value={canonical}
|
||||
setValue={value => setCanonical(value)}
|
||||
/>
|
||||
</div>
|
||||
{controller.isContentEditable || (controller.isMutable && controller.isProcessing) ? (
|
||||
{controller.isContentEditable ? (
|
||||
<SubmitButton
|
||||
text='Сохранить изменения'
|
||||
className='self-center'
|
||||
loading={processing}
|
||||
disabled={!isModified || controller.isProcessing}
|
||||
disabled={!isModified}
|
||||
icon={<FiSave size='1.25rem' />}
|
||||
/>
|
||||
) : null}
|
||||
|
|
|
@ -24,10 +24,10 @@ interface RSFormToolbarProps {
|
|||
|
||||
function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, onDestroy }: RSFormToolbarProps) {
|
||||
const controller = useRSEdit();
|
||||
const canSave = useMemo(() => modified && controller.isMutable, [modified, controller.isMutable]);
|
||||
const canSave = useMemo(() => modified && !controller.isProcessing, [modified, controller.isProcessing]);
|
||||
return (
|
||||
<Overlay position='top-1 right-1/2 translate-x-1/2' className='flex'>
|
||||
{controller.isContentEditable || (controller.isMutable && controller.isProcessing) ? (
|
||||
{controller.isContentEditable ? (
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Сохранить изменения', 'Ctrl + S')}
|
||||
disabled={!canSave}
|
||||
|
@ -48,7 +48,6 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o
|
|||
{!anonymous ? (
|
||||
<MiniButton
|
||||
titleHtml={`Отслеживание <b>${subscribed ? 'включено' : 'выключено'}</b>`}
|
||||
disabled={controller.isProcessing}
|
||||
icon={
|
||||
subscribed ? (
|
||||
<FiBell size='1.25rem' className='icon-primary' />
|
||||
|
@ -56,6 +55,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o
|
|||
<FiBellOff size='1.25rem' className='clr-text-controls' />
|
||||
)
|
||||
}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={controller.toggleSubscribe}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -67,12 +67,12 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o
|
|||
onClick={controller.claim}
|
||||
/>
|
||||
) : null}
|
||||
{controller.isContentEditable || (controller.isMutable && controller.isProcessing) ? (
|
||||
{controller.isMutable ? (
|
||||
<MiniButton
|
||||
title='Удалить схему'
|
||||
disabled={!controller.isMutable}
|
||||
onClick={onDestroy}
|
||||
icon={<BiTrash size='1.25rem' className='icon-red' />}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
onClick={onDestroy}
|
||||
/>
|
||||
) : null}
|
||||
<HelpButton topic={HelpTopic.RSFORM} offset={4} />
|
||||
|
|
|
@ -51,7 +51,7 @@ function EditorRSList({ selected, setSelected, onOpenEdit }: EditorRSListProps)
|
|||
}
|
||||
|
||||
function handleTableKey(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
if (!controller.isMutable) {
|
||||
if (!controller.isContentEditable || controller.isProcessing) {
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Delete' && selected.length > 0) {
|
||||
|
@ -97,7 +97,7 @@ function EditorRSList({ selected, setSelected, onOpenEdit }: EditorRSListProps)
|
|||
|
||||
return (
|
||||
<div tabIndex={-1} className='outline-none' onKeyDown={handleTableKey}>
|
||||
{controller.isContentEditable || (controller.isMutable && controller.isProcessing) ? (
|
||||
{controller.isContentEditable ? (
|
||||
<SelectedCounter
|
||||
totalCount={controller.schema?.stats?.count_all ?? 0}
|
||||
selectedCount={selected.length}
|
||||
|
@ -105,20 +105,18 @@ function EditorRSList({ selected, setSelected, onOpenEdit }: EditorRSListProps)
|
|||
/>
|
||||
) : null}
|
||||
|
||||
{controller.isContentEditable || (controller.isMutable && controller.isProcessing) ? (
|
||||
<RSListToolbar selectedCount={selected.length} />
|
||||
) : null}
|
||||
{controller.isContentEditable ? <RSListToolbar selectedCount={selected.length} /> : null}
|
||||
<div
|
||||
className={clsx('border-b', {
|
||||
'pt-[2.3rem]': controller.isContentEditable || controller.isProcessing,
|
||||
'relative top-[-1px]': !controller.isContentEditable && !controller.isProcessing
|
||||
'pt-[2.3rem]': controller.isContentEditable,
|
||||
'relative top-[-1px]': !controller.isContentEditable
|
||||
})}
|
||||
/>
|
||||
|
||||
<RSTable
|
||||
items={controller.schema?.items}
|
||||
maxHeight={tableHeight}
|
||||
enableSelection={controller.isContentEditable || (controller.isMutable && controller.isProcessing)}
|
||||
enableSelection={controller.isContentEditable}
|
||||
selected={rowSelection}
|
||||
setSelected={handleRowSelection}
|
||||
onEdit={onOpenEdit}
|
||||
|
|
|
@ -31,25 +31,25 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) {
|
|||
<MiniButton
|
||||
titleHtml={prepareTooltip('Переместить вверх', 'Alt + вверх')}
|
||||
icon={<BiUpvote size='1.25rem' className='icon-primary' />}
|
||||
disabled={!controller.isMutable || nothingSelected}
|
||||
disabled={controller.isProcessing || nothingSelected}
|
||||
onClick={controller.moveUp}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Переместить вниз', 'Alt + вниз')}
|
||||
icon={<BiDownvote size='1.25rem' className='icon-primary' />}
|
||||
disabled={!controller.isMutable || nothingSelected}
|
||||
disabled={controller.isProcessing || nothingSelected}
|
||||
onClick={controller.moveDown}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Клонировать конституенту', 'Alt + V')}
|
||||
icon={<BiDuplicate size='1.25rem' className='icon-green' />}
|
||||
disabled={!controller.isMutable || selectedCount !== 1}
|
||||
disabled={controller.isProcessing || selectedCount !== 1}
|
||||
onClick={controller.cloneCst}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Добавить новую конституенту...', 'Alt + `')}
|
||||
icon={<BiPlusCircle size='1.25rem' className='icon-green' />}
|
||||
disabled={!controller.isMutable}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={() => controller.createCst(undefined, false)}
|
||||
/>
|
||||
<div ref={insertMenu.ref}>
|
||||
|
@ -57,7 +57,7 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) {
|
|||
title='Добавить пустую конституенту'
|
||||
hideTitle={insertMenu.isOpen}
|
||||
icon={<BiDownArrowCircle size='1.25rem' className='icon-green' />}
|
||||
disabled={!controller.isMutable}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={insertMenu.toggle}
|
||||
/>
|
||||
<Dropdown isOpen={insertMenu.isOpen}>
|
||||
|
@ -74,7 +74,7 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) {
|
|||
<MiniButton
|
||||
titleHtml={prepareTooltip('Удалить выбранные', 'Delete')}
|
||||
icon={<BiTrash size='1.25rem' className='icon-red' />}
|
||||
disabled={!controller.isMutable || nothingSelected}
|
||||
disabled={controller.isProcessing || nothingSelected}
|
||||
onClick={controller.deleteCst}
|
||||
/>
|
||||
<HelpButton topic={HelpTopic.CSTLIST} offset={5} />
|
||||
|
|
|
@ -169,7 +169,7 @@ function EditorTermGraph({ selected, setSelected, onOpenEdit }: EditorTermGraphP
|
|||
|
||||
function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
|
||||
// Hotkeys implementation
|
||||
if (!controller.isMutable) {
|
||||
if (!controller.isContentEditable || controller.isProcessing) {
|
||||
return;
|
||||
}
|
||||
if (event.key === 'Delete') {
|
||||
|
|
|
@ -68,19 +68,19 @@ function GraphToolbar({
|
|||
disabled={!is3D}
|
||||
onClick={toggleOrbit}
|
||||
/>
|
||||
{controller.isMutable || controller.isProcessing ? (
|
||||
{controller.isContentEditable ? (
|
||||
<MiniButton
|
||||
title='Новая конституента'
|
||||
icon={<BiPlusCircle size='1.25rem' className='icon-green' />}
|
||||
disabled={!controller.isMutable}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={onCreate}
|
||||
/>
|
||||
) : null}
|
||||
{controller.isMutable || controller.isProcessing ? (
|
||||
{controller.isContentEditable ? (
|
||||
<MiniButton
|
||||
title='Удалить выбранные'
|
||||
icon={<BiTrash size='1.25rem' className='icon-red' />}
|
||||
disabled={nothingSelected || !controller.isMutable}
|
||||
disabled={nothingSelected || controller.isProcessing}
|
||||
onClick={onDelete}
|
||||
/>
|
||||
) : null}
|
||||
|
|
|
@ -114,13 +114,9 @@ export const RSEditState = ({
|
|||
|
||||
const isMutable = useMemo(() => {
|
||||
return (
|
||||
!model.loading &&
|
||||
!model.processing &&
|
||||
mode !== UserAccessMode.READER &&
|
||||
((model.isOwned || (mode === UserAccessMode.ADMIN && user?.is_staff)) ?? false)
|
||||
mode !== UserAccessMode.READER && ((model.isOwned || (mode === UserAccessMode.ADMIN && user?.is_staff)) ?? false)
|
||||
);
|
||||
}, [user?.is_staff, mode, model.isOwned, model.loading, model.processing]);
|
||||
|
||||
}, [user?.is_staff, mode, model.isOwned]);
|
||||
const isContentEditable = useMemo(() => isMutable && !model.isArchive, [isMutable, model.isArchive]);
|
||||
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
|
|
|
@ -138,9 +138,9 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
<Dropdown isOpen={schemaMenu.isOpen}>
|
||||
{user ? (
|
||||
<DropdownButton
|
||||
disabled={!model.isClaimable && !model.isOwned}
|
||||
text={model.isOwned ? 'Вы — владелец' : 'Стать владельцем'}
|
||||
icon={<LuCrown size='1rem' className='icon-green' />}
|
||||
disabled={!model.isClaimable && !model.isOwned}
|
||||
onClick={!model.isOwned && model.isClaimable ? handleClaimOwner : undefined}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -151,9 +151,9 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
/>
|
||||
{user ? (
|
||||
<DropdownButton
|
||||
disabled={model.isArchive}
|
||||
text='Клонировать'
|
||||
icon={<BiDuplicate size='1rem' className='icon-primary' />}
|
||||
disabled={model.isArchive}
|
||||
onClick={handleClone}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -162,11 +162,11 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
icon={<BiDownload size='1rem' className='icon-primary' />}
|
||||
onClick={handleDownload}
|
||||
/>
|
||||
{user ? (
|
||||
{controller.isContentEditable ? (
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable}
|
||||
text='Загрузить из Экстеора'
|
||||
icon={<BiUpload size='1rem' className='icon-red' />}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={handleUpload}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -174,6 +174,7 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
<DropdownButton
|
||||
text='Удалить схему'
|
||||
icon={<BiTrash size='1rem' className='icon-red' />}
|
||||
disabled={controller.isProcessing}
|
||||
onClick={handleDelete}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -208,40 +209,40 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
/>
|
||||
<Dropdown isOpen={editMenu.isOpen}>
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable}
|
||||
text='Шаблоны'
|
||||
title='Создать конституенту из шаблона'
|
||||
icon={<BiDiamond size='1rem' className='icon-green' />}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
onClick={handleTemplates}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable}
|
||||
text='Встраивание'
|
||||
title='Импортировать совокупность конституент из другой схемы'
|
||||
icon={<LuBookCopy size='1rem' className='icon-green' />}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
onClick={handleInlineSynthesis}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable}
|
||||
className='border-t-2'
|
||||
text='Порядковые имена'
|
||||
title='Присвоить порядковые имена и обновить выражения'
|
||||
icon={<LuWand2 size='1rem' className='icon-primary' />}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
onClick={handleReindex}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable || !controller.canProduceStructure}
|
||||
text='Порождение структуры'
|
||||
title='Раскрыть структуру типизации выделенной конституенты'
|
||||
icon={<LuNetwork size='1rem' className='icon-primary' />}
|
||||
disabled={!controller.isContentEditable || !controller.canProduceStructure}
|
||||
onClick={handleProduceStructure}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!controller.isContentEditable}
|
||||
text='Отождествление'
|
||||
title='Заменить вхождения одной конституенты на другую'
|
||||
icon={<LuReplace size='1rem' className='icon-red' />}
|
||||
onClick={handleSubstituteCst}
|
||||
disabled={!controller.isContentEditable || controller.isProcessing}
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
@ -289,17 +290,17 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) {
|
|||
onClick={() => handleChangeMode(UserAccessMode.READER)}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!model.isOwned}
|
||||
text={labelAccessMode(UserAccessMode.OWNER)}
|
||||
title={describeAccessMode(UserAccessMode.OWNER)}
|
||||
icon={<LuCrown size='1rem' className='icon-primary' />}
|
||||
disabled={!model.isOwned}
|
||||
onClick={() => handleChangeMode(UserAccessMode.OWNER)}
|
||||
/>
|
||||
<DropdownButton
|
||||
disabled={!user?.is_staff}
|
||||
text={labelAccessMode(UserAccessMode.ADMIN)}
|
||||
title={describeAccessMode(UserAccessMode.ADMIN)}
|
||||
icon={<BiMeteor size='1rem' className='icon-primary' />}
|
||||
disabled={!user?.is_staff}
|
||||
onClick={() => handleChangeMode(UserAccessMode.ADMIN)}
|
||||
/>
|
||||
</Dropdown>
|
||||
|
|
Loading…
Reference in New Issue
Block a user