Improve help UI + small fixes

This commit is contained in:
IRBorisov 2024-04-01 19:07:20 +03:00
parent 41af54abd3
commit aff116abbc
60 changed files with 259 additions and 167 deletions

View File

@ -140,6 +140,7 @@
"пересинтез", "пересинтез",
"Родоструктурная", "Родоструктурная",
"Родоструктурное", "Родоструктурное",
"родоструктурной",
"Синглетон", "Синглетон",
"твор", "твор",
"Терминологизация", "Терминологизация",

View File

@ -4,11 +4,11 @@ import ConceptToaster from '@/app/ConceptToaster';
import Footer from '@/app/Footer'; import Footer from '@/app/Footer';
import Navigation from '@/app/Navigation'; import Navigation from '@/app/Navigation';
import { NavigationState } from '@/context/NavigationContext'; import { NavigationState } from '@/context/NavigationContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
function ApplicationLayout() { function ApplicationLayout() {
const { viewportHeight, mainHeight, showScroll } = useConceptTheme(); const { viewportHeight, mainHeight, showScroll } = useConceptOptions();
return ( return (
<NavigationState> <NavigationState>
<div className='min-w-[20rem] clr-app antialiased'> <div className='min-w-[20rem] clr-app antialiased'>

View File

@ -1,11 +1,11 @@
import { ToastContainer, type ToastContainerProps } from 'react-toastify'; import { ToastContainer, type ToastContainerProps } from 'react-toastify';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
interface ToasterThemedProps extends Omit<ToastContainerProps, 'theme'> {} interface ToasterThemedProps extends Omit<ToastContainerProps, 'theme'> {}
function ToasterThemed(props: ToasterThemedProps) { function ToasterThemed(props: ToasterThemedProps) {
const { darkMode } = useConceptTheme(); const { darkMode } = useConceptOptions();
return <ToastContainer theme={darkMode ? 'dark' : 'light'} {...props} />; return <ToastContainer theme={darkMode ? 'dark' : 'light'} {...props} />;
} }

View File

@ -1,12 +1,12 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { urls } from '@/utils/constants'; import { urls } from '@/utils/constants';
import TextURL from '../components/ui/TextURL'; import TextURL from '../components/ui/TextURL';
function Footer() { function Footer() {
const { noNavigation, noFooter } = useConceptTheme(); const { noNavigation, noFooter } = useConceptOptions();
if (noNavigation || noFooter) { if (noNavigation || noFooter) {
return null; return null;
} }

View File

@ -6,7 +6,7 @@ import { pdfjs } from 'react-pdf';
import { AuthState } from '@/context/AuthContext'; import { AuthState } from '@/context/AuthContext';
import { LibraryState } from '@/context/LibraryContext'; import { LibraryState } from '@/context/LibraryContext';
import { ThemeState } from '@/context/ThemeContext'; import { OptionsState } from '@/context/OptionsContext';
import { UsersState } from '@/context/UsersContext'; import { UsersState } from '@/context/UsersContext';
import ErrorFallback from './ErrorFallback'; import ErrorFallback from './ErrorFallback';
@ -33,7 +33,7 @@ function GlobalProviders({ children }: { children: React.ReactNode }) {
onError={logError} onError={logError}
> >
<IntlProvider locale='ru' defaultLocale='ru'> <IntlProvider locale='ru' defaultLocale='ru'>
<ThemeState> <OptionsState>
<UsersState> <UsersState>
<AuthState> <AuthState>
<LibraryState> <LibraryState>
@ -43,7 +43,7 @@ function GlobalProviders({ children }: { children: React.ReactNode }) {
</LibraryState> </LibraryState>
</AuthState> </AuthState>
</UsersState> </UsersState>
</ThemeState> </OptionsState>
</IntlProvider> </IntlProvider>
</ErrorBoundary>); </ErrorBoundary>);
} }

View File

@ -1,10 +1,10 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
function Logo() { function Logo() {
const { darkMode } = useConceptTheme(); const { darkMode } = useConceptOptions();
const size = useWindowSize(); const size = useWindowSize();
return ( return (

View File

@ -5,7 +5,7 @@ import { IoLibrary } from 'react-icons/io5';
import { EducationIcon } from '@/components/Icons'; import { EducationIcon } from '@/components/Icons';
import { useConceptNavigation } from '@/context/NavigationContext'; import { useConceptNavigation } from '@/context/NavigationContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { animateNavigation } from '@/styling/animations'; import { animateNavigation } from '@/styling/animations';
import Logo from './Logo'; import Logo from './Logo';
@ -15,7 +15,7 @@ import UserMenu from './UserMenu';
function Navigation() { function Navigation() {
const router = useConceptNavigation(); const router = useConceptNavigation();
const { noNavigationAnimation } = useConceptTheme(); const { noNavigationAnimation } = useConceptOptions();
const navigateHome = () => router.push('/'); const navigateHome = () => router.push('/');
const navigateLibrary = () => router.push('/library'); const navigateLibrary = () => router.push('/library');

View File

@ -2,11 +2,11 @@ import clsx from 'clsx';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { RiPushpinFill, RiUnpinLine } from 'react-icons/ri'; import { RiPushpinFill, RiUnpinLine } from 'react-icons/ri';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { animateNavigationToggle } from '@/styling/animations'; import { animateNavigationToggle } from '@/styling/animations';
function ToggleNavigationButton() { function ToggleNavigationButton() {
const { noNavigationAnimation, toggleNoNavigation } = useConceptTheme(); const { noNavigationAnimation, toggleNoNavigation } = useConceptOptions();
return ( return (
<motion.button <motion.button
type='button' type='button'

View File

@ -1,8 +1,10 @@
import { LuLightbulb, LuLightbulbOff, LuLogOut, LuMoon, LuSun, LuUserCircle2 } from 'react-icons/lu';
import Dropdown from '@/components/ui/Dropdown'; import Dropdown from '@/components/ui/Dropdown';
import DropdownButton from '@/components/ui/DropdownButton'; import DropdownButton from '@/components/ui/DropdownButton';
import { useAuth } from '@/context/AuthContext'; import { useAuth } from '@/context/AuthContext';
import { useConceptNavigation } from '@/context/NavigationContext'; import { useConceptNavigation } from '@/context/NavigationContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
interface UserDropdownProps { interface UserDropdownProps {
isOpen: boolean; isOpen: boolean;
@ -10,29 +12,51 @@ interface UserDropdownProps {
} }
function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) { function UserDropdown({ isOpen, hideDropdown }: UserDropdownProps) {
const { darkMode, toggleDarkMode } = useConceptTheme(); const { darkMode, toggleDarkMode, showHelp, toggleShowHelp } = useConceptOptions();
const router = useConceptNavigation(); const router = useConceptNavigation();
const { user, logout } = useAuth(); const { user, logout } = useAuth();
const navigateProfile = () => { function navigateProfile() {
hideDropdown(); hideDropdown();
router.push('/profile'); router.push('/profile');
}; }
const logoutAndRedirect = () => { function logoutAndRedirect() {
hideDropdown(); hideDropdown();
logout(() => router.push('/login/')); logout(() => router.push('/login/'));
}; }
function handleToggleDarkMode() {
hideDropdown();
toggleDarkMode();
}
return ( return (
<Dropdown className='w-36' stretchLeft isOpen={isOpen}> <Dropdown className='min-w-[18ch] max-w-[12rem]' stretchLeft isOpen={isOpen}>
<DropdownButton text={user?.username} title='Профиль пользователя' onClick={navigateProfile} />
<DropdownButton <DropdownButton
text={darkMode ? 'Светлая тема' : 'Темная тема'} text={user?.username}
title='Переключение темы оформления' title='Профиль пользователя'
onClick={toggleDarkMode} icon={<LuUserCircle2 size='1rem' />}
onClick={navigateProfile}
/>
<DropdownButton
text={darkMode ? 'Тема: Темная' : 'Тема: Светлая'}
icon={darkMode ? <LuMoon size='1rem' /> : <LuSun size='1rem' />}
title='Переключение темы оформления'
onClick={handleToggleDarkMode}
/>
<DropdownButton
text={showHelp ? 'Помощь: Вкл' : 'Помощь: Выкл'}
icon={showHelp ? <LuLightbulb size='1rem' /> : <LuLightbulbOff size='1rem' />}
title='Отображение иконок подсказок'
onClick={toggleShowHelp}
/>
<DropdownButton
text='Выйти...'
className='font-semibold'
icon={<LuLogOut size='1rem' />}
onClick={logoutAndRedirect}
/> />
<DropdownButton text='Выйти...' className='font-semibold' onClick={logoutAndRedirect} />
</Dropdown> </Dropdown>
); );
} }

View File

@ -9,8 +9,8 @@ import { EditorView } from 'codemirror';
import { forwardRef, useCallback, useMemo, useRef } from 'react'; import { forwardRef, useCallback, useMemo, useRef } from 'react';
import Label from '@/components/ui/Label'; import Label from '@/components/ui/Label';
import { useConceptOptions } from '@/context/OptionsContext';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext';
import { getFontClassName } from '@/models/miscellaneousAPI'; import { getFontClassName } from '@/models/miscellaneousAPI';
import { generateAlias, getCstTypePrefix, guessCstType } from '@/models/rsformAPI'; import { generateAlias, getCstTypePrefix, guessCstType } from '@/models/rsformAPI';
import { extractGlobals } from '@/models/rslangAPI'; import { extractGlobals } from '@/models/rslangAPI';
@ -49,7 +49,7 @@ const RSInput = forwardRef<ReactCodeMirrorRef, RSInputProps>(
}, },
ref ref
) => { ) => {
const { darkMode, colors, mathFont } = useConceptTheme(); const { darkMode, colors, mathFont } = useConceptOptions();
const { schema } = useRSForm(); const { schema } = useRSForm();
const internalRef = useRef<ReactCodeMirrorRef>(null); const internalRef = useRef<ReactCodeMirrorRef>(null);

View File

@ -11,7 +11,7 @@ import { forwardRef, useCallback, useMemo, useRef, useState } from 'react';
import Label from '@/components/ui/Label'; import Label from '@/components/ui/Label';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import DlgEditReference from '@/dialogs/DlgEditReference'; import DlgEditReference from '@/dialogs/DlgEditReference';
import { ReferenceType } from '@/models/language'; import { ReferenceType } from '@/models/language';
import { IConstituenta } from '@/models/rsform'; import { IConstituenta } from '@/models/rsform';
@ -63,7 +63,7 @@ interface RefsInputInputProps
const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>( const RefsInput = forwardRef<ReactCodeMirrorRef, RefsInputInputProps>(
({ id, label, disabled, items, initialValue, value, resolved, onFocus, onBlur, onChange, ...restProps }, ref) => { ({ id, label, disabled, items, initialValue, value, resolved, onFocus, onBlur, onChange, ...restProps }, ref) => {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptOptions();
const { schema } = useRSForm(); const { schema } = useRSForm();
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { GramData } from '@/models/language'; import { GramData } from '@/models/language';
import { colorFgGrammeme } from '@/styling/color'; import { colorFgGrammeme } from '@/styling/color';
import { labelGrammeme } from '@/utils/labels'; import { labelGrammeme } from '@/utils/labels';
@ -10,7 +10,7 @@ interface GrammemeBadgeProps {
} }
function GrammemeBadge({ grammeme }: GrammemeBadgeProps) { function GrammemeBadge({ grammeme }: GrammemeBadgeProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
return ( return (
<div <div
className={clsx( className={clsx(

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { CstClass } from '@/models/rsform'; import { CstClass } from '@/models/rsform';
import { colorBgCstClass } from '@/styling/color'; import { colorBgCstClass } from '@/styling/color';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
@ -11,7 +11,7 @@ interface InfoCstClassProps {
} }
function InfoCstClass({ header }: InfoCstClassProps) { function InfoCstClass({ header }: InfoCstClassProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
return ( return (
<div className='flex flex-col gap-1 mb-2 dense'> <div className='flex flex-col gap-1 mb-2 dense'>

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ExpressionStatus } from '@/models/rsform'; import { ExpressionStatus } from '@/models/rsform';
import { colorBgCstStatus } from '@/styling/color'; import { colorBgCstStatus } from '@/styling/color';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
@ -11,7 +11,7 @@ interface InfoCstStatusProps {
} }
function InfoCstStatus({ title }: InfoCstStatusProps) { function InfoCstStatus({ title }: InfoCstStatusProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
return ( return (
<div className='flex flex-col gap-1 mb-2 dense'> <div className='flex flex-col gap-1 mb-2 dense'>

View File

@ -2,6 +2,7 @@ import { HelpTopic } from '@/models/miscellaneous';
import HelpAPI from '../man/HelpAPI'; import HelpAPI from '../man/HelpAPI';
import HelpConstituenta from '../man/HelpConstituenta'; import HelpConstituenta from '../man/HelpConstituenta';
import HelpCstAttributes from '../man/HelpCstAttributes';
import HelpExteor from '../man/HelpExteor'; import HelpExteor from '../man/HelpExteor';
import HelpLibrary from '../man/HelpLibrary'; import HelpLibrary from '../man/HelpLibrary';
import HelpMain from '../man/HelpMain'; import HelpMain from '../man/HelpMain';
@ -22,8 +23,9 @@ function InfoTopic({ topic }: InfoTopicProps) {
if (topic === HelpTopic.MAIN) return <HelpMain />; if (topic === HelpTopic.MAIN) return <HelpMain />;
if (topic === HelpTopic.LIBRARY) return <HelpLibrary />; if (topic === HelpTopic.LIBRARY) return <HelpLibrary />;
if (topic === HelpTopic.RSFORM) return <HelpRSFormMeta />; if (topic === HelpTopic.RSFORM) return <HelpRSFormMeta />;
if (topic === HelpTopic.CSTLIST) return <HelpRSFormItems />; if (topic === HelpTopic.CST_ATTRIBUTES) return <HelpCstAttributes />;
if (topic === HelpTopic.CONSTITUENTA) return <HelpConstituenta />; if (topic === HelpTopic.CST_LIST) return <HelpRSFormItems />;
if (topic === HelpTopic.CST_EDITOR) return <HelpConstituenta />;
if (topic === HelpTopic.GRAPH_TERM) return <HelpTermGraph />; if (topic === HelpTopic.GRAPH_TERM) return <HelpTermGraph />;
if (topic === HelpTopic.RSTEMPLATES) return <HelpRSTemplates />; if (topic === HelpTopic.RSTEMPLATES) return <HelpRSTemplates />;
if (topic === HelpTopic.RSLANG) return <HelpRSLang />; if (topic === HelpTopic.RSLANG) return <HelpRSLang />;

View File

@ -1,22 +1,28 @@
import { BiInfoCircle } from 'react-icons/bi'; import { LuLightbulb } from 'react-icons/lu';
import TextURL from '@/components/ui/TextURL'; import TextURL from '@/components/ui/TextURL';
import Tooltip, { PlacesType } from '@/components/ui/Tooltip'; import Tooltip, { PlacesType } from '@/components/ui/Tooltip';
import { useConceptOptions } from '@/context/OptionsContext';
import { HelpTopic } from '@/models/miscellaneous'; import { HelpTopic } from '@/models/miscellaneous';
import InfoTopic from '../info/InfoTopic'; import InfoTopic from '../info/InfoTopic';
import { CProps } from '../props'; import { CProps } from '../props';
interface HelpButtonProps extends CProps.Styling { interface BadgeHelpProps extends CProps.Styling {
topic: HelpTopic; topic: HelpTopic;
offset?: number; offset?: number;
place?: PlacesType; place?: PlacesType;
} }
function HelpButton({ topic, ...restProps }: HelpButtonProps) { function BadgeHelp({ topic, ...restProps }: BadgeHelpProps) {
const { showHelp } = useConceptOptions();
if (!showHelp) {
return null;
}
return ( return (
<div id={`help-${topic}`} className='p-1'> <div id={`help-${topic}`} className='p-1'>
<BiInfoCircle size='1.25rem' className='icon-primary' /> <LuLightbulb size='1.25rem' className='icon-primary' />
<Tooltip clickable anchorSelect={`#help-${topic}`} layer='z-modal-tooltip' {...restProps}> <Tooltip clickable anchorSelect={`#help-${topic}`} layer='z-modal-tooltip' {...restProps}>
<div className='relative' onClick={event => event.stopPropagation()}> <div className='relative' onClick={event => event.stopPropagation()}>
<div className='absolute right-0 text-sm top-[0.4rem] clr-input'> <div className='absolute right-0 text-sm top-[0.4rem] clr-input'>
@ -29,4 +35,4 @@ function HelpButton({ topic, ...restProps }: HelpButtonProps) {
); );
} }
export default HelpButton; export default BadgeHelp;

View File

@ -4,7 +4,7 @@ import Divider from '@/components/ui/Divider';
function HelpConstituenta() { function HelpConstituenta() {
// prettier-ignore // prettier-ignore
return ( return (
<div className='leading-tight'> <div className='dense'>
<h1>Редактор конституент</h1> <h1>Редактор конституент</h1>
<p><b>Сохранить изменения</b>: Ctrl + S или клик по кнопке Сохранить</p> <p><b>Сохранить изменения</b>: Ctrl + S или клик по кнопке Сохранить</p>
<p className='mt-1'><b>Формальное определение</b></p> <p className='mt-1'><b>Формальное определение</b></p>
@ -12,7 +12,7 @@ function HelpConstituenta() {
<p>- специальные конструкции вводятся с помощью кнопок снизу</p> <p>- специальные конструкции вводятся с помощью кнопок снизу</p>
<p className='mt-1'><b>Термин и Определение</b></p> <p className='mt-1'><b>Термин и Определение</b></p>
<p>- Ctrl + Пробел открывает редактирование отсылок</p> <p>- Ctrl + Пробел открывает редактирование отсылок</p>
<p className='mt-1'><b>Список конституент справа</b></p> <p className='mt-1'><b>Список конституент</b></p>
<p>- первая настройка - атрибуты конституенты</p> <p>- первая настройка - атрибуты конституенты</p>
<p>- вторая настройка - отбор по графу термов</p> <p>- вторая настройка - отбор по графу термов</p>
<p>- текущая конституента выделена цветом строки</p> <p>- текущая конституента выделена цветом строки</p>

View File

@ -0,0 +1,30 @@
import { HelpTopic } from '@/models/miscellaneous';
import TextURL from '../ui/TextURL';
function HelpCstAttributes() {
// prettier-ignore
return (
<div className='dense'>
<h1>Аттрибуты конституенты</h1>
<p><b>Термин</b> может быть задан для любой конституенты. Он используется для отсылок текстах в других Терминах и Текстовых определениях</p>
<p><b>Формальное определение</b> строится с помощью формального аппарата <TextURL text='родоструктурной экспликации' href={`/manuals?topic=${HelpTopic.RSLANG}`} /></p>
<p><b>Типизация</b> вычисляется автоматически на основе Формального определения и отражает структуру элементов множества, задаваемого определением</p>
<p><b>Текстовое определение</b> указывается для конституент, у которых есть Формальное определение или Область определения. Оно является текстовой интерпретацией формального определения и может содержать только слова-связки, термины теории множеств и отсылки на Термины ранее введенных конституент</p>
<p><b>Конвенция</b> - договоренность о соотнесении неопределяемого понятия с сущностями в предметной области</p>
<p><b>Комментарий</b> может быть добавлен к любому производному понятию для хранения дополнительной информации</p>
<h2>Неопределяемые понятия</h2>
<p><b>X1, C1</b> - Базисные множества и Константные множества не обладают сложной структурой и определяются Конвенцией. Элементы Константных множеств участвуют в арифметических операциях и порядковых предикатах наряду с мощностями множеств</p>
<p><b>S1 : (X1)</b> - Родовые структуры задаются совокупностью Области определения, Конвенции и набора Аксиом, а также Термином. Согласно Конвенции элементы родовой структуры заполняются из Области определения так, чтобы Аксиомы были выполнены. Родовая структура может быть как множеством, так и элементом или кортежем</p>
<p><b>A1 :== (α,β)S1 (β,α)S1</b> - Аксиомы задаются логическим Формальным определением и по необходимости Конвенцией</p>
<h2>Производные понятия</h2>
<p><b>D1 :== Pr1(S1)</b> - Термы задаются типизированным Формальным определением</p>
<p><b>T1 :== Pr1(S1)=Pr2(S1)</b> - Теоремы определяются логическим Формальным определением</p>
<p><b>F1 :== [σ(X1×X1)] Pr1(σ)\Pr2(σ)</b><br />Терм-функции определяются параметризованным типизированным Формальным определением</p>
<p><b>P1 :== [σ(X1×X1)] card(Pr1(σ)) = card(σ)</b><br />Предикат-функции определяются параметризованным логическим Формальным определением</p>
</div>);
}
export default HelpCstAttributes;

View File

@ -4,13 +4,18 @@ import Divider from '@/components/ui/Divider';
function HelpRSFormItems() { function HelpRSFormItems() {
// prettier-ignore // prettier-ignore
return ( return (
<div> <div className='dense'>
<h1>Горячие клавиши</h1> <h1>Список конституент</h1>
<p><b>Двойной клик / Alt + клик</b> - редактирование конституенты</p> <p>Конституенты обладают уникальным Именем, включающим их тип</p>
<p><b>Клик на квадрат слева</b> - выделение конституенты</p> <p>Список поддерживает выделение и перемещение</p>
<p><b>Alt + вверх/вниз</b> - движение конституент</p> <h2>Управление списком</h2>
<p><b>Delete</b> - удаление конституент</p> <p><b>Клик на строку</b> - выделение</p>
<p><b>Alt + 1-6,Q,W</b> - добавление конституент</p> <p><b>Shift + клик</b> - выделение нескольких</p>
<p><b>Alt + клик</b> - Редактор</p>
<p><b>Двойной клик</b> - Редактор</p>
<p><b>Alt + вверх/вниз</b> - перемещение</p>
<p><b>Delete</b> - удаление</p>
<p><b>Alt + 1-6,Q,W</b> - добавление</p>
<Divider margins='mt-2' /> <Divider margins='mt-2' />
<InfoCstStatus title='Статусы' /> <InfoCstStatus title='Статусы' />
</div>); </div>);

View File

@ -1,8 +1,11 @@
function HelpRSFormMeta() { function HelpRSFormMeta() {
// prettier-ignore // prettier-ignore
return ( return (
<div> <div className='dense'>
<h1>Паспорт схемы</h1> <h1>Карточка схемы</h1>
<p>Концептуальная схема содержит конституенты, формирующие систему терминов и определений</p>
<p>Карточка схемы содержит общую информацию и статистику схемы</p>
<h2>Управление</h2>
<p><b>Сохранить изменения</b>: Ctrl + S или кнопка Сохранить</p> <p><b>Сохранить изменения</b>: Ctrl + S или кнопка Сохранить</p>
<p><b>Владелец</b> обладает правом редактирования</p> <p><b>Владелец</b> обладает правом редактирования</p>
<p><b>Общедоступные</b> схемы доступны для всех</p> <p><b>Общедоступные</b> схемы доступны для всех</p>

View File

@ -6,7 +6,7 @@ function HelpTermGraph() {
// prettier-ignore // prettier-ignore
return ( return (
<div className='flex max-w-[80rem] min-w-[45rem]'> <div className='flex max-w-[80rem] min-w-[45rem]'>
<div> <div className='dense'>
<h1>Настройка графа</h1> <h1>Настройка графа</h1>
<p><b>Цвет</b> - выбор правила покраски узлов</p> <p><b>Цвет</b> - выбор правила покраски узлов</p>
<p><b>Граф</b> - выбор модели расположения узлов</p> <p><b>Граф</b> - выбор модели расположения узлов</p>
@ -20,7 +20,7 @@ function HelpTermGraph() {
<Divider vertical margins='mx-3' /> <Divider vertical margins='mx-3' />
<div> <div className='dense'>
<h1>Клавиши</h1> <h1>Клавиши</h1>
<p><b>Клик на конституенту</b> - выделение</p> <p><b>Клик на конституенту</b> - выделение</p>
<p><b>Клик на выделенную</b> - редактирование</p> <p><b>Клик на выделенную</b> - редактирование</p>

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import DataTable, { createColumnHelper, RowSelectionState } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, RowSelectionState } from '@/components/ui/DataTable';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform'; import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
import { describeConstituenta } from '@/utils/labels'; import { describeConstituenta } from '@/utils/labels';
@ -25,7 +25,7 @@ interface ConstituentaMultiPickerProps {
const columnHelper = createColumnHelper<IConstituenta>(); const columnHelper = createColumnHelper<IConstituenta>();
function ConstituentaMultiPicker({ id, schema, prefixID, rows, selected, setSelected }: ConstituentaMultiPickerProps) { function ConstituentaMultiPicker({ id, schema, prefixID, rows, selected, setSelected }: ConstituentaMultiPickerProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const [rowSelection, setRowSelection] = useState<RowSelectionState>({}); const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
useLayoutEffect(() => { useLayoutEffect(() => {

View File

@ -4,7 +4,7 @@ import { useEffect, useMemo, useState } from 'react';
import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable';
import SearchBar from '@/components/ui/SearchBar'; import SearchBar from '@/components/ui/SearchBar';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { CstMatchMode } from '@/models/miscellaneous'; import { CstMatchMode } from '@/models/miscellaneous';
import { IConstituenta } from '@/models/rsform'; import { IConstituenta } from '@/models/rsform';
import { matchConstituenta } from '@/models/rsformAPI'; import { matchConstituenta } from '@/models/rsformAPI';
@ -43,7 +43,7 @@ function ConstituentaPicker({
onBeginFilter, onBeginFilter,
onSelectValue onSelectValue
}: ConstituentaPickerProps) { }: ConstituentaPickerProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const [filteredData, setFilteredData] = useState<IConstituenta[]>([]); const [filteredData, setFilteredData] = useState<IConstituenta[]>([]);
const [filterText, setFilterText] = useState(initialFilter); const [filterText, setFilterText] = useState(initialFilter);

View File

@ -4,7 +4,7 @@ import { useIntl } from 'react-intl';
import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable';
import SearchBar from '@/components/ui/SearchBar'; import SearchBar from '@/components/ui/SearchBar';
import { useLibrary } from '@/context/LibraryContext'; import { useLibrary } from '@/context/LibraryContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ILibraryItem, LibraryItemID } from '@/models/library'; import { ILibraryItem, LibraryItemID } from '@/models/library';
import { ILibraryFilter } from '@/models/miscellaneous'; import { ILibraryFilter } from '@/models/miscellaneous';
@ -23,7 +23,7 @@ const columnHelper = createColumnHelper<ILibraryItem>();
function SchemaPicker({ id, initialFilter = '', rows = 4, value, onSelectValue }: SchemaPickerProps) { function SchemaPicker({ id, initialFilter = '', rows = 4, value, onSelectValue }: SchemaPickerProps) {
const intl = useIntl(); const intl = useIntl();
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const library = useLibrary(); const library = useLibrary();
const [filterText, setFilterText] = useState(initialFilter); const [filterText, setFilterText] = useState(initialFilter);

View File

@ -9,7 +9,7 @@ import ConstituentaSelector from '@/components/select/ConstituentaSelector';
import DataTable, { createColumnHelper } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper } from '@/components/ui/DataTable';
import Label from '@/components/ui/Label'; import Label from '@/components/ui/Label';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { IConstituenta, IRSForm, ISubstitution } from '@/models/rsform'; import { IConstituenta, IRSForm, ISubstitution } from '@/models/rsform';
import { describeConstituenta } from '@/utils/labels'; import { describeConstituenta } from '@/utils/labels';
@ -54,7 +54,7 @@ function SubstitutionsPicker({
setItems, setItems,
prefixID prefixID
}: SubstitutionsPickerProps) { }: SubstitutionsPickerProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const [leftCst, setLeftCst] = useState<IConstituenta | undefined>(undefined); const [leftCst, setLeftCst] = useState<IConstituenta | undefined>(undefined);
const [rightCst, setRightCst] = useState<IConstituenta | undefined>(undefined); const [rightCst, setRightCst] = useState<IConstituenta | undefined>(undefined);

View File

@ -2,7 +2,7 @@
import { ThreeDots } from 'react-loader-spinner'; import { ThreeDots } from 'react-loader-spinner';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import AnimateFade from '../wrap/AnimateFade'; import AnimateFade from '../wrap/AnimateFade';
@ -11,7 +11,7 @@ interface LoaderProps {
} }
function Loader({ size = 10 }: LoaderProps) { function Loader({ size = 10 }: LoaderProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
return ( return (
<AnimateFade noFadeIn className='flex justify-center'> <AnimateFade noFadeIn className='flex justify-center'>
<ThreeDots color={colors.bgPrimary} height={size * 10} width={size * 10} radius={size} /> <ThreeDots color={colors.bgPrimary} height={size * 10} width={size * 10} radius={size} />

View File

@ -3,7 +3,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import Select, { GroupBase, Props, StylesConfig } from 'react-select'; import Select, { GroupBase, Props, StylesConfig } from 'react-select';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { selectDarkT, selectLightT } from '@/styling/color'; import { selectDarkT, selectLightT } from '@/styling/color';
export interface SelectMultiProps<Option, Group extends GroupBase<Option> = GroupBase<Option>> export interface SelectMultiProps<Option, Group extends GroupBase<Option> = GroupBase<Option>>
@ -15,7 +15,7 @@ function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>
noPortal, noPortal,
...restProps ...restProps
}: SelectMultiProps<Option, Group>) { }: SelectMultiProps<Option, Group>) {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptOptions();
const themeColors = useMemo(() => (!darkMode ? selectLightT : selectDarkT), [darkMode]); const themeColors = useMemo(() => (!darkMode ? selectLightT : selectDarkT), [darkMode]);
const adjustedStyles: StylesConfig<Option, true, Group> = useMemo( const adjustedStyles: StylesConfig<Option, true, Group> = useMemo(

View File

@ -3,7 +3,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import Select, { GroupBase, Props, StylesConfig } from 'react-select'; import Select, { GroupBase, Props, StylesConfig } from 'react-select';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { selectDarkT, selectLightT } from '@/styling/color'; import { selectDarkT, selectLightT } from '@/styling/color';
interface SelectSingleProps<Option, Group extends GroupBase<Option> = GroupBase<Option>> interface SelectSingleProps<Option, Group extends GroupBase<Option> = GroupBase<Option>>
@ -15,7 +15,7 @@ function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option
noPortal, noPortal,
...restProps ...restProps
}: SelectSingleProps<Option, Group>) { }: SelectSingleProps<Option, Group>) {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptOptions();
const themeColors = useMemo(() => (!darkMode ? selectLightT : selectDarkT), [darkMode]); const themeColors = useMemo(() => (!darkMode ? selectLightT : selectDarkT), [darkMode]);
const adjustedStyles: StylesConfig<Option, false, Group> = useMemo( const adjustedStyles: StylesConfig<Option, false, Group> = useMemo(

View File

@ -5,7 +5,7 @@ import { ReactNode } from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ITooltip, Tooltip as TooltipImpl } from 'react-tooltip'; import { ITooltip, Tooltip as TooltipImpl } from 'react-tooltip';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
export type { PlacesType } from 'react-tooltip'; export type { PlacesType } from 'react-tooltip';
@ -23,7 +23,7 @@ function Tooltip({
style, style,
...restProps ...restProps
}: TooltipProps) { }: TooltipProps) {
const { darkMode } = useConceptTheme(); const { darkMode } = useConceptOptions();
if (typeof window === 'undefined') { if (typeof window === 'undefined') {
return null; return null;
} }

View File

@ -10,7 +10,7 @@ import { animationDuration } from '@/styling/animations';
import { darkT, IColorTheme, lightT } from '@/styling/color'; import { darkT, IColorTheme, lightT } from '@/styling/color';
import { globals, storage } from '@/utils/constants'; import { globals, storage } from '@/utils/constants';
interface IThemeContext { interface IOptionsContext {
viewportHeight: string; viewportHeight: string;
mainHeight: string; mainHeight: string;
@ -27,32 +27,38 @@ interface IThemeContext {
toggleNoNavigation: () => void; toggleNoNavigation: () => void;
noFooter: boolean; noFooter: boolean;
setNoFooter: (value: boolean) => void; setNoFooter: React.Dispatch<React.SetStateAction<boolean>>;
showScroll: boolean; showScroll: boolean;
setShowScroll: (value: boolean) => void; setShowScroll: React.Dispatch<React.SetStateAction<boolean>>;
showHelp: boolean;
toggleShowHelp: () => void;
calculateHeight: (offset: string) => string; calculateHeight: (offset: string) => string;
} }
const ThemeContext = createContext<IThemeContext | null>(null); const OptionsContext = createContext<IOptionsContext | null>(null);
export const useConceptTheme = () => { export const useConceptOptions = () => {
const context = useContext(ThemeContext); const context = useContext(OptionsContext);
if (!context) { if (!context) {
throw new Error('useConceptTheme has to be used within <ThemeState.Provider>'); throw new Error('useConceptTheme has to be used within <ThemeState.Provider>');
} }
return context; return context;
}; };
interface ThemeStateProps { interface OptionsStateProps {
children: React.ReactNode; children: React.ReactNode;
} }
export const ThemeState = ({ children }: ThemeStateProps) => { export const OptionsState = ({ children }: OptionsStateProps) => {
const [darkMode, setDarkMode] = useLocalStorage(storage.themeDark, false); const [darkMode, setDarkMode] = useLocalStorage(storage.themeDark, false);
const [mathFont, setMathFont] = useLocalStorage<FontStyle>(storage.rseditFont, 'math'); const [mathFont, setMathFont] = useLocalStorage<FontStyle>(storage.rseditFont, 'math');
const [colors, setColors] = useState<IColorTheme>(lightT); const [showHelp, setShowHelp] = useLocalStorage(storage.optionsHelp, true);
const [noNavigation, setNoNavigation] = useState(false); const [noNavigation, setNoNavigation] = useState(false);
const [colors, setColors] = useState<IColorTheme>(lightT);
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false); const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
const [noFooter, setNoFooter] = useState(false); const [noFooter, setNoFooter] = useState(false);
const [showScroll, setShowScroll] = useState(false); const [showScroll, setShowScroll] = useState(false);
@ -98,6 +104,11 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
[noNavigation, noFooter] [noNavigation, noFooter]
); );
const toggleDarkMode = useCallback(() => {
setDarkMode(prev => !prev);
window.location.reload();
}, [setDarkMode]);
const mainHeight = useMemo(() => { const mainHeight = useMemo(() => {
return !noNavigation ? 'calc(100vh - 6.75rem)' : '100vh'; return !noNavigation ? 'calc(100vh - 6.75rem)' : '100vh';
}, [noNavigation]); }, [noNavigation]);
@ -107,7 +118,7 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
}, [noNavigation]); }, [noNavigation]);
return ( return (
<ThemeContext.Provider <OptionsContext.Provider
value={{ value={{
darkMode, darkMode,
colors, colors,
@ -117,10 +128,12 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
noNavigation, noNavigation,
noFooter, noFooter,
showScroll, showScroll,
toggleDarkMode: () => setDarkMode(prev => !prev), showHelp,
toggleDarkMode: toggleDarkMode,
toggleNoNavigation: toggleNoNavigation, toggleNoNavigation: toggleNoNavigation,
setNoFooter, setNoFooter,
setShowScroll, setShowScroll,
toggleShowHelp: () => setShowHelp(prev => !prev),
viewportHeight, viewportHeight,
mainHeight, mainHeight,
calculateHeight calculateHeight
@ -136,6 +149,6 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
/> />
{children} {children}
</> </>
</ThemeContext.Provider> </OptionsContext.Provider>
); );
}; };

View File

@ -9,7 +9,7 @@ import RSInput from '@/components/RSInput';
import ConstituentaPicker from '@/components/select/ConstituentaPicker'; import ConstituentaPicker from '@/components/select/ConstituentaPicker';
import DataTable, { IConditionalStyle } from '@/components/ui/DataTable'; import DataTable, { IConditionalStyle } from '@/components/ui/DataTable';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { IConstituenta, IRSForm } from '@/models/rsform'; import { IConstituenta, IRSForm } from '@/models/rsform';
import { IArgumentValue } from '@/models/rslang'; import { IArgumentValue } from '@/models/rslang';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
@ -28,7 +28,7 @@ export interface IArgumentsState {
const argumentsHelper = createColumnHelper<IArgumentValue>(); const argumentsHelper = createColumnHelper<IArgumentValue>();
function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) { function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined); const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | undefined>(undefined); const [selectedArgument, setSelectedArgument] = useState<IArgumentValue | undefined>(undefined);

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { useLayoutEffect, useState } from 'react'; import { useLayoutEffect, useState } from 'react';
import { TabList, TabPanel, Tabs } from 'react-tabs'; import { TabList, TabPanel, Tabs } from 'react-tabs';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import Modal, { ModalProps } from '@/components/ui/Modal'; import Modal, { ModalProps } from '@/components/ui/Modal';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import TabLabel from '@/components/ui/TabLabel'; import TabLabel from '@/components/ui/TabLabel';
@ -110,7 +110,7 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
onSubmit={handleSubmit} onSubmit={handleSubmit}
> >
<Overlay position='top-0 right-[6rem]'> <Overlay position='top-0 right-[6rem]'>
<HelpButton topic={HelpTopic.RSTEMPLATES} className='max-w-[40rem]' offset={12} /> <BadgeHelp topic={HelpTopic.RSTEMPLATES} className='max-w-[40rem]' offset={12} />
</Overlay> </Overlay>
<Tabs <Tabs
forceRenderTabPanel forceRenderTabPanel

View File

@ -3,11 +3,13 @@
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import { useLayoutEffect, useMemo, useState } from 'react'; import { useLayoutEffect, useMemo, useState } from 'react';
import BadgeHelp from '@/components/man/BadgeHelp';
import RSInput from '@/components/RSInput'; import RSInput from '@/components/RSInput';
import SelectSingle from '@/components/ui/SelectSingle'; import SelectSingle from '@/components/ui/SelectSingle';
import TextArea from '@/components/ui/TextArea'; import TextArea from '@/components/ui/TextArea';
import TextInput from '@/components/ui/TextInput'; import TextInput from '@/components/ui/TextInput';
import AnimateFade from '@/components/wrap/AnimateFade'; import AnimateFade from '@/components/wrap/AnimateFade';
import { HelpTopic } from '@/models/miscellaneous';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform'; import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, isBaseSet, isBasicConcept, isFunctional, validateNewAlias } from '@/models/rsformAPI'; import { generateAlias, isBaseSet, isBasicConcept, isFunctional, validateNewAlias } from '@/models/rsformAPI';
import { labelCstType } from '@/utils/labels'; import { labelCstType } from '@/utils/labels';
@ -39,7 +41,7 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
return ( return (
<AnimatePresence> <AnimatePresence>
<div className='flex self-center gap-6'> <div className='flex items-center self-center'>
<SelectSingle <SelectSingle
id='dlg_cst_type' id='dlg_cst_type'
placeholder='Выберите тип' placeholder='Выберите тип'
@ -48,11 +50,12 @@ function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreat
value={{ value: state.cst_type, label: labelCstType(state.cst_type) }} value={{ value: state.cst_type, label: labelCstType(state.cst_type) }}
onChange={data => partialUpdate({ cst_type: data?.value ?? CstType.BASE })} onChange={data => partialUpdate({ cst_type: data?.value ?? CstType.BASE })}
/> />
<BadgeHelp topic={HelpTopic.CST_ATTRIBUTES} offset={16} className='max-w-[40rem] max-h-[calc(100vh-2rem)]' />
<TextInput <TextInput
id='dlg_cst_alias' id='dlg_cst_alias'
dense dense
label='Имя' label='Имя'
className='w-[7rem]' className='w-[7rem] ml-3'
value={state.alias} value={state.alias}
onChange={event => partialUpdate({ alias: event.target.value })} onChange={event => partialUpdate({ alias: event.target.value })}
/> />

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { useState } from 'react'; import { useState } from 'react';
import { TabList, TabPanel, Tabs } from 'react-tabs'; import { TabList, TabPanel, Tabs } from 'react-tabs';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import Modal from '@/components/ui/Modal'; import Modal from '@/components/ui/Modal';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import TabLabel from '@/components/ui/TabLabel'; import TabLabel from '@/components/ui/TabLabel';
@ -54,7 +54,7 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
className='w-[40rem] px-6 min-h-[34rem]' className='w-[40rem] px-6 min-h-[34rem]'
> >
<Overlay position='top-0 right-[4rem]'> <Overlay position='top-0 right-[4rem]'>
<HelpButton topic={HelpTopic.TERM_CONTROL} className='max-w-[35rem]' offset={14} /> <BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[35rem]' offset={14} />
</Overlay> </Overlay>
<Tabs <Tabs

View File

@ -7,7 +7,7 @@ import { useIntl } from 'react-intl';
import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/ui/DataTable';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { IVersionInfo } from '@/models/library'; import { IVersionInfo } from '@/models/library';
interface VersionsTableProps { interface VersionsTableProps {
@ -22,7 +22,7 @@ const columnHelper = createColumnHelper<IVersionInfo>();
function VersionsTable({ processing, items, onDelete, selected, onSelect }: VersionsTableProps) { function VersionsTable({ processing, items, onDelete, selected, onSelect }: VersionsTableProps) {
const intl = useIntl(); const intl = useIntl();
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const columns = useMemo( const columns = useMemo(
() => [ () => [

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { useLayoutEffect, useState } from 'react'; import { useLayoutEffect, useState } from 'react';
import { BiCheck, BiChevronsDown, BiLeftArrow, BiRightArrow, BiX } from 'react-icons/bi'; import { BiCheck, BiChevronsDown, BiLeftArrow, BiRightArrow, BiX } from 'react-icons/bi';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import SelectGrammeme from '@/components/select/SelectGrammeme'; import SelectGrammeme from '@/components/select/SelectGrammeme';
import Label from '@/components/ui/Label'; import Label from '@/components/ui/Label';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
@ -130,7 +130,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
className='flex flex-col w-[40rem] px-6' className='flex flex-col w-[40rem] px-6'
> >
<Overlay position='top-[-0.2rem] left-[8rem]'> <Overlay position='top-[-0.2rem] left-[8rem]'>
<HelpButton topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} /> <BadgeHelp topic={HelpTopic.TERM_CONTROL} className='max-w-[38rem]' offset={3} />
</Overlay> </Overlay>
<TextArea <TextArea

View File

@ -4,7 +4,7 @@ import { useCallback, useMemo, useState } from 'react';
import GraphUI, { GraphEdge, GraphNode } from '@/components/ui/GraphUI'; import GraphUI, { GraphEdge, GraphNode } from '@/components/ui/GraphUI';
import Modal, { ModalProps } from '@/components/ui/Modal'; import Modal, { ModalProps } from '@/components/ui/Modal';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { SyntaxTree } from '@/models/rslang'; import { SyntaxTree } from '@/models/rslang';
import { graphDarkT, graphLightT } from '@/styling/color'; import { graphDarkT, graphLightT } from '@/styling/color';
import { colorBgSyntaxTree } from '@/styling/color'; import { colorBgSyntaxTree } from '@/styling/color';
@ -17,7 +17,7 @@ interface DlgShowASTProps extends Pick<ModalProps, 'hideWindow'> {
} }
function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) { function DlgShowAST({ hideWindow, syntaxTree, expression }: DlgShowASTProps) {
const { darkMode, colors } = useConceptTheme(); const { darkMode, colors } = useConceptOptions();
const [hoverID, setHoverID] = useState<number | undefined>(undefined); const [hoverID, setHoverID] = useState<number | undefined>(undefined);
const hoverNode = useMemo(() => syntaxTree.find(node => node.uid === hoverID), [hoverID, syntaxTree]); const hoverNode = useMemo(() => syntaxTree.find(node => node.uid === hoverID), [hoverID, syntaxTree]);

View File

@ -40,8 +40,9 @@ export enum HelpTopic {
MAIN = 'main', MAIN = 'main',
LIBRARY = 'library', LIBRARY = 'library',
RSFORM = 'rsform', RSFORM = 'rsform',
CSTLIST = 'cstlist', CST_ATTRIBUTES = 'cst-type',
CONSTITUENTA = 'constituenta', CST_LIST = 'cst-list',
CST_EDITOR = 'cst-editor',
GRAPH_TERM = 'graph-term', GRAPH_TERM = 'graph-term',
RSTEMPLATES = 'rstemplates', RSTEMPLATES = 'rstemplates',
RSLANG = 'rslang', RSLANG = 'rslang',

View File

@ -6,7 +6,7 @@ import DataLoader from '@/components/wrap/DataLoader';
import { useAuth } from '@/context/AuthContext'; import { useAuth } from '@/context/AuthContext';
import { useLibrary } from '@/context/LibraryContext'; import { useLibrary } from '@/context/LibraryContext';
import { useConceptNavigation } from '@/context/NavigationContext'; import { useConceptNavigation } from '@/context/NavigationContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { ILibraryItem } from '@/models/library'; import { ILibraryItem } from '@/models/library';
@ -25,7 +25,7 @@ function LibraryPage() {
const { user } = useAuth(); const { user } = useAuth();
const library = useLibrary(); const library = useLibrary();
const { setShowScroll } = useConceptTheme(); const { setShowScroll } = useConceptOptions();
const [filter, setFilter] = useState<ILibraryFilter>({}); const [filter, setFilter] = useState<ILibraryFilter>({});
const [items, setItems] = useState<ILibraryItem[]>([]); const [items, setItems] = useState<ILibraryItem[]>([]);

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { useLayoutEffect, useMemo, useState } from 'react'; import { useLayoutEffect, useMemo, useState } from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import DataTable, { createColumnHelper, VisibilityState } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, VisibilityState } from '@/components/ui/DataTable';
import FlexColumn from '@/components/ui/FlexColumn'; import FlexColumn from '@/components/ui/FlexColumn';
import TextURL from '@/components/ui/TextURL'; import TextURL from '@/components/ui/TextURL';
@ -118,7 +118,7 @@ function ViewLibrary({ items, resetQuery }: ViewLibraryProps) {
'flex gap-1' 'flex gap-1'
)} )}
> >
<HelpButton topic={HelpTopic.LIBRARY} className='max-w-[30rem] text-sm' offset={5} place='right-start' /> <BadgeHelp topic={HelpTopic.LIBRARY} className='max-w-[30rem] text-sm' offset={5} place='right-start' />
</div> </div>
</div> </div>
<DataTable <DataTable

View File

@ -1,7 +1,7 @@
'use client'; 'use client';
import { useConceptNavigation } from '@/context/NavigationContext'; import { useConceptNavigation } from '@/context/NavigationContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { HelpTopic } from '@/models/miscellaneous'; import { HelpTopic } from '@/models/miscellaneous';
@ -13,7 +13,7 @@ function ManualsPage() {
const query = useQueryStrings(); const query = useQueryStrings();
const topic = (query.get('topic') || HelpTopic.MAIN) as HelpTopic; const topic = (query.get('topic') || HelpTopic.MAIN) as HelpTopic;
const { mainHeight } = useConceptTheme(); const { mainHeight } = useConceptOptions();
function onSelectTopic(newTopic: HelpTopic) { function onSelectTopic(newTopic: HelpTopic) {
router.push(`/manuals?topic=${newTopic}`); router.push(`/manuals?topic=${newTopic}`);

View File

@ -6,7 +6,7 @@ import { useCallback } from 'react';
import { RiMenuFoldFill, RiMenuUnfoldFill } from 'react-icons/ri'; import { RiMenuFoldFill, RiMenuUnfoldFill } from 'react-icons/ri';
import Button from '@/components/ui/Button'; import Button from '@/components/ui/Button';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useDropdown from '@/hooks/useDropdown'; import useDropdown from '@/hooks/useDropdown';
import { HelpTopic } from '@/models/miscellaneous'; import { HelpTopic } from '@/models/miscellaneous';
import { animateSlideLeft } from '@/styling/animations'; import { animateSlideLeft } from '@/styling/animations';
@ -20,7 +20,7 @@ interface TopicsListDropDownProps {
function TopicsListDropDown({ activeTopic, onChangeTopic }: TopicsListDropDownProps) { function TopicsListDropDown({ activeTopic, onChangeTopic }: TopicsListDropDownProps) {
const menu = useDropdown(); const menu = useDropdown();
const { noNavigation } = useConceptTheme(); const { noNavigation } = useConceptOptions();
const selectTheme = useCallback( const selectTheme = useCallback(
(topic: HelpTopic) => { (topic: HelpTopic) => {

View File

@ -8,13 +8,13 @@ import { FaRegKeyboard } from 'react-icons/fa6';
import { RiNodeTree } from 'react-icons/ri'; import { RiNodeTree } from 'react-icons/ri';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import RSInput from '@/components/RSInput'; import RSInput from '@/components/RSInput';
import { RSTextWrapper } from '@/components/RSInput/textEditing'; import { RSTextWrapper } from '@/components/RSInput/textEditing';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import { useConceptOptions } from '@/context/OptionsContext';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext';
import DlgShowAST from '@/dialogs/DlgShowAST'; import DlgShowAST from '@/dialogs/DlgShowAST';
import useCheckExpression from '@/hooks/useCheckExpression'; import useCheckExpression from '@/hooks/useCheckExpression';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
@ -58,7 +58,7 @@ function EditorRSExpression({
...restProps ...restProps
}: EditorRSExpressionProps) { }: EditorRSExpressionProps) {
const model = useRSForm(); const model = useRSForm();
const { mathFont, setMathFont } = useConceptTheme(); const { mathFont, setMathFont } = useConceptOptions();
const [isModified, setIsModified] = useState(false); const [isModified, setIsModified] = useState(false);
const parser = useCheckExpression({ schema: model.schema }); const parser = useCheckExpression({ schema: model.schema });
@ -198,7 +198,7 @@ function EditorRSExpression({
parseData={parser.parseData} parseData={parser.parseData}
onAnalyze={() => handleCheckExpression()} onAnalyze={() => handleCheckExpression()}
/> />
<HelpButton topic={HelpTopic.CONSTITUENTA} offset={4} /> <BadgeHelp topic={HelpTopic.CST_EDITOR} offset={4} />
</Overlay> </Overlay>
<RSInput <RSInput

View File

@ -5,7 +5,7 @@ import { AnimatePresence } from 'framer-motion';
import { useMemo } from 'react'; import { useMemo } from 'react';
import Loader from '@/components/ui/Loader'; import Loader from '@/components/ui/Loader';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ExpressionStatus } from '@/models/rsform'; import { ExpressionStatus } from '@/models/rsform';
import { type IConstituenta } from '@/models/rsform'; import { type IConstituenta } from '@/models/rsform';
import { inferStatus } from '@/models/rsformAPI'; import { inferStatus } from '@/models/rsformAPI';
@ -25,7 +25,7 @@ interface StatusBarProps {
} }
function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze }: StatusBarProps) { function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze }: StatusBarProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const status = useMemo(() => { const status = useMemo(() => {
if (isModified) { if (isModified) {
return ExpressionStatus.UNKNOWN; return ExpressionStatus.UNKNOWN;

View File

@ -6,7 +6,7 @@ import { FiSave } from 'react-icons/fi';
import { LuGitBranchPlus, LuPencilLine } from 'react-icons/lu'; import { LuGitBranchPlus, LuPencilLine } from 'react-icons/lu';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import VersionSelector from '@/components/select/VersionSelector'; import VersionSelector from '@/components/select/VersionSelector';
import Checkbox from '@/components/ui/Checkbox'; import Checkbox from '@/components/ui/Checkbox';
import Label from '@/components/ui/Label'; import Label from '@/components/ui/Label';
@ -136,7 +136,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {
/> />
</> </>
) : null} ) : null}
<HelpButton topic={HelpTopic.VERSIONS} className='max-w-[30rem]' offset={4} /> <BadgeHelp topic={HelpTopic.VERSIONS} className='max-w-[30rem]' offset={4} />
</Overlay> </Overlay>
<Label text='Версия' className='mb-2' /> <Label text='Версия' className='mb-2' />
<VersionSelector <VersionSelector

View File

@ -5,7 +5,7 @@ import { BiDownload, BiShareAlt, BiTrash } from 'react-icons/bi';
import { FiBell, FiBellOff, FiSave } from 'react-icons/fi'; import { FiBell, FiBellOff, FiSave } from 'react-icons/fi';
import { LuCrown } from 'react-icons/lu'; import { LuCrown } from 'react-icons/lu';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous'; import { HelpTopic } from '@/models/miscellaneous';
@ -75,7 +75,7 @@ function RSFormToolbar({ modified, anonymous, subscribed, claimable, onSubmit, o
onClick={onDestroy} onClick={onDestroy}
/> />
) : null} ) : null}
<HelpButton topic={HelpTopic.RSFORM} offset={4} /> <BadgeHelp topic={HelpTopic.RSFORM} offset={4} className='max-w-[32rem]' />
</Overlay> </Overlay>
); );
} }

View File

@ -5,7 +5,7 @@ import { useLayoutEffect, useMemo, useState } from 'react';
import SelectedCounter from '@/components/info/SelectedCounter'; import SelectedCounter from '@/components/info/SelectedCounter';
import { type RowSelectionState } from '@/components/ui/DataTable'; import { type RowSelectionState } from '@/components/ui/DataTable';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ConstituentaID, CstType } from '@/models/rsform'; import { ConstituentaID, CstType } from '@/models/rsform';
import { useRSEdit } from '../RSEditContext'; import { useRSEdit } from '../RSEditContext';
@ -19,7 +19,7 @@ interface EditorRSListProps {
} }
function EditorRSList({ selected, setSelected, onOpenEdit }: EditorRSListProps) { function EditorRSList({ selected, setSelected, onOpenEdit }: EditorRSListProps) {
const { calculateHeight } = useConceptTheme(); const { calculateHeight } = useConceptOptions();
const [rowSelection, setRowSelection] = useState<RowSelectionState>({}); const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const controller = useRSEdit(); const controller = useRSEdit();

View File

@ -3,7 +3,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { BiDownArrowCircle, BiDownvote, BiDuplicate, BiPlusCircle, BiTrash, BiUpvote } from 'react-icons/bi'; import { BiDownArrowCircle, BiDownvote, BiDuplicate, BiPlusCircle, BiTrash, BiUpvote } from 'react-icons/bi';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import Dropdown from '@/components/ui/Dropdown'; import Dropdown from '@/components/ui/Dropdown';
import DropdownButton from '@/components/ui/DropdownButton'; import DropdownButton from '@/components/ui/DropdownButton';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
@ -77,7 +77,7 @@ function RSListToolbar({ selectedCount }: RSListToolbarProps) {
disabled={controller.isProcessing || nothingSelected} disabled={controller.isProcessing || nothingSelected}
onClick={controller.deleteCst} onClick={controller.deleteCst}
/> />
<HelpButton topic={HelpTopic.CSTLIST} offset={5} /> <BadgeHelp topic={HelpTopic.CST_LIST} offset={5} />
</Overlay> </Overlay>
); );
} }

View File

@ -6,7 +6,7 @@ import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import ConstituentaBadge from '@/components/info/ConstituentaBadge'; import ConstituentaBadge from '@/components/info/ConstituentaBadge';
import DataTable, { createColumnHelper, RowSelectionState, VisibilityState } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, RowSelectionState, VisibilityState } from '@/components/ui/DataTable';
import FlexColumn from '@/components/ui/FlexColumn'; import FlexColumn from '@/components/ui/FlexColumn';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
import { ConstituentaID, IConstituenta } from '@/models/rsform'; import { ConstituentaID, IConstituenta } from '@/models/rsform';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
@ -31,7 +31,7 @@ const COLUMN_CONVENTION_HIDE_THRESHOLD = 1800;
const columnHelper = createColumnHelper<IConstituenta>(); const columnHelper = createColumnHelper<IConstituenta>();
function RSTable({ items, maxHeight, enableSelection, selected, setSelected, onEdit, onCreateNew }: RSTableProps) { function RSTable({ items, maxHeight, enableSelection, selected, setSelected, onEdit, onCreateNew }: RSTableProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const windowSize = useWindowSize(); const windowSize = useWindowSize();
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({}); const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});

View File

@ -8,7 +8,7 @@ import { GraphEdge, GraphNode, LayoutTypes } from 'reagraph';
import InfoConstituenta from '@/components/info/InfoConstituenta'; import InfoConstituenta from '@/components/info/InfoConstituenta';
import SelectedCounter from '@/components/info/SelectedCounter'; import SelectedCounter from '@/components/info/SelectedCounter';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import DlgGraphParams from '@/dialogs/DlgGraphParams'; import DlgGraphParams from '@/dialogs/DlgGraphParams';
import useLocalStorage from '@/hooks/useLocalStorage'; import useLocalStorage from '@/hooks/useLocalStorage';
import { GraphColoringScheme, GraphFilterParams } from '@/models/miscellaneous'; import { GraphColoringScheme, GraphFilterParams } from '@/models/miscellaneous';
@ -31,7 +31,7 @@ interface EditorTermGraphProps {
function EditorTermGraph({ selected, setSelected, onOpenEdit }: EditorTermGraphProps) { function EditorTermGraph({ selected, setSelected, onOpenEdit }: EditorTermGraphProps) {
const controller = useRSEdit(); const controller = useRSEdit();
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const [filterParams, setFilterParams] = useLocalStorage<GraphFilterParams>(storage.rsgraphFilter, { const [filterParams, setFilterParams] = useLocalStorage<GraphFilterParams>(storage.rsgraphFilter, {
noHermits: true, noHermits: true,

View File

@ -2,7 +2,7 @@
import { BiCollapse, BiFilterAlt, BiFont, BiFontFamily, BiPlanet, BiPlusCircle, BiTrash } from 'react-icons/bi'; import { BiCollapse, BiFilterAlt, BiFont, BiFontFamily, BiPlanet, BiPlusCircle, BiTrash } from 'react-icons/bi';
import HelpButton from '@/components/man/HelpButton'; import BadgeHelp from '@/components/man/BadgeHelp';
import MiniButton from '@/components/ui/MiniButton'; import MiniButton from '@/components/ui/MiniButton';
import Overlay from '@/components/ui/Overlay'; import Overlay from '@/components/ui/Overlay';
import { HelpTopic } from '@/models/miscellaneous'; import { HelpTopic } from '@/models/miscellaneous';
@ -84,7 +84,7 @@ function GraphToolbar({
onClick={onDelete} onClick={onDelete}
/> />
) : null} ) : null}
<HelpButton topic={HelpTopic.GRAPH_TERM} className='max-w-[calc(100vw-4rem)]' offset={4} /> <BadgeHelp topic={HelpTopic.GRAPH_TERM} className='max-w-[calc(100vw-4rem)]' offset={4} />
</Overlay> </Overlay>
); );
} }

View File

@ -3,7 +3,7 @@
import { useCallback, useLayoutEffect, useMemo, useRef } from 'react'; import { useCallback, useLayoutEffect, useMemo, useRef } from 'react';
import GraphUI, { GraphCanvasRef, GraphEdge, GraphNode, LayoutTypes, useSelection } from '@/components/ui/GraphUI'; import GraphUI, { GraphCanvasRef, GraphEdge, GraphNode, LayoutTypes, useSelection } from '@/components/ui/GraphUI';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ConstituentaID } from '@/models/rsform'; import { ConstituentaID } from '@/models/rsform';
import { graphDarkT, graphLightT } from '@/styling/color'; import { graphDarkT, graphLightT } from '@/styling/color';
import { resources } from '@/utils/constants'; import { resources } from '@/utils/constants';
@ -40,7 +40,7 @@ function TermGraph({
onSelect, onSelect,
onDeselectAll onDeselectAll
}: TermGraphProps) { }: TermGraphProps) {
const { calculateHeight, darkMode } = useConceptTheme(); const { calculateHeight, darkMode } = useConceptOptions();
const graphRef = useRef<GraphCanvasRef | null>(null); const graphRef = useRef<GraphCanvasRef | null>(null);
const { selections, actives, setSelections, onCanvasClick, onNodePointerOver, onNodePointerOut } = useSelection({ const { selections, actives, setSelections, onCanvasClick, onNodePointerOver, onNodePointerOut } = useSelection({

View File

@ -3,7 +3,7 @@
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import ConstituentaTooltip from '@/components/info/ConstituentaTooltip'; import ConstituentaTooltip from '@/components/info/ConstituentaTooltip';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { GraphColoringScheme } from '@/models/miscellaneous'; import { GraphColoringScheme } from '@/models/miscellaneous';
import { ConstituentaID, IRSForm } from '@/models/rsform'; import { ConstituentaID, IRSForm } from '@/models/rsform';
import { colorBgGraphNode } from '@/styling/color'; import { colorBgGraphNode } from '@/styling/color';
@ -20,7 +20,7 @@ interface ViewHiddenProps {
} }
function ViewHidden({ items, selected, toggleSelection, schema, coloringScheme, onEdit }: ViewHiddenProps) { function ViewHidden({ items, selected, toggleSelection, schema, coloringScheme, onEdit }: ViewHiddenProps) {
const { colors, noNavigation } = useConceptTheme(); const { colors, noNavigation } = useConceptOptions();
const dismissedHeight = useMemo(() => { const dismissedHeight = useMemo(() => {
return !noNavigation ? 'calc(100vh - 28rem - 4px)' : 'calc(100vh - 22.2rem - 4px)'; return !noNavigation ? 'calc(100vh - 28rem - 4px)' : 'calc(100vh - 22.2rem - 4px)';

View File

@ -10,7 +10,7 @@ import AnimateFade from '@/components/wrap/AnimateFade';
import { useLibrary } from '@/context/LibraryContext'; import { useLibrary } from '@/context/LibraryContext';
import { useBlockNavigation, useConceptNavigation } from '@/context/NavigationContext'; import { useBlockNavigation, useConceptNavigation } from '@/context/NavigationContext';
import { useRSForm } from '@/context/RSFormContext'; import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { ConstituentaID, IConstituenta, IConstituentaMeta } from '@/models/rsform'; import { ConstituentaID, IConstituenta, IConstituentaMeta } from '@/models/rsform';
import { prefixes, TIMEOUT_UI_REFRESH } from '@/utils/constants'; import { prefixes, TIMEOUT_UI_REFRESH } from '@/utils/constants';
@ -37,7 +37,7 @@ function RSTabs() {
const version = Number(query.get('v')) ?? undefined; const version = Number(query.get('v')) ?? undefined;
const cstQuery = query.get('active'); const cstQuery = query.get('active');
const { setNoFooter, calculateHeight } = useConceptTheme(); const { setNoFooter, calculateHeight } = useConceptOptions();
const { schema, loading } = useRSForm(); const { schema, loading } = useRSForm();
const { destroyItem } = useLibrary(); const { destroyItem } = useLibrary();

View File

@ -5,7 +5,7 @@ import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import ConstituentaBadge from '@/components/info/ConstituentaBadge'; import ConstituentaBadge from '@/components/info/ConstituentaBadge';
import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/ui/DataTable'; import DataTable, { createColumnHelper, IConditionalStyle, VisibilityState } from '@/components/ui/DataTable';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
import { ConstituentaID, IConstituenta } from '@/models/rsform'; import { ConstituentaID, IConstituenta } from '@/models/rsform';
import { isMockCst } from '@/models/rsformAPI'; import { isMockCst } from '@/models/rsformAPI';
@ -23,7 +23,7 @@ interface ConstituentsTableProps {
const columnHelper = createColumnHelper<IConstituenta>(); const columnHelper = createColumnHelper<IConstituenta>();
function ConstituentsTable({ items, activeID, onOpenEdit, maxHeight, denseThreshold = 9999 }: ConstituentsTableProps) { function ConstituentsTable({ items, activeID, onOpenEdit, maxHeight, denseThreshold = 9999 }: ConstituentsTableProps) {
const { colors } = useConceptTheme(); const { colors } = useConceptOptions();
const windowSize = useWindowSize(); const windowSize = useWindowSize();
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({ expression: true }); const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({ expression: true });

View File

@ -4,7 +4,7 @@ import clsx from 'clsx';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useConceptTheme } from '@/context/ThemeContext'; import { useConceptOptions } from '@/context/OptionsContext';
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform'; import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
import { animateSideView } from '@/styling/animations'; import { animateSideView } from '@/styling/animations';
@ -27,7 +27,7 @@ interface ViewConstituentsProps {
} }
function ViewConstituents({ expression, schema, activeID, isBottom, baseHeight, onOpenEdit }: ViewConstituentsProps) { function ViewConstituents({ expression, schema, activeID, isBottom, baseHeight, onOpenEdit }: ViewConstituentsProps) {
const { noNavigation } = useConceptTheme(); const { noNavigation } = useConceptOptions();
const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []); const [filteredData, setFilteredData] = useState<IConstituenta[]>(schema?.items ?? []);

View File

@ -83,6 +83,7 @@ export const storage = {
PREFIX: 'portal.', PREFIX: 'portal.',
themeDark: 'theme.dark', themeDark: 'theme.dark',
optionsHelp: 'options.help',
rseditFont: 'rsedit.font', rseditFont: 'rsedit.font',
rseditShowList: 'rsedit.show_list', rseditShowList: 'rsedit.show_list',

View File

@ -348,8 +348,9 @@ export function labelHelpTopic(topic: HelpTopic): string {
case HelpTopic.MAIN: return 'Портал'; case HelpTopic.MAIN: return 'Портал';
case HelpTopic.LIBRARY: return 'Библиотека'; case HelpTopic.LIBRARY: return 'Библиотека';
case HelpTopic.RSFORM: return '- карточка схемы'; case HelpTopic.RSFORM: return '- карточка схемы';
case HelpTopic.CSTLIST: return '- список конституент'; case HelpTopic.CST_ATTRIBUTES: return '- конституента';
case HelpTopic.CONSTITUENTA: return '- конституента'; case HelpTopic.CST_LIST: return '- список конституент';
case HelpTopic.CST_EDITOR: return '- редактор конституенты';
case HelpTopic.GRAPH_TERM: return '- граф термов'; case HelpTopic.GRAPH_TERM: return '- граф термов';
case HelpTopic.RSTEMPLATES: return '- шаблоны выражений'; case HelpTopic.RSTEMPLATES: return '- шаблоны выражений';
case HelpTopic.RSLANG: return 'Экспликация'; case HelpTopic.RSLANG: return 'Экспликация';
@ -370,8 +371,9 @@ export function describeHelpTopic(topic: HelpTopic): string {
case HelpTopic.MAIN: return 'Общая справка по порталу'; case HelpTopic.MAIN: return 'Общая справка по порталу';
case HelpTopic.LIBRARY: return 'Описание работы с библиотекой схем'; case HelpTopic.LIBRARY: return 'Описание работы с библиотекой схем';
case HelpTopic.RSFORM: return 'Описание работы с описанием схемы'; case HelpTopic.RSFORM: return 'Описание работы с описанием схемы';
case HelpTopic.CSTLIST: return 'Описание работы со списком конституент'; case HelpTopic.CST_ATTRIBUTES: return 'Описание типов и свойств конституент';
case HelpTopic.CONSTITUENTA: return 'Описание редактирования конституенты'; case HelpTopic.CST_LIST: return 'Описание работы со списком конституент';
case HelpTopic.CST_EDITOR: return 'Описание редактирования конституенты';
case HelpTopic.GRAPH_TERM: return 'Описание работы с графом термов схемы'; case HelpTopic.GRAPH_TERM: return 'Описание работы с графом термов схемы';
case HelpTopic.RSTEMPLATES: return 'Описание работы с Банком выражений>'; case HelpTopic.RSTEMPLATES: return 'Описание работы с Банком выражений>';
case HelpTopic.RSLANG: return 'Справка по языку родов структур и экспликации'; case HelpTopic.RSLANG: return 'Справка по языку родов структур и экспликации';

View File

@ -53,7 +53,7 @@ export function applyPattern(text: string, mapping: { [key: string]: string }, p
const patternMatches = text.matchAll(pattern); const patternMatches = text.matchAll(pattern);
for (const segment of patternMatches) { for (const segment of patternMatches) {
const entity = segment[0]; const entity = segment[0];
const start = segment.index!; const start = segment.index ?? 0;
if (entity in mapping) { if (entity in mapping) {
output += text.substring(posInput, start); output += text.substring(posInput, start);
output += mapping[entity]; output += mapping[entity];

View File

@ -24,8 +24,9 @@
"baseUrl": "./src/", "baseUrl": "./src/",
"paths": { "paths": {
"@/*": ["*"] "@/*": ["*"]
}
}, },
}, "types": ["vite/client"],
"include": ["src"], "include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }] "references": [{ "path": "./tsconfig.node.json" }]
} }