Compare commits

...

8 Commits

Author SHA1 Message Date
IRBorisov
e22da6881c try fixing disabled inputs
Some checks are pending
Frontend CI / build (18.x) (push) Waiting to run
2024-06-10 21:25:11 +03:00
IRBorisov
c47e5373e2 Improve help UI 2024-06-10 11:57:48 +03:00
IRBorisov
decd0da6cd Improve help UI for small screens 2024-06-09 20:40:41 +03:00
IRBorisov
3d2cf353f3 UI: Improve readonly mode 2024-06-09 15:18:52 +03:00
IRBorisov
4c3ca1bb39 Fix convention display if newline is present 2024-06-08 21:53:16 +03:00
IRBorisov
0679e1ddcd Remove text-adjust for Safari 2024-06-08 21:44:30 +03:00
IRBorisov
1c15f987bf Fix dark mode detection 2024-06-08 21:31:11 +03:00
IRBorisov
c9edf68264 Small navigation fix for touch accuracy 2024-06-07 23:17:49 +03:00
38 changed files with 214 additions and 97 deletions

View File

@ -155,6 +155,7 @@
"Булеан",
"Бурбаки",
"Версионирование",
"Владельцом",
"Десинглетон",
"доксинг",
"интерпретируемости",

View File

@ -22,11 +22,14 @@
<title>Концепт Портал</title>
<script>
if (
localStorage.getItem('darkMode') === 'true' ||
localStorage.getItem('color-theme') === 'dark' ||
(!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
let isDark = false;
if ('portal.theme.dark' in localStorage) {
isDark = localStorage.getItem('portal.theme.dark') === 'true';
} else if (window.matchMedia) {
isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
localStorage.setItem('portal.theme.dark', isDark ? 'true' : 'false');
}
if (isDark) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');

View File

@ -1,3 +1,2 @@
User-agent: *
Allow: /
Disallow: /library

View File

@ -47,7 +47,7 @@ function Navigation() {
<div tabIndex={-1} className='flex items-center mr-auto cursor-pointer' onClick={navigateHome}>
<Logo />
</div>
<div className='flex'>
<div className='flex gap-1 py-[0.3rem]'>
<NavigationButton
text='Новая схема'
title='Создать новую схему'

View File

@ -23,6 +23,7 @@ function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }:
'mr-1 h-full', // prettier: split lines
'flex items-center gap-1',
'clr-btn-nav',
'rounded-xl',
'font-controls whitespace-nowrap',
{
'px-2': text,

View File

@ -33,7 +33,8 @@ function Tooltip({
delayHide={100}
opacity={0.97}
className={clsx(
'overflow-auto sm:overflow-hidden overscroll-contain',
'max-h-[calc(100svh-6rem)]',
'overflow-y-auto overflow-x-hidden sm:overflow-hidden overscroll-contain',
'border shadow-md',
'text-balance',
layer,

View File

@ -14,6 +14,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
import { inferTemplatedType, substituteTemplateArgs } from '@/models/rslangAPI';
import { PARAMETER } from '@/utils/constants';
import FormCreateCst from '../DlgCreateCst/FormCreateCst';
import ArgumentsTab, { IArgumentsState } from './ArgumentsTab';
@ -144,7 +145,11 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
onSubmit={handleSubmit}
>
<Overlay position='top-0 right-[6rem]'>
<BadgeHelp topic={HelpTopic.RSL_TEMPLATES} className='max-w-[40rem]' offset={12} />
<BadgeHelp
topic={HelpTopic.RSL_TEMPLATES}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={12}
/>
</Overlay>
<Tabs
selectedTabClassName='clr-selected'

View File

@ -1,5 +1,6 @@
'use client';
import clsx from 'clsx';
import { AnimatePresence } from 'framer-motion';
import { useLayoutEffect, useMemo, useState } from 'react';
@ -12,6 +13,7 @@ import AnimateFade from '@/components/wrap/AnimateFade';
import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, isBaseSet, isBasicConcept, isFunctional, validateNewAlias } from '@/models/rsformAPI';
import { PARAMETER } from '@/utils/constants';
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
@ -52,7 +54,11 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
value={{ value: state.cst_type, label: labelCstType(state.cst_type) }}
onChange={data => partialUpdate({ cst_type: data?.value ?? CstType.BASE })}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} className='max-w-[40rem] max-h-[calc(100svh-2rem)]' />
<BadgeHelp
topic={HelpTopic.CC_CONSTITUENTA}
offset={16}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
/>
<TextInput
id='dlg_cst_alias'
dense

View File

@ -11,6 +11,7 @@ import TabLabel from '@/components/ui/TabLabel';
import { ReferenceType } from '@/models/language';
import { HelpTopic } from '@/models/miscellaneous';
import { IRSForm } from '@/models/rsform';
import { PARAMETER } from '@/utils/constants';
import { labelReferenceType } from '@/utils/labels';
import EntityTab from './EntityTab';
@ -69,10 +70,14 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
hideWindow={hideWindow}
canSubmit={isValid}
onSubmit={handleSubmit}
className='w-[40rem] px-6 min-h-[34rem]'
className='w-[40rem] px-6 min-h-[35rem]'
>
<Overlay position='top-0 right-[4rem]'>
<BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[35rem]' offset={14} />
<Overlay position='top-0 right-0'>
<BadgeHelp
topic={HelpTopic.TERM_CONTROL}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={14}
/>
</Overlay>
<Tabs
@ -82,15 +87,10 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
onSelect={setActiveTab}
>
<TabList className={clsx('mb-3 self-center', 'flex', 'border divide-x rounded-none')}>
<TabLabel
title='Отсылка на термин в заданной словоформе'
label={labelReferenceType(ReferenceType.ENTITY)}
className='w-[12rem]'
/>
<TabLabel title='Отсылка на термин в заданной словоформе' label={labelReferenceType(ReferenceType.ENTITY)} />
<TabLabel
title='Установление синтаксической связи с отсылкой на термин'
label={labelReferenceType(ReferenceType.SYNTACTIC)}
className='w-[12rem]'
/>
</TabList>

View File

@ -22,7 +22,7 @@ function SelectWordForm({ selected, setSelected }: SelectWordFormProps) {
);
return (
<div className='text-sm'>
<div className='text-xs sm:text-sm'>
{DefaultWordForms.slice(0, 12).map((data, index) => (
<WordformButton
key={`${prefixes.wordform_list}${index}`}

View File

@ -17,7 +17,7 @@ function WordformButton({ text, example, grams, onSelectGrams, isSelected, ...re
tabIndex={-1}
onClick={() => onSelectGrams(grams)}
className={clsx(
'min-w-[6.15rem]',
'min-w-[4.15rem] sm:min-w-[6.15rem]',
'p-1',
'border rounded-none',
'cursor-pointer',

View File

@ -16,6 +16,7 @@ import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '@/models/lang
import { parseGrammemes, wordFormEquals } from '@/models/languageAPI';
import { HelpTopic } from '@/models/miscellaneous';
import { IConstituenta, TermForm } from '@/models/rsform';
import { PARAMETER } from '@/utils/constants';
import { prompts } from '@/utils/labels';
import { IGrammemeOption, SelectorGrammemes, SelectorGrammemesList } from '@/utils/selectors';
@ -131,7 +132,11 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
className='flex flex-col w-[40rem] px-6'
>
<Overlay position='top-[-0.2rem] left-[8rem]'>
<BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} />
<BadgeHelp
topic={HelpTopic.TERM_CONTROL}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={3}
/>
</Overlay>
<TextArea
@ -179,33 +184,36 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
/>
</div>
<Overlay position='top-2 left-0'>
<MiniButton
noHover
title='Внести словоформу'
icon={<IconAccept size='1.5rem' className='icon-green' />}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
noHover
title='Генерировать стандартные словоформы'
icon={<IconMoveDown size='1.5rem' className='icon-primary' />}
disabled={textProcessor.loading || !inputText}
onClick={handleGenerateLexeme}
/>
</Overlay>
<div className={clsx('mt-3 mb-2', 'flex self-center items-center', 'text-sm text-center font-semibold')}>
<span>Заданные вручную словоформы [{forms.length}]</span>
<MiniButton
noHover
title='Сбросить все словоформы'
className='py-0'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={textProcessor.loading || forms.length === 0}
onClick={handleResetAll}
/>
<div className='flex justify-between'>
<div className='cc-icons'>
<MiniButton
noHover
title='Внести словоформу'
icon={<IconAccept size='1.5rem' className='icon-green' />}
disabled={textProcessor.loading || !inputText || inputGrams.length == 0}
onClick={handleAddForm}
/>
<MiniButton
noHover
title='Генерировать стандартные словоформы'
icon={<IconMoveDown size='1.5rem' className='icon-primary' />}
disabled={textProcessor.loading || !inputText}
onClick={handleGenerateLexeme}
/>
</div>
<div
className={clsx('mt-3 mb-2', 'w-full flex justify-center items-center', 'text-sm text-center font-semibold')}
>
<div>Заданные вручную словоформы [{forms.length}]</div>
<MiniButton
noHover
title='Сбросить все словоформы'
className='py-0'
icon={<IconRemove size='1.5rem' className='icon-red' />}
disabled={textProcessor.loading || forms.length === 0}
onClick={handleResetAll}
/>
</div>
</div>
<WordFormsTable forms={forms} setForms={setForms} onFormSelect={handleSelectForm} />

View File

@ -12,6 +12,7 @@ import usePartialUpdate from '@/hooks/usePartialUpdate';
import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstRenameData } from '@/models/rsform';
import { generateAlias, validateNewAlias } from '@/models/rsformAPI';
import { PARAMETER } from '@/utils/constants';
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
@ -47,7 +48,7 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
hideWindow={hideWindow}
canSubmit={validated}
onSubmit={handleSubmit}
className={clsx('w-[30rem]', 'py-6 px-6 flex gap-3 justify-center items-center')}
className={clsx('w-[30rem]', 'py-6 pr-3 pl-6 flex justify-center items-center')}
>
<SelectSingle
id='dlg_cst_type'
@ -60,15 +61,20 @@ function DlgRenameCst({ hideWindow, initial, onRename }: DlgRenameCstProps) {
}}
onChange={data => updateData({ cst_type: data?.value ?? CstType.BASE })}
/>
<BadgeHelp topic={HelpTopic.CC_CONSTITUENTA} offset={16} className='max-w-[40rem] max-h-[calc(100svh-2rem)]' />
<TextInput
id='dlg_cst_alias'
dense
label='Имя'
className='w-[7rem]'
className='w-[7rem] ml-3'
value={cstData.alias}
onChange={event => updateData({ alias: event.target.value })}
/>
<BadgeHelp
topic={HelpTopic.CC_CONSTITUENTA}
offset={16}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
/>
</Modal>
);
}

View File

@ -11,7 +11,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import { SyntaxTree } from '@/models/rslang';
import { graphDarkT, graphLightT } from '@/styling/color';
import { colorBgSyntaxTree } from '@/styling/color';
import { resources } from '@/utils/constants';
import { PARAMETER, resources } from '@/utils/constants';
import { labelSyntaxTree } from '@/utils/labels';
interface DlgShowASTProps extends Pick<ModalProps, 'hideWindow'> {
@ -55,7 +55,7 @@ function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
return (
<Modal readonly hideWindow={hideWindow} className='px-6'>
<Overlay position='left-[-1rem] top-[0.25rem]'>
<BadgeHelp topic={HelpTopic.UI_FORMULA_TREE} className='max-w-[32rem]' />
<BadgeHelp topic={HelpTopic.UI_FORMULA_TREE} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
<div className='my-2 text-lg text-center'>
{!hoverNode ? expression : null}

View File

@ -47,6 +47,7 @@ export enum HelpTopic {
UI_FORMULA_TREE = 'ui-formula-tree',
UI_CST_STATUS = 'ui-rsform-cst-status',
UI_CST_CLASS = 'ui-rsform-cst-class',
UI_OSS_GRAPH = 'ui-oss-graph',
CONCEPTUAL = 'concept',
CC_SYSTEM = 'concept-rsform',
@ -91,6 +92,7 @@ export const topicParent: Map<HelpTopic, HelpTopic> = new Map([
[HelpTopic.UI_FORMULA_TREE, HelpTopic.INTERFACE],
[HelpTopic.UI_CST_STATUS, HelpTopic.INTERFACE],
[HelpTopic.UI_CST_CLASS, HelpTopic.INTERFACE],
[HelpTopic.UI_OSS_GRAPH, HelpTopic.INTERFACE],
[HelpTopic.CONCEPTUAL, HelpTopic.CONCEPTUAL],
[HelpTopic.CC_SYSTEM, HelpTopic.CONCEPTUAL],

View File

@ -14,7 +14,7 @@ import SelectorButton from '@/components/ui/SelectorButton';
import useDropdown from '@/hooks/useDropdown';
import { LocationHead } from '@/models/library';
import { HelpTopic } from '@/models/miscellaneous';
import { prefixes } from '@/utils/constants';
import { PARAMETER, prefixes } from '@/utils/constants';
import { describeLocationHead, labelLocationHead } from '@/utils/labels';
import { tripleToggleColor } from '@/utils/utils';
@ -170,7 +170,12 @@ function SearchPanel({
/>
</div>
<BadgeHelp topic={HelpTopic.UI_LIBRARY} className='max-w-[28rem] text-sm' offset={5} place='right-start' />
<BadgeHelp
topic={HelpTopic.UI_LIBRARY}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'text-sm')}
offset={5}
place='right-start'
/>
</div>
);
}

View File

@ -4,6 +4,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import HelpAccess from './items/HelpAccess';
import HelpAPI from './items/HelpAPI';
import HelpConcept from './items/HelpConcept';
import HelpConceptOSS from './items/HelpConceptOSS';
import HelpConceptRelations from './items/HelpConceptRelations';
import HelpConceptSynthesis from './items/HelpConceptSynthesis';
import HelpConceptSystem from './items/HelpConceptSystem';
@ -17,7 +18,7 @@ import HelpFormulaTree from './items/HelpFormulaTree';
import HelpInfo from './items/HelpInfo';
import HelpInterface from './items/HelpInterface';
import HelpLibrary from './items/HelpLibrary';
import HelpOSS from './items/HelpOSS';
import HelpOssGraph from './items/HelpOssGraph';
import HelpPortal from './items/HelpPortal';
import HelpPrivacy from './items/HelpPrivacy';
import HelpRSFormCard from './items/HelpRSFormCard';
@ -60,13 +61,14 @@ function TopicPage({ topic }: TopicPageProps) {
if (topic === HelpTopic.UI_FORMULA_TREE) return <HelpFormulaTree />;
if (topic === HelpTopic.UI_CST_STATUS) return <HelpCstStatus />;
if (topic === HelpTopic.UI_CST_CLASS) return <HelpCstClass />;
if (topic === HelpTopic.UI_OSS_GRAPH) return <HelpOssGraph />;
if (topic === HelpTopic.CONCEPTUAL) return <HelpConcept />;
if (topic === HelpTopic.CC_SYSTEM) return <HelpConceptSystem />;
if (topic === HelpTopic.CC_CONSTITUENTA) return <HelpCstAttributes />;
if (topic === HelpTopic.CC_RELATIONS) return <HelpConceptRelations />;
if (topic === HelpTopic.CC_SYNTHESIS) return <HelpConceptSynthesis />;
if (topic === HelpTopic.CC_OSS) return <HelpOSS />;
if (topic === HelpTopic.CC_OSS) return <HelpConceptOSS />;
if (topic === HelpTopic.RSLANG) return <HelpRSLang />;
if (topic === HelpTopic.RSL_TYPES) return <HelpRSLangTypes />;

View File

@ -1,8 +1,31 @@
import { IconHide, IconImmutable, IconPrivate, IconProtected, IconPublic } from '@/components/Icons';
function HelpAccess() {
return (
<div>
<h1>Организация доступов</h1>
<p>TBD.</p>
<p>Редактирование контента осуществляется Редакторами и Владельцом.</p>
<p>Редактирование прав и доступов осуществляется Владельцом.</p>
<p>
Доступ к контенту на Портале может быть ограничен владельцем каждой схемы в рамках <b>политики доступа</b>.
</p>
<li>
<IconPublic className='inline-icon icon-green' /> публичная политика не ограничивает чтение схемы
</li>
<li>
<IconProtected className='inline-icon icon-blue' /> защитная политика запрещает доступ для всех кроме редакторов
и владельца схемы
</li>
<li>
<IconPrivate className='inline-icon icon-red' /> личная политика оставляет доступ к схеме только владельцу
</li>
<li>
<IconHide className='inline-icon' /> режим скрытия схемы из списка в Библиотеке не ограничивает доступ к схеме
по прямой ссылке
</li>
<li>
<IconImmutable className='inline-icon' /> режим защиты от редактирования предохраняет от случайных изменений
</li>
</div>
);
}

View File

@ -0,0 +1,27 @@
import LinkTopic from '@/components/ui/LinkTopic';
import { HelpTopic } from '@/models/miscellaneous';
function HelpConceptOSS() {
return (
<div>
<h1>Операционная схема синтеза</h1>
<p>
Работа со сложными предметными областями требует многократного{' '}
<LinkTopic text='синтеза' topic={HelpTopic.CC_SYNTHESIS} /> для построения целевых понятий. Последовательность
синтезов концептуальных схем задается с помощью <b>Операционной схемы синтеза (ОСС)</b> в форме Графа синтеза.
</p>
<p>
Отдельные операции в рамках ОСС задаются <b>таблицами отождествлений</b> понятий из синтезируемых схем. Таким
образом <LinkTopic text='конституенты' topic={HelpTopic.CC_CONSTITUENTA} /> в каждой КС разделяются на
наследованные, отождествленные и дописанные.
</p>
<p>
Портал поддерживает <b>сквозные изменения</b> в рамках ОСС. Изменения, внесенные в исходные концептуальные схемы
автоматически проносятся через граф синтеза (путем обновления наследованных конституент). Формальные определения
наследованных конституент можно редактировать только путем изменения исходных конституент.
</p>
</div>
);
}
export default HelpConceptOSS;

View File

@ -5,10 +5,8 @@ function HelpFormulaTree() {
return (
<div>
<h1>Дерево разбора выражения</h1>
<p>
Дерево разбора получено путем семантических преобразований дерева синтаксического разбора. Оно отражает
структуру грамматически корректного выражения языка родов структур.
</p>
<p>Дерево получено путем семантических преобразований дерева синтаксического разбора.</p>
<p>Оно отражает структуру грамматически корректного выражения языка родов структур.</p>
<li>Порядок узлов в рамках одного уровня может отличаться от их порядка в выражении</li>
<li>При наведении курсора на узел в тексте выделяется соответствующий ему фрагмент</li>
<li>Текст в узле дерева соответствует элементу языка</li>

View File

@ -1,10 +0,0 @@
function HelpOSS() {
return (
<div>
<h1>Операционная схема синтеза</h1>
<p>TBD.</p>
</div>
);
}
export default HelpOSS;

View File

@ -0,0 +1,10 @@
function HelpOssGraph() {
return (
<div>
<h1>Граф синтеза</h1>
<p>TBD.</p>
</div>
);
}
export default HelpOssGraph;

View File

@ -26,8 +26,8 @@ function HelpTermGraph() {
const { colors } = useConceptOptions();
return (
<div className='flex flex-col'>
<div className='flex'>
<div className='dense w-[14rem]'>
<div className='flex flex-col sm:flex-row'>
<div className='w-full sm:w-[14rem]'>
<h1>Настройка графа</h1>
<li>Цвет покраска узлов</li>
<li>Граф расположение</li>
@ -43,9 +43,9 @@ function HelpTermGraph() {
</li>
</div>
<Divider vertical margins='mx-3 mt-3' />
<Divider vertical margins='mx-3 mt-3' className='hidden sm:block' />
<div className='dense w-[21rem]'>
<div className='w-full sm:w-[21rem]'>
<h1>Изменение узлов</h1>
<li>Клик на конституенту выделение</li>
<li>
@ -66,10 +66,10 @@ function HelpTermGraph() {
</div>
</div>
<Divider margins='my-3' />
<Divider margins='my-3' className='hidden sm:block' />
<div className='flex mb-3'>
<div className='dense w-[14rem]'>
<div className='flex mb-3 flex-col-reverse sm:flex-row'>
<div className='w-full sm:w-[14rem]'>
<h1>Общие</h1>
<li>
<IconFilter className='inline-icon' /> Открыть настройки
@ -82,7 +82,7 @@ function HelpTermGraph() {
</li>
</div>
<Divider vertical margins='mx-3' />
<Divider vertical margins='mx-3' className='hidden sm:block' />
<div className='dense w-[21rem]'>
<h1>Выделение</h1>

View File

@ -10,6 +10,7 @@ import Overlay from '@/components/ui/Overlay';
import { useAccessMode } from '@/context/AccessModeContext';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels';
import { useOssEdit } from '../OssEditContext';
@ -57,7 +58,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, onSubmit, onDestroy }:
onClick={onDestroy}
/>
) : null}
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className='max-w-[30rem]' />
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -13,6 +13,7 @@ import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip, tooltips } from '@/utils/labels';
interface ConstituentaToolbarProps {
@ -94,7 +95,7 @@ function ConstituentaToolbar({
disabled={disabled || modified}
onClick={onMoveDown}
/>
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} />
<BadgeHelp topic={HelpTopic.UI_RS_EDITOR} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -30,10 +30,10 @@ function ControlsOverlay({ constituenta, disabled, modified, processing, onRenam
) : null}
<div
className={clsx(
'pt-1 pl-[1.375rem]', // prettier: split lines
'pt-1 sm:pl-[1.375rem] pl-1', // prettier: split lines
'text-sm font-medium whitespace-nowrap',
'select-text cursor-default',
disabled && !processing && 'pl-[2.8rem]'
disabled && !processing && 'pl-[1.6rem] sm:pl-[2.8rem]'
)}
>
<span>Имя </span>

View File

@ -159,7 +159,7 @@ function FormConstituenta({
disabled={true}
label='Типизация'
value={typification}
colors='clr-app'
colors='clr-app clr-text-default'
/>
<AnimatePresence>
<AnimateFade key='cst_expression_fade' hideContent={!!state && !state?.definition_formal && isElementary}>
@ -204,12 +204,11 @@ function FormConstituenta({
<TextArea
id='cst_convention'
spellCheck
className='min-h-[3.75rem]'
label={isBasic ? 'Конвенция' : 'Комментарий'}
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
value={convention}
disabled={disabled}
rows={convention.length > 2 * ROW_SIZE_IN_CHARACTERS ? 3 : 2}
rows={convention.length > 2 * ROW_SIZE_IN_CHARACTERS || convention.includes('\n') ? 4 : 2}
onChange={event => setConvention(event.target.value)}
/>
</AnimateFade>

View File

@ -21,7 +21,7 @@ function ExpressionToolbar({ disabled, showControls, toggleControls, showAST }:
}
return (
<Overlay position='top-[-0.5rem] right-0 cc-icons'>
<Overlay position='top-[-0.5rem] right-0' className='cc-icons'>
<MiniButton
title='Изменить шрифт'
onClick={toggleFont}

View File

@ -41,10 +41,12 @@ function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze
tabIndex={0}
className={clsx(
'w-[10rem] h-[1.75rem]',
'scale-75 sm:scale-100 mx-[-2.5rem] sm:m-0',
'px-2 flex items-center justify-center gap-2',
'border',
'select-none',
'cursor-pointer',
'translate-x-[-1.5rem]',
'focus-frame',
'duration-500 transition-colors'
)}

View File

@ -11,6 +11,7 @@ import { useAccessMode } from '@/context/AccessModeContext';
import { AccessPolicy, ILibraryItemEditor } from '@/models/library';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
interface AccessToolbarProps {
visible: boolean;
@ -59,7 +60,7 @@ function AccessToolbar({ visible, toggleVisible, readOnly, toggleReadOnly, contr
disabled={accessLevel === UserLevel.READER || controller.isProcessing}
/>
<BadgeHelp topic={HelpTopic.ACCESS} className='max-w-[30rem]' offset={4} />
<BadgeHelp topic={HelpTopic.ACCESS} className={PARAMETER.TOOLTIP_WIDTH} offset={4} />
</div>
</Overlay>
);

View File

@ -10,6 +10,7 @@ import Overlay from '@/components/ui/Overlay';
import { useAccessMode } from '@/context/AccessModeContext';
import { HelpTopic } from '@/models/miscellaneous';
import { UserLevel } from '@/models/user';
import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels';
import { useRSEdit } from '../RSEditContext';
@ -57,7 +58,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, onSubmit, onDestroy }:
onClick={onDestroy}
/>
) : null}
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className='max-w-[30rem]' />
<BadgeHelp topic={HelpTopic.UI_RS_CARD} offset={4} className={PARAMETER.TOOLTIP_WIDTH} />
</Overlay>
);
}

View File

@ -3,6 +3,7 @@ import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { useRSEdit } from '../RSEditContext';
@ -34,7 +35,7 @@ function VersionsToolbar() {
/>
</>
) : null}
<BadgeHelp topic={HelpTopic.VERSIONS} className='max-w-[30rem]' offset={4} />
<BadgeHelp topic={HelpTopic.VERSIONS} className={PARAMETER.TOOLTIP_WIDTH} offset={4} />
</Overlay>
);
}

View File

@ -1,3 +1,5 @@
import clsx from 'clsx';
import {
IconClustering,
IconClusteringOff,
@ -13,6 +15,7 @@ import {
import BadgeHelp from '@/components/info/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton';
import { HelpTopic } from '@/models/miscellaneous';
import { PARAMETER } from '@/utils/constants';
import { useRSEdit } from '../RSEditContext';
@ -111,7 +114,11 @@ function GraphToolbar({
title='Сохранить изображение'
onClick={onSaveImage}
/>
<BadgeHelp topic={HelpTopic.UI_GRAPH_TERM} className='max-w-[calc(100vw-4rem)]' offset={4} />
<BadgeHelp
topic={HelpTopic.UI_GRAPH_TERM}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
offset={4}
/>
</div>
);
}

View File

@ -4,9 +4,11 @@ import clsx from 'clsx';
import { motion } from 'framer-motion';
import { useMemo, useState } from 'react';
import { useAccessMode } from '@/context/AccessModeContext';
import { useConceptOptions } from '@/context/OptionsContext';
import useWindowSize from '@/hooks/useWindowSize';
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
import { UserLevel } from '@/models/user';
import { animateSideView } from '@/styling/animations';
import ConstituentsSearch from './ConstituentsSearch';
@ -29,20 +31,25 @@ interface ViewConstituentsProps {
function ViewConstituents({ expression, schema, activeCst, isBottom, onOpenEdit }: ViewConstituentsProps) {
const { calculateHeight } = useConceptOptions();
const windowSize = useWindowSize();
const { accessLevel } = useAccessMode();
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);
const table = useMemo(
() => (
<ConstituentsTable
maxHeight={isBottom ? calculateHeight('42rem', '10rem') : calculateHeight('8.2rem')}
maxHeight={
isBottom
? calculateHeight(accessLevel !== UserLevel.READER ? '42rem' : '35rem', '10rem')
: calculateHeight('8.2rem')
}
items={filteredData}
activeCst={activeCst}
onOpenEdit={onOpenEdit}
denseThreshold={COLUMN_EXPRESSION_HIDE_THRESHOLD}
/>
),
[isBottom, filteredData, activeCst, onOpenEdit, calculateHeight]
[isBottom, filteredData, activeCst, onOpenEdit, calculateHeight, accessLevel]
);
return (

View File

@ -10,6 +10,8 @@
html,
body {
-webkit-text-size-adjust: 100%;
width: 100%;
height: 100%;
margin: 0px;

View File

@ -156,9 +156,13 @@
}
}
.clr-text-default {
:is(.clr-text-default, input:disabled, textarea:disabled) {
opacity: 1;
-webkit-text-fill-color: var(--cl-fg-100);
color: var(--cl-fg-100);
.dark & {
opacity: 1;
-webkit-text-fill-color: var(--cd-fg-100);
color: var(--cd-fg-100);
}
}

View File

@ -16,7 +16,9 @@ export const PARAMETER = {
graphPopupDelay: 500, // milliseconds delay for graph popup selections
graphRefreshDelay: 10, // milliseconds delay for graph viewpoint reset
logicLabel: 'LOGIC'
logicLabel: 'LOGIC',
TOOLTIP_WIDTH: 'max-w-[29rem]'
};
/**

View File

@ -372,6 +372,7 @@ export function labelHelpTopic(topic: HelpTopic): string {
case HelpTopic.UI_FORMULA_TREE: return 'Дерево разбора';
case HelpTopic.UI_CST_STATUS: return 'Статус конституенты';
case HelpTopic.UI_CST_CLASS: return 'Класс конституенты';
case HelpTopic.UI_OSS_GRAPH: return 'Граф синтеза';
case HelpTopic.CONCEPTUAL: return 'Концептуализация';
case HelpTopic.CC_SYSTEM: return 'Система определений';
@ -419,6 +420,7 @@ export function describeHelpTopic(topic: HelpTopic): string {
case HelpTopic.UI_FORMULA_TREE: return 'просмотр дерева разбора <br/>родоструктурного выражения';
case HelpTopic.UI_CST_STATUS: return 'нотация статуса конституенты';
case HelpTopic.UI_CST_CLASS: return 'нотация класса конституенты';
case HelpTopic.UI_OSS_GRAPH: return 'графическая форма <br/>операционной схемы синтеза';
case HelpTopic.CONCEPTUAL: return 'основы концептуализации';
case HelpTopic.CC_SYSTEM: return 'концептуальная схема <br/>как система понятий';