mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
Refactoring: standardize localStorage and add prefix
This commit is contained in:
parent
8a134557b6
commit
3ac6a3577d
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -106,6 +106,7 @@
|
||||||
"rseditor",
|
"rseditor",
|
||||||
"rsform",
|
"rsform",
|
||||||
"rsforms",
|
"rsforms",
|
||||||
|
"rsgraph",
|
||||||
"rslang",
|
"rslang",
|
||||||
"rstemplates",
|
"rstemplates",
|
||||||
"SIDELIST",
|
"SIDELIST",
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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 { useConceptTheme } from '@/context/ThemeContext';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
function ApplicationLayout() {
|
function ApplicationLayout() {
|
||||||
const { viewportHeight, mainHeight, showScroll } = useConceptTheme();
|
const { viewportHeight, mainHeight, showScroll } = useConceptTheme();
|
||||||
|
@ -22,7 +22,7 @@ function ApplicationLayout() {
|
||||||
<Navigation />
|
<Navigation />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id={globalIDs.main_scroll}
|
id={globals.main_scroll}
|
||||||
className='overflow-y-auto overscroll-none min-w-fit'
|
className='overflow-y-auto overscroll-none min-w-fit'
|
||||||
style={{
|
style={{
|
||||||
maxHeight: viewportHeight,
|
maxHeight: viewportHeight,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
interface NavigationButtonProps extends CProps.Titled {
|
interface NavigationButtonProps extends CProps.Titled {
|
||||||
text?: string;
|
text?: string;
|
||||||
|
@ -14,7 +14,7 @@ function NavigationButton({ icon, title, titleHtml, hideTitle, onClick, text }:
|
||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ function Button({
|
||||||
className,
|
className,
|
||||||
colors
|
colors
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CheckboxCheckedIcon } from '../Icons';
|
import { CheckboxCheckedIcon } from '../Icons';
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
@ -54,7 +54,7 @@ function Checkbox({
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CheckboxCheckedIcon, CheckboxNullIcon } from '../Icons';
|
import { CheckboxCheckedIcon, CheckboxNullIcon } from '../Icons';
|
||||||
import { CheckboxProps } from './Checkbox';
|
import { CheckboxProps } from './Checkbox';
|
||||||
|
@ -57,7 +57,7 @@ function CheckboxTristate({
|
||||||
)}
|
)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import clsx from 'clsx';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
import { animateDropdownItem } from '@/styling/animations';
|
import { animateDropdownItem } from '@/styling/animations';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ function DropdownButton({
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
variants={animateDropdownItem}
|
variants={animateDropdownItem}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ function MiniButton({
|
||||||
},
|
},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ function SelectorButton({
|
||||||
className,
|
className,
|
||||||
!transparent && colors
|
!transparent && colors
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import clsx from 'clsx';
|
||||||
import type { TabProps as TabPropsImpl } from 'react-tabs';
|
import type { TabProps as TabPropsImpl } from 'react-tabs';
|
||||||
import { Tab as TabImpl } from 'react-tabs';
|
import { Tab as TabImpl } from 'react-tabs';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import { CProps } from '../props';
|
import { CProps } from '../props';
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function TabLabel({ label, title, titleHtml, hideTitle, className, ...otherProps
|
||||||
'select-none hover:cursor-pointer',
|
'select-none hover:cursor-pointer',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react';
|
import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react';
|
||||||
|
|
||||||
import { type ErrorData } from '@/components/info/InfoError';
|
import { type ErrorData } from '@/components/info/InfoError';
|
||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
|
||||||
import { IPasswordTokenData, IRequestPasswordData, IResetPasswordData, IUserLoginData } from '@/models/library';
|
import { IPasswordTokenData, IRequestPasswordData, IResetPasswordData, IUserLoginData } from '@/models/library';
|
||||||
import { ICurrentUser } from '@/models/library';
|
import { ICurrentUser } from '@/models/library';
|
||||||
import { IUserSignupData } from '@/models/library';
|
import { IUserSignupData } from '@/models/library';
|
||||||
|
@ -53,7 +52,7 @@ interface AuthStateProps {
|
||||||
|
|
||||||
export const AuthState = ({ children }: AuthStateProps) => {
|
export const AuthState = ({ children }: AuthStateProps) => {
|
||||||
const { users } = useUsers();
|
const { users } = useUsers();
|
||||||
const [user, setUser] = useLocalStorage<ICurrentUser | undefined>('user', undefined);
|
const [user, setUser] = useState<ICurrentUser | undefined>(undefined);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState<ErrorData>(undefined);
|
const [error, setError] = useState<ErrorData>(undefined);
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
interface INavigationContext {
|
interface INavigationContext {
|
||||||
push: (path: string) => void;
|
push: (path: string) => void;
|
||||||
|
@ -43,7 +43,7 @@ export const NavigationState = ({ children }: NavigationStateProps) => {
|
||||||
|
|
||||||
const scrollTop = useCallback(() => {
|
const scrollTop = useCallback(() => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
const mainScroll = document.getElementById(globalIDs.main_scroll);
|
const mainScroll = document.getElementById(globals.main_scroll);
|
||||||
if (mainScroll) {
|
if (mainScroll) {
|
||||||
mainScroll.scroll(0, 0);
|
mainScroll.scroll(0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { FontStyle } from '@/models/miscellaneous';
|
import { FontStyle } from '@/models/miscellaneous';
|
||||||
import { animationDuration } from '@/styling/animations';
|
import { animationDuration } from '@/styling/animations';
|
||||||
import { darkT, IColorTheme, lightT } from '@/styling/color';
|
import { darkT, IColorTheme, lightT } from '@/styling/color';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals, storage } from '@/utils/constants';
|
||||||
|
|
||||||
interface IThemeContext {
|
interface IThemeContext {
|
||||||
viewportHeight: string;
|
viewportHeight: string;
|
||||||
|
@ -49,8 +49,8 @@ interface ThemeStateProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ThemeState = ({ children }: ThemeStateProps) => {
|
export const ThemeState = ({ children }: ThemeStateProps) => {
|
||||||
const [darkMode, setDarkMode] = useLocalStorage('darkMode', false);
|
const [darkMode, setDarkMode] = useLocalStorage(storage.themeDark, false);
|
||||||
const [mathFont, setMathFont] = useLocalStorage<FontStyle>('editor_font_math', 'math');
|
const [mathFont, setMathFont] = useLocalStorage<FontStyle>(storage.rseditFont, 'math');
|
||||||
const [colors, setColors] = useState<IColorTheme>(lightT);
|
const [colors, setColors] = useState<IColorTheme>(lightT);
|
||||||
const [noNavigation, setNoNavigation] = useState(false);
|
const [noNavigation, setNoNavigation] = useState(false);
|
||||||
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
|
const [noNavigationAnimation, setNoNavigationAnimation] = useState(false);
|
||||||
|
@ -129,7 +129,7 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
float
|
float
|
||||||
id={`${globalIDs.tooltip}`}
|
id={`${globals.tooltip}`}
|
||||||
layer='z-topmost'
|
layer='z-topmost'
|
||||||
place='right-start'
|
place='right-start'
|
||||||
className={clsx('mt-3 translate-y-1/2', 'max-w-[20rem]')}
|
className={clsx('mt-3 translate-y-1/2', 'max-w-[20rem]')}
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
import { storage } from '@/utils/constants';
|
||||||
|
|
||||||
function useLocalStorage<ValueType>(key: string, defaultValue: ValueType | (() => ValueType)) {
|
function useLocalStorage<ValueType>(key: string, defaultValue: ValueType | (() => ValueType)) {
|
||||||
|
const prefixedKey = `${storage.PREFIX}${key}`;
|
||||||
const [value, setValue] = useState<ValueType>(() => {
|
const [value, setValue] = useState<ValueType>(() => {
|
||||||
const loadedJson = localStorage.getItem(key);
|
const loadedJson = localStorage.getItem(prefixedKey);
|
||||||
if (loadedJson != null) {
|
if (loadedJson != null) {
|
||||||
return JSON.parse(loadedJson) as ValueType;
|
return JSON.parse(loadedJson) as ValueType;
|
||||||
} else if (typeof defaultValue === 'function') {
|
} else if (typeof defaultValue === 'function') {
|
||||||
|
@ -16,11 +19,11 @@ function useLocalStorage<ValueType>(key: string, defaultValue: ValueType | (() =
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
localStorage.removeItem(key);
|
localStorage.removeItem(prefixedKey);
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(key, JSON.stringify(value));
|
localStorage.setItem(prefixedKey, JSON.stringify(value));
|
||||||
}
|
}
|
||||||
}, [key, value]);
|
}, [prefixedKey, value]);
|
||||||
|
|
||||||
return [value, setValue] as [ValueType, typeof setValue];
|
return [value, setValue] as [ValueType, typeof setValue];
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import useQueryStrings from '@/hooks/useQueryStrings';
|
||||||
import { ILibraryItem } from '@/models/library';
|
import { ILibraryItem } from '@/models/library';
|
||||||
import { ILibraryFilter, LibraryFilterStrategy } from '@/models/miscellaneous';
|
import { ILibraryFilter, LibraryFilterStrategy } from '@/models/miscellaneous';
|
||||||
import { filterFromStrategy } from '@/models/miscellaneousAPI';
|
import { filterFromStrategy } from '@/models/miscellaneousAPI';
|
||||||
|
import { storage } from '@/utils/constants';
|
||||||
|
|
||||||
import SearchPanel from './SearchPanel';
|
import SearchPanel from './SearchPanel';
|
||||||
import ViewLibrary from './ViewLibrary';
|
import ViewLibrary from './ViewLibrary';
|
||||||
|
@ -19,7 +20,7 @@ import ViewLibrary from './ViewLibrary';
|
||||||
function LibraryPage() {
|
function LibraryPage() {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
const urlParams = useQueryStrings();
|
const urlParams = useQueryStrings();
|
||||||
const searchFilter = (urlParams.get('filter') || null) as LibraryFilterStrategy | null;
|
const queryFilter = (urlParams.get('filter') || null) as LibraryFilterStrategy | null;
|
||||||
|
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
@ -31,23 +32,19 @@ function LibraryPage() {
|
||||||
|
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const [strategy, setStrategy] = useLocalStorage<LibraryFilterStrategy>(
|
const [strategy, setStrategy] = useLocalStorage<LibraryFilterStrategy>(
|
||||||
'search_strategy',
|
storage.librarySearchStrategy,
|
||||||
LibraryFilterStrategy.MANUAL
|
LibraryFilterStrategy.MANUAL
|
||||||
);
|
);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (searchFilter === null) {
|
if (!queryFilter || !Object.values(LibraryFilterStrategy).includes(queryFilter)) {
|
||||||
router.replace(`/library?filter=${strategy}`);
|
router.replace(`/library?filter=${strategy}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const inputStrategy =
|
|
||||||
searchFilter && Object.values(LibraryFilterStrategy).includes(searchFilter)
|
|
||||||
? searchFilter
|
|
||||||
: LibraryFilterStrategy.MANUAL;
|
|
||||||
setQuery('');
|
setQuery('');
|
||||||
setStrategy(inputStrategy);
|
setStrategy(queryFilter);
|
||||||
setFilter(filterFromStrategy(inputStrategy));
|
setFilter(filterFromStrategy(queryFilter));
|
||||||
}, [user, router, setQuery, setFilter, setStrategy, strategy, searchFilter]);
|
}, [user, router, setQuery, setFilter, setStrategy, strategy, queryFilter]);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setShowScroll(true);
|
setShowScroll(true);
|
||||||
|
|
|
@ -15,6 +15,7 @@ import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import useWindowSize from '@/hooks/useWindowSize';
|
import useWindowSize from '@/hooks/useWindowSize';
|
||||||
import { ILibraryItem } from '@/models/library';
|
import { ILibraryItem } from '@/models/library';
|
||||||
import { HelpTopic } from '@/models/miscellaneous';
|
import { HelpTopic } from '@/models/miscellaneous';
|
||||||
|
import { storage } from '@/utils/constants';
|
||||||
|
|
||||||
import ItemIcons from './ItemIcons';
|
import ItemIcons from './ItemIcons';
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ function ViewLibrary({ items, resetQuery }: ViewLibraryProps) {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { getUserLabel } = useUsers();
|
const { getUserLabel } = useUsers();
|
||||||
const [itemsPerPage, setItemsPerPage] = useLocalStorage<number>('library_per_page', 50);
|
const [itemsPerPage, setItemsPerPage] = useLocalStorage<number>(storage.libraryPagination, 50);
|
||||||
|
|
||||||
const handleOpenItem = (item: ILibraryItem) => router.push(`/rsforms/${item.id}`);
|
const handleOpenItem = (item: ILibraryItem) => router.push(`/rsforms/${item.id}`);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useMemo, useState } from 'react';
|
||||||
import useLocalStorage from '@/hooks/useLocalStorage';
|
import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import useWindowSize from '@/hooks/useWindowSize';
|
import useWindowSize from '@/hooks/useWindowSize';
|
||||||
import { ConstituentaID, IConstituenta } from '@/models/rsform';
|
import { ConstituentaID, IConstituenta } from '@/models/rsform';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals, storage } from '@/utils/constants';
|
||||||
|
|
||||||
import { useRSEdit } from '../RSEditContext';
|
import { useRSEdit } from '../RSEditContext';
|
||||||
import ViewConstituents from '../ViewConstituents';
|
import ViewConstituents from '../ViewConstituents';
|
||||||
|
@ -31,7 +31,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
||||||
const controller = useRSEdit();
|
const controller = useRSEdit();
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
|
|
||||||
const [showList, setShowList] = useLocalStorage('rseditor-show-list', true);
|
const [showList, setShowList] = useLocalStorage(storage.rseditShowList, true);
|
||||||
const [toggleReset, setToggleReset] = useState(false);
|
const [toggleReset, setToggleReset] = useState(false);
|
||||||
|
|
||||||
const disabled = useMemo(
|
const disabled = useMemo(
|
||||||
|
@ -62,7 +62,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
||||||
}
|
}
|
||||||
|
|
||||||
function initiateSubmit() {
|
function initiateSubmit() {
|
||||||
const element = document.getElementById(globalIDs.constituenta_editor) as HTMLFormElement;
|
const element = document.getElementById(globals.constituenta_editor) as HTMLFormElement;
|
||||||
if (element) {
|
if (element) {
|
||||||
element.requestSubmit();
|
element.requestSubmit();
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ function EditorConstituenta({ activeCst, isModified, setIsModified, onOpenEdit }
|
||||||
<FormConstituenta
|
<FormConstituenta
|
||||||
isMutable={!disabled}
|
isMutable={!disabled}
|
||||||
showList={showList}
|
showList={showList}
|
||||||
id={globalIDs.constituenta_editor}
|
id={globals.constituenta_editor}
|
||||||
constituenta={activeCst}
|
constituenta={activeCst}
|
||||||
isModified={isModified}
|
isModified={isModified}
|
||||||
toggleReset={toggleReset}
|
toggleReset={toggleReset}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { IConstituenta } from '@/models/rsform';
|
||||||
import { getDefinitionPrefix } from '@/models/rsformAPI';
|
import { getDefinitionPrefix } from '@/models/rsformAPI';
|
||||||
import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '@/models/rslang';
|
import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '@/models/rslang';
|
||||||
import { TokenID } from '@/models/rslang';
|
import { TokenID } from '@/models/rslang';
|
||||||
|
import { storage } from '@/utils/constants';
|
||||||
import { labelTypification } from '@/utils/labels';
|
import { labelTypification } from '@/utils/labels';
|
||||||
|
|
||||||
import ParsingResult from './ParsingResult';
|
import ParsingResult from './ParsingResult';
|
||||||
|
@ -67,7 +68,7 @@ function EditorRSExpression({
|
||||||
const [syntaxTree, setSyntaxTree] = useState<SyntaxTree>([]);
|
const [syntaxTree, setSyntaxTree] = useState<SyntaxTree>([]);
|
||||||
const [expression, setExpression] = useState('');
|
const [expression, setExpression] = useState('');
|
||||||
const [showAST, setShowAST] = useState(false);
|
const [showAST, setShowAST] = useState(false);
|
||||||
const [showControls, setShowControls] = useLocalStorage('rseditor-show-controls', true);
|
const [showControls, setShowControls] = useLocalStorage(storage.rseditShowControls, true);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setIsModified(false);
|
setIsModified(false);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import clsx from 'clsx';
|
||||||
|
|
||||||
import { CProps } from '@/components/props';
|
import { CProps } from '@/components/props';
|
||||||
import { TokenID } from '@/models/rslang';
|
import { TokenID } from '@/models/rslang';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
interface RSLocalButtonProps extends CProps.Titled {
|
interface RSLocalButtonProps extends CProps.Titled {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -16,7 +16,7 @@ function RSLocalButton({ text, title, titleHtml, hideTitle, disabled, onInsert }
|
||||||
type='button'
|
type='button'
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
data-tooltip-id={!!title || !!titleHtml ? globalIDs.tooltip : undefined}
|
data-tooltip-id={!!title || !!titleHtml ? globals.tooltip : undefined}
|
||||||
data-tooltip-html={titleHtml}
|
data-tooltip-html={titleHtml}
|
||||||
data-tooltip-content={title}
|
data-tooltip-content={title}
|
||||||
data-tooltip-hidden={hideTitle}
|
data-tooltip-hidden={hideTitle}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { TokenID } from '@/models/rslang';
|
import { TokenID } from '@/models/rslang';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
import { describeToken, labelToken } from '@/utils/labels';
|
import { describeToken, labelToken } from '@/utils/labels';
|
||||||
|
|
||||||
interface RSTokenButtonProps {
|
interface RSTokenButtonProps {
|
||||||
|
@ -30,7 +30,7 @@ function RSTokenButton({ token, disabled, onInsert }: RSTokenButtonProps) {
|
||||||
'w-[1.7rem] sm:w-[2.25rem]': label.length <= 3
|
'w-[1.7rem] sm:w-[2.25rem]': label.length <= 3
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
data-tooltip-id={globalIDs.tooltip}
|
data-tooltip-id={globals.tooltip}
|
||||||
data-tooltip-html={describeToken(token)}
|
data-tooltip-html={describeToken(token)}
|
||||||
>
|
>
|
||||||
{label ? <span className='whitespace-nowrap'>{label}</span> : null}
|
{label ? <span className='whitespace-nowrap'>{label}</span> : null}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { type IConstituenta } from '@/models/rsform';
|
||||||
import { inferStatus } from '@/models/rsformAPI';
|
import { inferStatus } from '@/models/rsformAPI';
|
||||||
import { IExpressionParse, ParsingStatus } from '@/models/rslang';
|
import { IExpressionParse, ParsingStatus } from '@/models/rslang';
|
||||||
import { colorBgCstStatus } from '@/styling/color';
|
import { colorBgCstStatus } from '@/styling/color';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
import { labelExpressionStatus, prepareTooltip } from '@/utils/labels';
|
import { labelExpressionStatus, prepareTooltip } from '@/utils/labels';
|
||||||
|
|
||||||
import StatusIcon from './StatusIcon';
|
import StatusIcon from './StatusIcon';
|
||||||
|
@ -48,7 +48,7 @@ function StatusBar({ isModified, processing, constituenta, parseData, onAnalyze
|
||||||
'duration-500 transition-colors'
|
'duration-500 transition-colors'
|
||||||
)}
|
)}
|
||||||
style={{ backgroundColor: processing ? colors.bgDefault : colorBgCstStatus(status, colors) }}
|
style={{ backgroundColor: processing ? colors.bgDefault : colorBgCstStatus(status, colors) }}
|
||||||
data-tooltip-id={globalIDs.tooltip}
|
data-tooltip-id={globals.tooltip}
|
||||||
data-tooltip-html={prepareTooltip('Проверить определение', 'Ctrl + Q')}
|
data-tooltip-html={prepareTooltip('Проверить определение', 'Ctrl + Q')}
|
||||||
onClick={onAnalyze}
|
onClick={onAnalyze}
|
||||||
>
|
>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Divider from '@/components/ui/Divider';
|
||||||
import FlexColumn from '@/components/ui/FlexColumn';
|
import FlexColumn from '@/components/ui/FlexColumn';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useRSForm } from '@/context/RSFormContext';
|
import { useRSForm } from '@/context/RSFormContext';
|
||||||
import { globalIDs } from '@/utils/constants';
|
import { globals } from '@/utils/constants';
|
||||||
|
|
||||||
import FormRSForm from './FormRSForm';
|
import FormRSForm from './FormRSForm';
|
||||||
import RSFormStats from './RSFormStats';
|
import RSFormStats from './RSFormStats';
|
||||||
|
@ -24,7 +24,7 @@ function EditorRSForm({ isModified, onDestroy, setIsModified }: EditorRSFormProp
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
function initiateSubmit() {
|
function initiateSubmit() {
|
||||||
const element = document.getElementById(globalIDs.library_item_editor) as HTMLFormElement;
|
const element = document.getElementById(globals.library_item_editor) as HTMLFormElement;
|
||||||
if (element) {
|
if (element) {
|
||||||
element.requestSubmit();
|
element.requestSubmit();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ function EditorRSForm({ isModified, onDestroy, setIsModified }: EditorRSFormProp
|
||||||
/>
|
/>
|
||||||
<div tabIndex={-1} onKeyDown={handleInput} className={clsx('flex flex-col sm:flex-row', 'sm:w-fit w-full')}>
|
<div tabIndex={-1} onKeyDown={handleInput} className={clsx('flex flex-col sm:flex-row', 'sm:w-fit w-full')}>
|
||||||
<FlexColumn className='px-4 pb-2'>
|
<FlexColumn className='px-4 pb-2'>
|
||||||
<FormRSForm id={globalIDs.library_item_editor} isModified={isModified} setIsModified={setIsModified} />
|
<FormRSForm id={globals.library_item_editor} isModified={isModified} setIsModified={setIsModified} />
|
||||||
|
|
||||||
<Divider margins='my-1' />
|
<Divider margins='my-1' />
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import useLocalStorage from '@/hooks/useLocalStorage';
|
||||||
import { GraphColoringScheme, GraphFilterParams } from '@/models/miscellaneous';
|
import { GraphColoringScheme, GraphFilterParams } from '@/models/miscellaneous';
|
||||||
import { ConstituentaID, CstType } from '@/models/rsform';
|
import { ConstituentaID, CstType } from '@/models/rsform';
|
||||||
import { colorBgGraphNode } from '@/styling/color';
|
import { colorBgGraphNode } from '@/styling/color';
|
||||||
import { TIMEOUT_GRAPH_REFRESH } from '@/utils/constants';
|
import { storage, TIMEOUT_GRAPH_REFRESH } from '@/utils/constants';
|
||||||
|
|
||||||
import { useRSEdit } from '../RSEditContext';
|
import { useRSEdit } from '../RSEditContext';
|
||||||
import GraphSidebar from './GraphSidebar';
|
import GraphSidebar from './GraphSidebar';
|
||||||
|
@ -33,7 +33,7 @@ function EditorTermGraph({ selected, setSelected, onOpenEdit }: EditorTermGraphP
|
||||||
const controller = useRSEdit();
|
const controller = useRSEdit();
|
||||||
const { colors } = useConceptTheme();
|
const { colors } = useConceptTheme();
|
||||||
|
|
||||||
const [filterParams, setFilterParams] = useLocalStorage<GraphFilterParams>('graph_filter', {
|
const [filterParams, setFilterParams] = useLocalStorage<GraphFilterParams>(storage.rsgraphFilter, {
|
||||||
noHermits: true,
|
noHermits: true,
|
||||||
noTemplates: false,
|
noTemplates: false,
|
||||||
noTransitive: true,
|
noTransitive: true,
|
||||||
|
@ -55,10 +55,13 @@ function EditorTermGraph({ selected, setSelected, onOpenEdit }: EditorTermGraphP
|
||||||
|
|
||||||
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
const nothingSelected = useMemo(() => selected.length === 0, [selected]);
|
||||||
|
|
||||||
const [layout, setLayout] = useLocalStorage<LayoutTypes>('graph_layout', 'treeTd2d');
|
const [layout, setLayout] = useLocalStorage<LayoutTypes>(storage.rsgraphLayout, 'treeTd2d');
|
||||||
const is3D = useMemo(() => layout.includes('3d'), [layout]);
|
const [coloringScheme, setColoringScheme] = useLocalStorage<GraphColoringScheme>(
|
||||||
const [coloringScheme, setColoringScheme] = useLocalStorage<GraphColoringScheme>('graph_coloring', 'type');
|
storage.rsgraphColoringScheme,
|
||||||
|
'type'
|
||||||
|
);
|
||||||
const [orbit, setOrbit] = useState(false);
|
const [orbit, setOrbit] = useState(false);
|
||||||
|
const is3D = useMemo(() => layout.includes('3d'), [layout]);
|
||||||
|
|
||||||
const [hoverID, setHoverID] = useState<ConstituentaID | undefined>(undefined);
|
const [hoverID, setHoverID] = useState<ConstituentaID | undefined>(undefined);
|
||||||
const hoverCst = useMemo(() => {
|
const hoverCst = useMemo(() => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useCallback, useLayoutEffect } from 'react';
|
import { useCallback, useLayoutEffect, useState } from 'react';
|
||||||
import { BiCog, BiFilterAlt } from 'react-icons/bi';
|
import { BiCog, BiFilterAlt } from 'react-icons/bi';
|
||||||
|
|
||||||
import Dropdown from '@/components/ui/Dropdown';
|
import Dropdown from '@/components/ui/Dropdown';
|
||||||
|
@ -14,7 +14,7 @@ import { applyGraphFilter } from '@/models/miscellaneousAPI';
|
||||||
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
|
import { ConstituentaID, IConstituenta, IRSForm } from '@/models/rsform';
|
||||||
import { createMockConstituenta, matchConstituenta } from '@/models/rsformAPI';
|
import { createMockConstituenta, matchConstituenta } from '@/models/rsformAPI';
|
||||||
import { extractGlobals } from '@/models/rslangAPI';
|
import { extractGlobals } from '@/models/rslangAPI';
|
||||||
import { prefixes } from '@/utils/constants';
|
import { prefixes, storage } from '@/utils/constants';
|
||||||
import { describeCstMatchMode, describeCstSource, labelCstMatchMode, labelCstSource } from '@/utils/labels';
|
import { describeCstMatchMode, describeCstSource, labelCstMatchMode, labelCstSource } from '@/utils/labels';
|
||||||
|
|
||||||
interface ConstituentsSearchProps {
|
interface ConstituentsSearchProps {
|
||||||
|
@ -25,9 +25,9 @@ interface ConstituentsSearchProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }: ConstituentsSearchProps) {
|
function ConstituentsSearch({ schema, activeID, activeExpression, setFiltered }: ConstituentsSearchProps) {
|
||||||
const [filterMatch, setFilterMatch] = useLocalStorage('side-filter-match', CstMatchMode.ALL);
|
const [filterMatch, setFilterMatch] = useLocalStorage(storage.cstFilterMatch, CstMatchMode.ALL);
|
||||||
const [filterText, setFilterText] = useLocalStorage('side-filter-text', '');
|
const [filterSource, setFilterSource] = useLocalStorage(storage.cstFilterGraph, DependencyMode.ALL);
|
||||||
const [filterSource, setFilterSource] = useLocalStorage('side-filter-dependency', DependencyMode.ALL);
|
const [filterText, setFilterText] = useState('');
|
||||||
|
|
||||||
const matchModeMenu = useDropdown();
|
const matchModeMenu = useDropdown();
|
||||||
const sourceMenu = useDropdown();
|
const sourceMenu = useDropdown();
|
||||||
|
|
|
@ -19,7 +19,7 @@ import ExpectedAnonymous from '@/components/wrap/ExpectedAnonymous';
|
||||||
import { useAuth } from '@/context/AuthContext';
|
import { useAuth } from '@/context/AuthContext';
|
||||||
import { useConceptNavigation } from '@/context/NavigationContext';
|
import { useConceptNavigation } from '@/context/NavigationContext';
|
||||||
import { type IUserSignupData } from '@/models/library';
|
import { type IUserSignupData } from '@/models/library';
|
||||||
import { globalIDs, patterns } from '@/utils/constants';
|
import { globals, patterns } from '@/utils/constants';
|
||||||
|
|
||||||
function RegisterPage() {
|
function RegisterPage() {
|
||||||
const router = useConceptNavigation();
|
const router = useConceptNavigation();
|
||||||
|
@ -74,10 +74,10 @@ function RegisterPage() {
|
||||||
<div className='flex gap-12'>
|
<div className='flex gap-12'>
|
||||||
<FlexColumn>
|
<FlexColumn>
|
||||||
<div className='absolute'>
|
<div className='absolute'>
|
||||||
<Overlay id={globalIDs.password_tooltip} position='top-[4.8rem] left-[3.4rem] absolute'>
|
<Overlay id={globals.password_tooltip} position='top-[4.8rem] left-[3.4rem] absolute'>
|
||||||
<BiInfoCircle size='1.25rem' className='icon-primary' />
|
<BiInfoCircle size='1.25rem' className='icon-primary' />
|
||||||
</Overlay>
|
</Overlay>
|
||||||
<Tooltip anchorSelect={`#${globalIDs.password_tooltip}`} offset={6}>
|
<Tooltip anchorSelect={`#${globals.password_tooltip}`} offset={6}>
|
||||||
<p>- используйте уникальный пароль</p>
|
<p>- используйте уникальный пароль</p>
|
||||||
<p>- портал функционирует в тестовом режиме</p>
|
<p>- портал функционирует в тестовом режиме</p>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
|
@ -29,15 +29,6 @@ export const TIMEOUT_GRAPH_REFRESH = 200;
|
||||||
*/
|
*/
|
||||||
export const EXTEOR_TRS_FILE = '.trs';
|
export const EXTEOR_TRS_FILE = '.trs';
|
||||||
|
|
||||||
/**
|
|
||||||
* Resource relative URIs.
|
|
||||||
*/
|
|
||||||
export const resources = {
|
|
||||||
graph_font: '/DejaVu.ttf',
|
|
||||||
privacy_policy: '/privacy.pdf',
|
|
||||||
logo: '/logo_full.svg'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Numeric limitations.
|
* Numeric limitations.
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +44,15 @@ export const patterns = {
|
||||||
library_alias: `.{1,${limits.library_alias_len}}`
|
library_alias: `.{1,${limits.library_alias_len}}`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local URIs.
|
||||||
|
*/
|
||||||
|
export const resources = {
|
||||||
|
graph_font: '/DejaVu.ttf',
|
||||||
|
privacy_policy: '/privacy.pdf',
|
||||||
|
logo: '/logo_full.svg'
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Youtube IDs for embedding.
|
* Youtube IDs for embedding.
|
||||||
*/
|
*/
|
||||||
|
@ -61,7 +61,7 @@ export const youtube = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constant URLs.
|
* External URLs.
|
||||||
*/
|
*/
|
||||||
export const urls = {
|
export const urls = {
|
||||||
concept: 'https://www.acconcept.ru/',
|
concept: 'https://www.acconcept.ru/',
|
||||||
|
@ -77,9 +77,32 @@ export const urls = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global unique IDs.
|
* Local storage ID.
|
||||||
*/
|
*/
|
||||||
export const globalIDs = {
|
export const storage = {
|
||||||
|
PREFIX: 'portal.',
|
||||||
|
|
||||||
|
themeDark: 'theme.dark',
|
||||||
|
|
||||||
|
rseditFont: 'rsedit.font',
|
||||||
|
rseditShowList: 'rsedit.show_list',
|
||||||
|
rseditShowControls: 'rsedit.show_controls',
|
||||||
|
|
||||||
|
librarySearchStrategy: 'library.search.strategy',
|
||||||
|
libraryPagination: 'library.pagination',
|
||||||
|
|
||||||
|
rsgraphFilter: 'rsgraph.filter',
|
||||||
|
rsgraphLayout: 'rsgraph.layout',
|
||||||
|
rsgraphColoringScheme: 'rsgraph.coloring_scheme',
|
||||||
|
|
||||||
|
cstFilterMatch: 'cst.filter.match',
|
||||||
|
cstFilterGraph: 'cst.filter.graph'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global element ID.
|
||||||
|
*/
|
||||||
|
export const globals = {
|
||||||
tooltip: 'global_tooltip',
|
tooltip: 'global_tooltip',
|
||||||
password_tooltip: 'password_tooltip',
|
password_tooltip: 'password_tooltip',
|
||||||
main_scroll: 'main_scroll',
|
main_scroll: 'main_scroll',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user