mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Small screen optimizations and help fix
This commit is contained in:
parent
26991f460c
commit
64e1b028bc
|
@ -11,7 +11,7 @@ function ApplicationLayout() {
|
|||
const { viewportHeight, mainHeight, showScroll } = useConceptOptions();
|
||||
return (
|
||||
<NavigationState>
|
||||
<div className='min-w-[20rem] clr-app antialiased'>
|
||||
<div className='min-w-[20rem] overflow-x-auto max-w-[100vw] clr-app antialiased'>
|
||||
<ConceptToaster
|
||||
className='mt-[4rem] text-sm' // prettier: split lines
|
||||
autoClose={3000}
|
||||
|
@ -23,7 +23,7 @@ function ApplicationLayout() {
|
|||
|
||||
<div
|
||||
id={globals.main_scroll}
|
||||
className='overflow-x-auto cc-scroll-y min-w-fit'
|
||||
className='cc-scroll-y min-w-fit'
|
||||
style={{
|
||||
maxHeight: viewportHeight,
|
||||
overflowY: showScroll ? 'scroll' : 'auto'
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
import LinkTopic from '@/components/ui/LinkTopic';
|
||||
import { useConceptOptions } from '@/context/OptionsContext';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
|
||||
import {
|
||||
IconClone,
|
||||
IconControls,
|
||||
IconDestroy,
|
||||
IconEdit,
|
||||
IconList,
|
||||
IconMoveDown,
|
||||
IconMoveUp,
|
||||
IconNewItem,
|
||||
IconReset,
|
||||
IconSave,
|
||||
IconStatusOK,
|
||||
IconText,
|
||||
IconTree
|
||||
} from '../../../components/Icons';
|
||||
} from '@/components/Icons';
|
||||
import LinkTopic from '@/components/ui/LinkTopic';
|
||||
import { useConceptOptions } from '@/context/OptionsContext';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
|
||||
function HelpCstEditor() {
|
||||
const { colors } = useConceptOptions();
|
||||
|
@ -21,11 +26,23 @@ function HelpCstEditor() {
|
|||
<IconSave className='inline-icon' /> сохранить изменения: Ctrl + S
|
||||
</li>
|
||||
<li>
|
||||
<IconEdit className='inline-icon' /> кнопка переименования справа от{' '}
|
||||
<LinkTopic text='Имени' topic={HelpTopic.CC_CONSTITUENTA} />
|
||||
<IconReset className='inline-icon' /> сбросить несохраненные изменения
|
||||
</li>
|
||||
<li>
|
||||
<IconClone className='inline-icon icon-green' /> клонировать текущую: Alt + V
|
||||
</li>
|
||||
<li>
|
||||
<IconNewItem className='inline-icon icon-green' /> новая конституента
|
||||
</li>
|
||||
<li>
|
||||
<IconDestroy className='inline-icon icon-red' /> удаление текущей
|
||||
</li>
|
||||
|
||||
<h2>Термин и Текстовое определение</h2>
|
||||
<li>
|
||||
<IconEdit className='inline-icon' /> кнопка переименования справа от{' '}
|
||||
<LinkTopic text='Имени' topic={HelpTopic.CC_CONSTITUENTA} />
|
||||
</li>
|
||||
<li>
|
||||
<IconEdit className='inline-icon' /> кнопка редактирования словоформ справа от{' '}
|
||||
<LinkTopic text='Термина' topic={HelpTopic.CC_CONSTITUENTA} />
|
||||
|
@ -42,9 +59,6 @@ function HelpCstEditor() {
|
|||
<li>
|
||||
<IconControls className='inline-icon' /> специальная клавиатура и горячие клавиши
|
||||
</li>
|
||||
<li>
|
||||
<IconList className='inline-icon' /> отображение списка конституент
|
||||
</li>
|
||||
<li>
|
||||
<IconTree className='inline-icon' /> отображение{' '}
|
||||
<LinkTopic text='дерева разбора' topic={HelpTopic.UI_FORMULA_TREE} />
|
||||
|
@ -52,6 +66,13 @@ function HelpCstEditor() {
|
|||
<li>Ctrl + Пробел дополняет до незанятого имени</li>
|
||||
|
||||
<h2>Список конституент</h2>
|
||||
<li>
|
||||
<IconList className='inline-icon' /> отображение списка конституент
|
||||
</li>
|
||||
<li>
|
||||
<IconMoveDown className='inline-icon' />
|
||||
<IconMoveUp className='inline-icon' /> Alt + вверх/вниз – перемещение
|
||||
</li>
|
||||
<li>фильтрация в верхней части</li>
|
||||
<li>при наведении на имя конституенты отображаются атрибуты</li>
|
||||
<li>
|
||||
|
|
|
@ -2,7 +2,16 @@ import InfoCstStatus from '@/components/info/InfoCstStatus';
|
|||
import Divider from '@/components/ui/Divider';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
|
||||
import { IconAlias, IconDestroy, IconMoveDown, IconMoveUp, IconOpenList, IconReset } from '../../../components/Icons';
|
||||
import {
|
||||
IconAlias,
|
||||
IconClone,
|
||||
IconDestroy,
|
||||
IconMoveDown,
|
||||
IconMoveUp,
|
||||
IconNewItem,
|
||||
IconOpenList,
|
||||
IconReset
|
||||
} from '../../../components/Icons';
|
||||
import LinkTopic from '../../../components/ui/LinkTopic';
|
||||
|
||||
function HelpRSFormItems() {
|
||||
|
@ -26,11 +35,18 @@ function HelpRSFormItems() {
|
|||
<IconMoveUp className='inline-icon' />
|
||||
<IconMoveDown className='inline-icon' /> Alt + вверх/вниз – перемещение
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<IconDestroy className='inline-icon icon-red' /> удаление: Delete
|
||||
<IconClone className='inline-icon icon-green' /> клонировать выделенную: Alt + V
|
||||
</li>
|
||||
<li>
|
||||
<IconOpenList className='inline-icon icon-green' /> добавление: Alt + 1-6,Q,W –{' '}
|
||||
<IconNewItem className='inline-icon icon-green' /> новая конституента: Alt + `
|
||||
</li>
|
||||
<li>
|
||||
<IconOpenList className='inline-icon icon-green' /> быстрое добавление: Alt + 1-6,Q,W
|
||||
</li>
|
||||
<li>
|
||||
<IconDestroy className='inline-icon icon-red' /> удаление выделенных: Delete
|
||||
</li>
|
||||
|
||||
<Divider margins='my-2' />
|
||||
|
|
|
@ -1,4 +1,14 @@
|
|||
import { IconClone, IconDestroy, IconMoveDown, IconMoveUp, IconNewItem, IconReset, IconSave } from '@/components/Icons';
|
||||
import {
|
||||
IconClone,
|
||||
IconDestroy,
|
||||
IconList,
|
||||
IconListOff,
|
||||
IconMoveDown,
|
||||
IconMoveUp,
|
||||
IconNewItem,
|
||||
IconReset,
|
||||
IconSave
|
||||
} from '@/components/Icons';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
|
@ -8,6 +18,7 @@ import { messages, prepareTooltip } from '@/utils/labels';
|
|||
interface ConstituentaToolbarProps {
|
||||
disabled: boolean;
|
||||
modified: boolean;
|
||||
showList: boolean;
|
||||
|
||||
onSubmit: () => void;
|
||||
onReset: () => void;
|
||||
|
@ -17,18 +28,22 @@ interface ConstituentaToolbarProps {
|
|||
onDelete: () => void;
|
||||
onClone: () => void;
|
||||
onCreate: () => void;
|
||||
onToggleList: () => void;
|
||||
}
|
||||
|
||||
function ConstituentaToolbar({
|
||||
disabled,
|
||||
modified,
|
||||
showList,
|
||||
|
||||
onSubmit,
|
||||
onReset,
|
||||
onMoveUp,
|
||||
onMoveDown,
|
||||
onDelete,
|
||||
onClone,
|
||||
onCreate
|
||||
onCreate,
|
||||
onToggleList
|
||||
}: ConstituentaToolbarProps) {
|
||||
return (
|
||||
<Overlay position='top-1 right-4' className='cc-icons sm:right-1/2 sm:translate-x-1/2'>
|
||||
|
@ -62,6 +77,11 @@ function ConstituentaToolbar({
|
|||
onClick={onDelete}
|
||||
icon={<IconDestroy size='1.25rem' className='icon-red' />}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Отображение списка конституент'
|
||||
icon={showList ? <IconList size='1.25rem' className='icon-primary' /> : <IconListOff size='1.25rem' />}
|
||||
onClick={onToggleList}
|
||||
/>
|
||||
<MiniButton
|
||||
titleHtml={prepareTooltip('Переместить вверх', 'Alt + вверх')}
|
||||
icon={<IconMoveUp size='1.25rem' className='icon-primary' />}
|
||||
|
|
|
@ -18,7 +18,7 @@ interface ControlsOverlayProps {
|
|||
|
||||
function ControlsOverlay({ constituenta, disabled, modified, processing, onRename, onEditTerm }: ControlsOverlayProps) {
|
||||
return (
|
||||
<Overlay position='top-1 left-[4.3rem]' className='flex select-none'>
|
||||
<Overlay position='top-1 left-[4.7rem]' className='flex select-none'>
|
||||
{!disabled || processing ? (
|
||||
<MiniButton
|
||||
title={modified ? messages.unsaved : `Редактировать словоформы термина`}
|
||||
|
|
|
@ -81,6 +81,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
<ConstituentaToolbar
|
||||
disabled={disabled}
|
||||
modified={isModified}
|
||||
showList={showList}
|
||||
onMoveUp={controller.moveUp}
|
||||
onMoveDown={controller.moveDown}
|
||||
onSubmit={initiateSubmit}
|
||||
|
@ -88,6 +89,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
onDelete={controller.deleteCst}
|
||||
onClone={controller.cloneCst}
|
||||
onCreate={() => controller.createCst(activeCst?.cst_type, false)}
|
||||
onToggleList={() => setShowList(prev => !prev)}
|
||||
/>
|
||||
) : null}
|
||||
<div
|
||||
|
@ -101,12 +103,10 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
|||
>
|
||||
<FormConstituenta
|
||||
disabled={disabled}
|
||||
showList={showList}
|
||||
id={globals.constituenta_editor}
|
||||
state={activeCst}
|
||||
isModified={isModified}
|
||||
toggleReset={toggleReset}
|
||||
onToggleList={() => setShowList(prev => !prev)}
|
||||
setIsModified={setIsModified}
|
||||
onEditTerm={controller.editTermForms}
|
||||
onRename={controller.renameCst}
|
||||
|
|
|
@ -25,7 +25,6 @@ export const ROW_SIZE_IN_CHARACTERS = 70;
|
|||
|
||||
interface FormConstituentaProps {
|
||||
disabled: boolean;
|
||||
showList: boolean;
|
||||
|
||||
id?: string;
|
||||
state?: IConstituenta;
|
||||
|
@ -34,14 +33,12 @@ interface FormConstituentaProps {
|
|||
toggleReset: boolean;
|
||||
setIsModified: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
|
||||
onToggleList: () => void;
|
||||
onRename: () => void;
|
||||
onEditTerm: () => void;
|
||||
}
|
||||
|
||||
function FormConstituenta({
|
||||
disabled,
|
||||
showList,
|
||||
id,
|
||||
state,
|
||||
|
||||
|
@ -50,8 +47,7 @@ function FormConstituenta({
|
|||
|
||||
toggleReset,
|
||||
onRename,
|
||||
onEditTerm,
|
||||
onToggleList
|
||||
onEditTerm
|
||||
}: FormConstituentaProps) {
|
||||
const { schema, cstUpdate, processing } = useRSForm();
|
||||
|
||||
|
@ -138,7 +134,7 @@ function FormConstituenta({
|
|||
/>
|
||||
<form
|
||||
id={id}
|
||||
className={clsx('cc-column', 'mt-1 w-full md:w-[47.8rem] shrink-0', 'px-4 py-1')}
|
||||
className={clsx('cc-column', 'mt-1 w-full md:w-[48.8rem] shrink-0', 'px-6 py-1')}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<RefsInput
|
||||
|
@ -183,10 +179,8 @@ function FormConstituenta({
|
|||
}
|
||||
value={expression}
|
||||
activeCst={state}
|
||||
showList={showList}
|
||||
disabled={disabled}
|
||||
toggleReset={toggleReset}
|
||||
onToggleList={onToggleList}
|
||||
onChange={newValue => setExpression(newValue)}
|
||||
setTypification={setTypification}
|
||||
/>
|
||||
|
|
|
@ -5,13 +5,10 @@ import { AnimatePresence } from 'framer-motion';
|
|||
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { IconControls, IconList, IconListOff, IconText, IconTextOff, IconTree } from '@/components/Icons';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import RSInput from '@/components/RSInput';
|
||||
import { RSTextWrapper } from '@/components/RSInput/textEditing';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
import { useConceptOptions } from '@/context/OptionsContext';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
import DlgShowAST from '@/dialogs/DlgShowAST';
|
||||
import useCheckExpression from '@/hooks/useCheckExpression';
|
||||
|
@ -24,6 +21,7 @@ import { TokenID } from '@/models/rslang';
|
|||
import { storage } from '@/utils/constants';
|
||||
import { labelTypification } from '@/utils/labels';
|
||||
|
||||
import ExpressionToolbar from './ExpressionToolbar';
|
||||
import ParsingResult from './ParsingResult';
|
||||
import RSEditorControls from './RSEditControls';
|
||||
import StatusBar from './StatusBar';
|
||||
|
@ -37,11 +35,9 @@ interface EditorRSExpressionProps {
|
|||
|
||||
disabled?: boolean;
|
||||
toggleReset?: boolean;
|
||||
showList: boolean;
|
||||
|
||||
setTypification: (typification: string) => void;
|
||||
onChange: (newValue: string) => void;
|
||||
onToggleList: () => void;
|
||||
}
|
||||
|
||||
function EditorRSExpression({
|
||||
|
@ -49,14 +45,11 @@ function EditorRSExpression({
|
|||
disabled,
|
||||
value,
|
||||
toggleReset,
|
||||
showList,
|
||||
setTypification,
|
||||
onChange,
|
||||
onToggleList,
|
||||
...restProps
|
||||
}: EditorRSExpressionProps) {
|
||||
const model = useRSForm();
|
||||
const { mathFont, setMathFont } = useConceptOptions();
|
||||
|
||||
const [isModified, setIsModified] = useState(false);
|
||||
const parser = useCheckExpression({ schema: model.schema });
|
||||
|
@ -147,10 +140,6 @@ function EditorRSExpression({
|
|||
});
|
||||
}
|
||||
|
||||
function toggleFont() {
|
||||
setMathFont(mathFont === 'math' ? 'math2' : 'math');
|
||||
}
|
||||
|
||||
const controls = useMemo(
|
||||
() => (
|
||||
<RSEditorControls
|
||||
|
@ -170,32 +159,12 @@ function EditorRSExpression({
|
|||
) : null}
|
||||
</AnimatePresence>
|
||||
|
||||
<Overlay position='top-[-0.5rem] right-0 cc-icons'>
|
||||
<MiniButton
|
||||
title='Изменить шрифт'
|
||||
onClick={toggleFont}
|
||||
icon={
|
||||
mathFont === 'math' ? <IconText size='1.25rem' className='icon-primary' /> : <IconTextOff size='1.25rem' />
|
||||
}
|
||||
/>
|
||||
{!disabled || model.processing ? (
|
||||
<MiniButton
|
||||
title='Отображение специальной клавиатуры'
|
||||
icon={<IconControls size='1.25rem' className={showControls ? 'icon-primary' : ''} />}
|
||||
onClick={() => setShowControls(prev => !prev)}
|
||||
/>
|
||||
) : null}
|
||||
<MiniButton
|
||||
title='Отображение списка конституент'
|
||||
icon={showList ? <IconList size='1.25rem' className='icon-primary' /> : <IconListOff size='1.25rem' />}
|
||||
onClick={onToggleList}
|
||||
/>
|
||||
<MiniButton
|
||||
title='Дерево разбора выражения'
|
||||
onClick={handleShowAST}
|
||||
icon={<IconTree size='1.25rem' className='icon-primary' />}
|
||||
/>
|
||||
</Overlay>
|
||||
<ExpressionToolbar
|
||||
disabled={disabled}
|
||||
showControls={showControls}
|
||||
showAST={handleShowAST}
|
||||
toggleControls={() => setShowControls(prev => !prev)}
|
||||
/>
|
||||
|
||||
<Overlay position='top-[-0.5rem] pl-[8rem] sm:pl-[4rem] right-1/2 translate-x-1/2 flex'>
|
||||
<StatusBar
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { IconControls, IconText, IconTextOff, IconTree } from '@/components/Icons';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
import { useConceptOptions } from '@/context/OptionsContext';
|
||||
import { useRSForm } from '@/context/RSFormContext';
|
||||
|
||||
interface ExpressionToolbarProps {
|
||||
disabled?: boolean;
|
||||
showControls: boolean;
|
||||
|
||||
toggleControls: () => void;
|
||||
showAST: () => void;
|
||||
}
|
||||
|
||||
function ExpressionToolbar({ disabled, showControls, toggleControls, showAST }: ExpressionToolbarProps) {
|
||||
const model = useRSForm();
|
||||
const { mathFont, setMathFont } = useConceptOptions();
|
||||
|
||||
function toggleFont() {
|
||||
setMathFont(mathFont === 'math' ? 'math2' : 'math');
|
||||
}
|
||||
|
||||
return (
|
||||
<Overlay position='top-[-0.5rem] right-0 cc-icons'>
|
||||
<MiniButton
|
||||
title='Изменить шрифт'
|
||||
onClick={toggleFont}
|
||||
icon={
|
||||
mathFont === 'math' ? <IconText size='1.25rem' className='icon-primary' /> : <IconTextOff size='1.25rem' />
|
||||
}
|
||||
/>
|
||||
{!disabled || model.processing ? (
|
||||
<MiniButton
|
||||
title='Отображение специальной клавиатуры'
|
||||
icon={<IconControls size='1.25rem' className={showControls ? 'icon-primary' : ''} />}
|
||||
onClick={toggleControls}
|
||||
/>
|
||||
) : null}
|
||||
<MiniButton
|
||||
title='Дерево разбора выражения'
|
||||
onClick={showAST}
|
||||
icon={<IconTree size='1.25rem' className='icon-primary' />}
|
||||
/>
|
||||
</Overlay>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExpressionToolbar;
|
|
@ -1,3 +1,4 @@
|
|||
import clsx from 'clsx';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { TokenID } from '@/models/rslang';
|
||||
|
@ -90,7 +91,13 @@ interface RSEditorControlsProps {
|
|||
function RSEditorControls({ isOpen, disabled, onEdit }: RSEditorControlsProps) {
|
||||
return (
|
||||
<motion.div
|
||||
className='flex-wrap text-xs select-none sm:text-sm divide-solid'
|
||||
className={clsx(
|
||||
'max-w-[38.5rem] sm:max-w-[40rem] sm:min-w-[40rem] md:max-w-fit mx-1 sm:mx-0',
|
||||
'flex-wrap',
|
||||
'divide-solid',
|
||||
'text-xs md:text-sm',
|
||||
'select-none'
|
||||
)}
|
||||
initial={false}
|
||||
animate={isOpen ? 'open' : 'closed'}
|
||||
variants={animateRSControl}
|
||||
|
|
|
@ -26,8 +26,8 @@ function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps) {
|
|||
'font-math',
|
||||
'cursor-pointer disabled:cursor-default',
|
||||
{
|
||||
'w-[3.4rem] sm:w-[4.5rem]': label.length > 3,
|
||||
'w-[1.7rem] sm:w-[2.25rem]': label.length <= 3
|
||||
'w-[3.7rem] md:w-[4.5rem]': label.length > 3,
|
||||
'w-[1.85rem] md:w-[2.25rem]': label.length <= 3
|
||||
}
|
||||
)}
|
||||
data-tooltip-id={globals.tooltip}
|
||||
|
|
|
@ -30,7 +30,7 @@ function ViewConstituents({ expression, schema, activeCst, isBottom, onOpenEdit
|
|||
const table = useMemo(
|
||||
() => (
|
||||
<ConstituentsTable
|
||||
maxHeight={isBottom ? '12rem' : calculateHeight('8.2rem')}
|
||||
maxHeight={isBottom ? calculateHeight('42rem') : calculateHeight('8.2rem')}
|
||||
items={filteredData}
|
||||
activeCst={activeCst}
|
||||
onOpenEdit={onOpenEdit}
|
||||
|
@ -46,7 +46,7 @@ function ViewConstituents({ expression, schema, activeCst, isBottom, onOpenEdit
|
|||
'border overflow-hidden', // prettier: split-lines
|
||||
{
|
||||
'mt-[2.2rem] rounded-l-md rounded-r-none': !isBottom, // prettier: split-lines
|
||||
'mt-3 mx-6 rounded-md': isBottom
|
||||
'mt-3 mx-6 rounded-md md:w-[45.8rem]': isBottom
|
||||
}
|
||||
)}
|
||||
initial={{ ...animateSideView.initial }}
|
||||
|
|
Loading…
Reference in New Issue
Block a user