Refactoring: implement aliases and use client

This commit is contained in:
IRBorisov 2023-12-13 14:32:57 +03:00
parent 263e26ab7b
commit 87dc02dba5
184 changed files with 1372 additions and 1130 deletions

4
.gitignore vendored
View File

@ -56,6 +56,10 @@ bower_components
*.sublime*
# NextJS
**/.next/
**/out/
# Environments
venv/

View File

@ -1,4 +1,5 @@
# Dev specific
.gitignore
node_modules
.env.local
.env.local
.next

View File

@ -1,4 +1,3 @@
import { pdfjs } from 'react-pdf';
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom';
import ConceptToaster from './components/ConceptToaster';
@ -18,11 +17,6 @@ import RSFormPage from './pages/RSFormPage';
import UserProfilePage from './pages/UserProfilePage';
import { globalIDs } from './utils/constants';
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url,
).toString();
function Root() {
const { noNavigation, noFooter, viewportHeight, mainHeight, showScroll } = useConceptTheme();
return (
@ -45,7 +39,7 @@ function Root() {
overflowY: showScroll ? 'scroll': 'auto'
}}
>
<main className='w-full h-full min-w-fit flex flex-col items-center' style={{minHeight: mainHeight}}>
<main className='flex flex-col items-center w-full h-full min-w-fit' style={{minHeight: mainHeight}}>
<Outlet />
</main>

View File

@ -0,0 +1,53 @@
'use client';
import { ErrorBoundary } from 'react-error-boundary';
import { IntlProvider } from 'react-intl';
import { pdfjs } from 'react-pdf';
import { AuthState } from '@/context/AuthContext';
import { LibraryState } from '@/context/LibraryContext';
import { ThemeState } from '@/context/ThemeContext';
import { UsersState } from '@/context/UsersContext';
import ErrorFallback from './components/ErrorFallback';
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.min.js',
import.meta.url,
).toString();
const resetState = () => {
console.log('Resetting state after error fallback')
};
const logError = (error: Error, info: { componentStack?: string | null | undefined }) => {
console.log('Error fallback: ' + error.message);
if (info.componentStack) {
console.log('Component stack: ' + info.componentStack);
}
};
function GlobalProviders({ children }: { children: React.ReactNode }) {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={resetState}
onError={logError}
>
<IntlProvider locale='ru' defaultLocale='ru'>
<ThemeState>
<UsersState>
<AuthState>
<LibraryState>
{children}
</LibraryState>
</AuthState>
</UsersState>
</ThemeState>
</IntlProvider>
</ErrorBoundary>);
}
export default GlobalProviders;

View File

@ -1,4 +1,4 @@
import { IColorsProps, IControlProps } from '../commonInterfaces';
import { IColorsProps, IControlProps } from './commonInterfaces';
interface ButtonProps
extends IControlProps, IColorsProps, Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'children' | 'title'| 'type'> {

View File

@ -1,13 +1,15 @@
'use client';
import { ThreeDots } from 'react-loader-spinner';
import { useConceptTheme } from '../../context/ThemeContext';
import { useConceptTheme } from '@/context/ThemeContext';
interface ConceptLoaderProps {
size?: number
}
export function ConceptLoader({size=10}: ConceptLoaderProps) {
const {colors} = useConceptTheme()
const {colors} = useConceptTheme();
return (
<div className='flex justify-center w-full h-full'>

View File

@ -16,8 +16,7 @@ function ConceptTab({ label, tooltip, className, ...otherProps }: ConceptTabProp
{...otherProps}
>
{label}
</Tab>
);
</Tab>);
}
ConceptTab.tabsRole = 'Tab';

View File

@ -1,7 +1,9 @@
'use client';
import { createPortal } from 'react-dom';
import { ITooltip, Tooltip } from 'react-tooltip';
import { useConceptTheme } from '../../context/ThemeContext';
import { useConceptTheme } from '@/context/ThemeContext';
interface ConceptTooltipProps
extends Omit<ITooltip, 'variant'> {
@ -17,6 +19,9 @@ function ConceptTooltip({
}: ConceptTooltipProps) {
const { darkMode } = useConceptTheme();
if (typeof window === 'undefined') {
return null;
}
return createPortal(
<Tooltip
opacity={0.97}
@ -28,4 +33,4 @@ function ConceptTooltip({
/>, document.body);
}
export default ConceptTooltip;
export default ConceptTooltip;

View File

@ -1,3 +1,5 @@
'use client';
import { useRef, useState } from 'react';
import { UploadIcon } from '../Icons';

View File

@ -0,0 +1,11 @@
'use client';
import { GraphCanvas as GraphUI } from 'reagraph';
export {
type GraphEdge, type GraphNode, type GraphCanvasRef,
type LayoutTypes,
Sphere, useSelection
} from 'reagraph';
export default GraphUI;

View File

@ -1,6 +1,9 @@
'use client';
import { useRef } from 'react';
import useEscapeKey from '../../hooks/useEscapeKey';
import useEscapeKey from '@/hooks/useEscapeKey';
import { CrossIcon } from '../Icons';
import Button from './Button';
import MiniButton from './MiniButton';

View File

@ -1,9 +1,12 @@
'use client';
import type { PDFDocumentProxy } from 'pdfjs-dist';
import { useMemo, useState } from 'react';
import { Document, Page } from 'react-pdf';
import useWindowSize from '../../hooks/useWindowSize';
import { graphLightT } from '../../utils/color';
import useWindowSize from '@/hooks/useWindowSize';
import { graphLightT } from '@/utils/color';
import Overlay from './Overlay';
import PageControls from './PageControls';
@ -14,15 +17,12 @@ interface PDFViewerProps {
file?: string | ArrayBuffer | Blob
}
function PDFViewer({
file
}: PDFViewerProps) {
function PDFViewer({ file }: PDFViewerProps) {
const windowSize = useWindowSize();
const [pageCount, setPageCount] = useState(0);
const [pageNumber, setPageNumber] = useState(1);
const pageWidth = useMemo(
() => {
return Math.max(MINIMUM_WIDTH, (Math.min((windowSize?.width ?? 0) - 300, MAXIMUM_WIDTH)));
@ -48,7 +48,7 @@ function PDFViewer({
/>
</Overlay>
<Page
className='select-none pointer-events-none'
className='pointer-events-none select-none'
renderTextLayer={false}
renderAnnotationLayer={false}
pageNumber={pageNumber}

View File

@ -1,4 +1,4 @@
import { GotoFirstIcon, GotoLastIcon, GotoNextIcon, GotoPrevIcon } from '../Icons';
import { GotoFirstIcon, GotoLastIcon, GotoNextIcon, GotoPrevIcon } from '@/components/Icons';
interface PageControlsProps {
pageNumber: number

View File

@ -3,7 +3,10 @@ interface PrettyJsonProps {
}
function PrettyJson({ data }: PrettyJsonProps) {
return (<pre>{JSON.stringify(data, null, 2)}</pre>);
return (
<pre>
{JSON.stringify(data, null, 2)}
</pre>);
}
export default PrettyJson;
export default PrettyJson;

View File

@ -1,8 +1,10 @@
'use client';
import { useMemo } from 'react';
import Select, { GroupBase, Props, StylesConfig } from 'react-select';
import { useConceptTheme } from '../../context/ThemeContext';
import { selectDarkT, selectLightT } from '../../utils/color';
import { useConceptTheme } from '@/context/ThemeContext';
import { selectDarkT, selectLightT } from '@/utils/color';
export interface SelectMultiProps<
Option,
@ -45,12 +47,11 @@ function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>
}),
input: (styles) => ({...styles}),
placeholder: (styles) => ({...styles}),
multiValue: styles => ({
multiValue: (styles) => ({
...styles,
borderRadius: '0.5rem',
backgroundColor: colors.bgSelected,
}),
})
}), [colors]);
return (
@ -70,4 +71,4 @@ function SelectMulti<Option, Group extends GroupBase<Option> = GroupBase<Option>
/>);
}
export default SelectMulti;
export default SelectMulti;

View File

@ -1,8 +1,10 @@
'use client';
import { useMemo } from 'react';
import Select, { GroupBase, Props, StylesConfig } from 'react-select';
import { useConceptTheme } from '../../context/ThemeContext';
import { selectDarkT, selectLightT } from '../../utils/color';
import { useConceptTheme } from '@/context/ThemeContext';
import { selectDarkT, selectLightT } from '@/utils/color';
interface SelectSingleProps<
Option,
@ -65,4 +67,4 @@ function SelectSingle<Option, Group extends GroupBase<Option> = GroupBase<Option
/>);
}
export default SelectSingle;
export default SelectSingle;

View File

@ -31,4 +31,4 @@ function SelectorButton({
</button>);
}
export default SelectorButton;
export default SelectorButton;

View File

@ -23,4 +23,4 @@ function SubmitButton({
</button>);
}
export default SubmitButton;
export default SubmitButton;

View File

@ -27,4 +27,4 @@ function SwitchButton<ValueType>({
</button>);
}
export default SwitchButton;
export default SwitchButton;

View File

@ -1,6 +1,6 @@
import { TextareaHTMLAttributes } from 'react';
import { IColorsProps, IEditorProps } from '../commonInterfaces';
import { IColorsProps, IEditorProps } from './commonInterfaces';
import Label from './Label';
export interface TextAreaProps
@ -34,4 +34,4 @@ function TextArea({
</div>);
}
export default TextArea;
export default TextArea;

View File

@ -1,4 +1,4 @@
import { IColorsProps, IEditorProps } from '../commonInterfaces';
import { IColorsProps, IEditorProps } from './commonInterfaces';
import Label from './Label';
interface TextInputProps
@ -37,4 +37,4 @@ function TextInput({
</div>);
}
export default TextInput;
export default TextInput;

View File

@ -1,5 +1,6 @@
import { Link } from 'react-router-dom';
interface TextURLProps {
text: string
tooltip?: string
@ -35,4 +36,4 @@ function TextURL({ text, href, tooltip, color='text-url', onClick }: TextURLProp
}
}
export default TextURL;
export default TextURL;

View File

@ -67,4 +67,4 @@ function Tristate({
</button>);
}
export default Tristate;
export default Tristate;

View File

@ -1,6 +1,6 @@
import { ToastContainer, type ToastContainerProps } from 'react-toastify';
import { useConceptTheme } from '../context/ThemeContext';
import { useConceptTheme } from '@/context/ThemeContext';
interface ToasterThemedProps extends Omit<ToastContainerProps, 'theme'>{}

View File

@ -1,3 +1,5 @@
'use client';
import {
Cell, ColumnSort,
createColumnHelper, flexRender, getCoreRowModel,
@ -55,7 +57,7 @@ extends Pick<TableOptions<TData>,
* @param headPosition - Top position of sticky header (0 if no other sticky elements are present).
* No sticky header if omitted
*/
export default function DataTable<TData extends RowData>({
function DataTable<TData extends RowData>({
dense, headPosition, conditionalRowStyles, noFooter, noHeader,
onRowClicked, onRowDoubleClicked, noDataComponent,
@ -212,3 +214,5 @@ export default function DataTable<TData extends RowData>({
{isEmpty ? (noDataComponent ?? <DefaultNoData />) : null}
</div>);
}
export default DataTable;

View File

@ -1,7 +1,10 @@
'use client';
import { Table } from '@tanstack/react-table';
import { useCallback } from 'react';
import { prefixes } from '../../utils/constants';
import { prefixes } from '@/utils/constants';
import { GotoFirstIcon, GotoLastIcon, GotoNextIcon, GotoPrevIcon } from '../Icons';
interface PaginationToolsProps<TData> {

View File

@ -1,6 +1,6 @@
import { Table } from '@tanstack/react-table';
import Tristate from '../Common/Tristate';
import Tristate from '@/components/Common/Tristate';
interface SelectAllProps<TData> {
table: Table<TData>
@ -19,4 +19,4 @@ function SelectAll<TData>({ table }: SelectAllProps<TData>) {
/>);
}
export default SelectAll;
export default SelectAll;

View File

@ -1,6 +1,6 @@
import { Row } from '@tanstack/react-table';
import Checkbox from '../Common/Checkbox';
import Checkbox from '@/components/Common/Checkbox';
interface SelectRowProps<TData> {
row: Row<TData>
@ -14,4 +14,4 @@ function SelectRow<TData>({ row }: SelectRowProps<TData>) {
/>);
}
export default SelectRow;
export default SelectRow;

View File

@ -1,6 +1,6 @@
import { Column } from '@tanstack/react-table';
import { AscendingIcon, DescendingIcon } from '../Icons';
import { AscendingIcon, DescendingIcon } from '@/components/Icons';
interface SortingIconProps<TData> {
column: Column<TData>

View File

@ -1,16 +1,18 @@
import { type FallbackProps } from 'react-error-boundary';
import Button from './Common/Button';
import InfoError from './InfoError';
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
reportError(error);
return (
<div className='flex flex-col items-center antialiased clr-app' role='alert'>
<h1 className='text-lg font-semibold'>Что-то пошло не так!</h1>
{error}
<Button onClick={resetErrorBoundary} text='Попробовать еще раз' />
</div>
);
<div className='flex flex-col items-center antialiased clr-app' role='alert'>
<h1 className='text-lg font-semibold'>Что-то пошло не так!</h1>
<Button
onClick={resetErrorBoundary}
text='Попробовать еще раз'
/>
<InfoError error={error as Error} />
</div>);
}
export default ErrorFallback;

View File

@ -1,20 +1,21 @@
import { useAuth } from '../context/AuthContext';
import { useConceptNavigation } from '../context/NagivationContext';
import { useAuth } from '@/context/AuthContext';
import { useConceptNavigation } from '@/context/NagivationContext';
import TextURL from './Common/TextURL';
function ExpectedAnonymous() {
const { user, logout } = useAuth();
const { navigateTo } = useConceptNavigation();
const router = useConceptNavigation();
function logoutAndRedirect() {
logout(() => navigateTo('/login/'));
logout(() => router.push('/login/'));
}
return (
<div className='flex flex-col items-center gap-3 py-6'>
<p className='font-semibold'>{`Вы вошли в систему как ${user?.username ?? ''}`}</p>
<div className='flex gap-3'>
<TextURL text='Новая схема' href='/rsform-create'/>
<TextURL text='Новая схема' href='/library/create'/>
<span> | </span>
<TextURL text='Библиотека' href='/library'/>
<span> | </span>

View File

@ -1,4 +1,4 @@
import { urls } from '../utils/constants';
import { urls } from '@/utils/constants';
import TextURL from './Common/TextURL';
function Footer() {

View File

@ -1,6 +1,6 @@
import { IConstituenta } from '../../models/rsform';
import ConceptTooltip from '../Common/ConceptTooltip';
import InfoConstituenta from '../Shared/InfoConstituenta';
import ConceptTooltip from '@/components/Common/ConceptTooltip';
import InfoConstituenta from '@/components/Shared/InfoConstituenta';
import { IConstituenta } from '@/models/rsform';
interface ConstituentaTooltipProps {
data: IConstituenta
@ -17,4 +17,4 @@ function ConstituentaTooltip({ data, anchor }: ConstituentaTooltipProps) {
</ConceptTooltip>);
}
export default ConstituentaTooltip;
export default ConstituentaTooltip;

View File

@ -1,5 +1,5 @@
import { urls } from '../../utils/constants';
import TextURL from '../Common/TextURL';
import TextURL from '@/components/Common/TextURL';
import { urls } from '@/utils/constants';
function HelpAPI() {
return (
@ -12,4 +12,4 @@ function HelpAPI() {
</div>);
}
export default HelpAPI;
export default HelpAPI;

View File

@ -1,7 +1,8 @@
import { HelpTopic } from '../../models/miscelanious';
import ConceptTooltip from '../Common/ConceptTooltip';
import TextURL from '../Common/TextURL';
import { HelpIcon } from '../Icons';
import ConceptTooltip from '@/components/Common/ConceptTooltip';
import TextURL from '@/components/Common/TextURL';
import { HelpIcon } from '@/components/Icons';
import { HelpTopic } from '@/models/miscelanious';
import InfoTopic from './InfoTopic';
interface HelpButtonProps {
@ -35,4 +36,4 @@ function HelpButton({ topic, offset, dimensions }: HelpButtonProps) {
</>);
}
export default HelpButton;
export default HelpButton;

View File

@ -1,5 +1,5 @@
import Divider from '../Common/Divider';
import InfoCstStatus from '../Shared/InfoCstStatus';
import Divider from '@/components/Common/Divider';
import InfoCstStatus from '@/components/Shared/InfoCstStatus';
function HelpConstituenta() {
return (
@ -22,4 +22,4 @@ function HelpConstituenta() {
</div>);
}
export default HelpConstituenta;
export default HelpConstituenta;

View File

@ -1,5 +1,5 @@
import { urls } from '../../utils/constants';
import TextURL from '../Common/TextURL';
import TextURL from '@/components/Common/TextURL';
import { urls } from '@/utils/constants';
function HelpExteor() {
return (
@ -24,4 +24,4 @@ function HelpExteor() {
</div>);
}
export default HelpExteor;
export default HelpExteor;

View File

@ -1,4 +1,4 @@
import { EducationIcon, GroupIcon,SubscribedIcon } from '../Icons';
import { EducationIcon, GroupIcon,SubscribedIcon } from '@/components/Icons';
function HelpLibrary() {
return (
@ -23,4 +23,4 @@ function HelpLibrary() {
</div>);
}
export default HelpLibrary;
export default HelpLibrary;

View File

@ -1,5 +1,5 @@
import { urls } from '../../utils/constants';
import TextURL from '../Common/TextURL';
import TextURL from '@/components/Common/TextURL';
import { urls } from '@/utils/constants';
function HelpMain() {
return (
@ -20,4 +20,4 @@ function HelpMain() {
</div>);
}
export default HelpMain;
export default HelpMain;

View File

@ -1,5 +1,5 @@
import { resources } from '../../utils/constants';
import PDFViewer from '../Common/PDFViewer';
import PDFViewer from '@/components/Common/PDFViewer';
import { resources } from '@/utils/constants';
function HelpPrivacy() {
return (
@ -8,4 +8,4 @@ function HelpPrivacy() {
/>);
}
export default HelpPrivacy;
export default HelpPrivacy;

View File

@ -1,5 +1,5 @@
import Divider from '../Common/Divider';
import InfoCstStatus from '../Shared/InfoCstStatus';
import Divider from '@/components/Common/Divider';
import InfoCstStatus from '@/components/Shared/InfoCstStatus';
function HelpRSFormItems() {
return (
@ -15,4 +15,4 @@ function HelpRSFormItems() {
</div>);
}
export default HelpRSFormItems;
export default HelpRSFormItems;

View File

@ -12,4 +12,4 @@ function HelpRSFormMeta() {
</div>);
}
export default HelpRSFormMeta;
export default HelpRSFormMeta;

View File

@ -1,8 +1,8 @@
import { useMemo } from 'react';
import useWindowSize from '../../hooks/useWindowSize';
import { urls, youtube } from '../../utils/constants';
import EmbedYoutube from '../Common/EmbedYoutube';
import EmbedYoutube from '@/components/Common/EmbedYoutube';
import useWindowSize from '@/hooks/useWindowSize';
import { urls, youtube } from '@/utils/constants';
const OPT_VIDEO_H = 1080;
@ -38,4 +38,4 @@ function HelpRSLang() {
</div>);
}
export default HelpRSLang;
export default HelpRSLang;

View File

@ -1,6 +1,6 @@
import Divider from '../Common/Divider';
import InfoCstClass from '../Shared/InfoCstClass';
import InfoCstStatus from '../Shared/InfoCstStatus';
import Divider from '@/components/Common/Divider';
import InfoCstClass from '@/components/Shared/InfoCstClass';
import InfoCstStatus from '@/components/Shared/InfoCstStatus';
function HelpTermGraph() {
return (
@ -33,4 +33,4 @@ function HelpTermGraph() {
</div>);
}
export default HelpTermGraph;
export default HelpTermGraph;

View File

@ -13,4 +13,4 @@ function HelpTerminologyControl() {
</div>);
}
export default HelpTerminologyControl;
export default HelpTerminologyControl;

View File

@ -1,4 +1,5 @@
import { HelpTopic } from '../../models/miscelanious';
import { HelpTopic } from '@/models/miscelanious';
import HelpAPI from './HelpAPI';
import HelpConstituenta from './HelpConstituenta';
import HelpExteor from './HelpExteor';
@ -32,4 +33,4 @@ function InfoTopic({ topic }: InfoTopicProps) {
return null;
}
export default InfoTopic;
export default InfoTopic;

View File

@ -1,15 +1,16 @@
import axios, { type AxiosError,AxiosHeaderValue } from 'axios';
import axios, { type AxiosError } from 'axios';
import { isResponseHtml } from '@/utils/utils';
import PrettyJson from './Common/PrettyJSON';
export type ErrorInfo = string | Error | AxiosError | undefined;
export type ErrorData = string | Error | AxiosError | undefined;
interface BackendErrorProps {
error: ErrorInfo
interface InfoErrorProps {
error: ErrorData
}
function DescribeError(error: ErrorInfo) {
reportError(error);
function DescribeError({error} : {error: ErrorData}) {
if (!error) {
return <p>Ошибки отсутствуют</p>;
} else if (typeof error === 'string') {
@ -22,28 +23,14 @@ function DescribeError(error: ErrorInfo) {
}
if (error.response.status === 404) {
return (
<div className='flex flex-col justify-start'>
<p>{'Обращение к несуществующему API'}</p>
<PrettyJson data={error} />
</div>
);
<div className='flex flex-col justify-start'>
<p>{'Обращение к несуществующему API'}</p>
<PrettyJson data={error} />
</div>);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const isHtml = (() => {
if (!error.response) {
return false;
}
const header = error.response.headers['content-type'] as AxiosHeaderValue;
if (!header) {
return false;
}
if (typeof header === 'number' || typeof header === 'boolean') {
return false;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
return header.includes('text/html');
})();
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const isHtml = isResponseHtml(error.response);
return (
<div className='flex flex-col justify-start'>
<p className='underline'>Ошибка</p>
@ -57,11 +44,11 @@ function DescribeError(error: ErrorInfo) {
);
}
function BackendError({ error }: BackendErrorProps) {
function InfoError({ error }: InfoErrorProps) {
return (
<div className='px-3 py-2 min-w-[15rem] text-sm font-semibold select-text text-warning'>
{DescribeError(error)}
<DescribeError error={error} />
</div>);
}
export default BackendError;
export default InfoError;

View File

@ -1,34 +1,11 @@
import { Link } from 'react-router-dom';
import { useConceptTheme } from '../../context/ThemeContext';
import useWindowSize from '../../hooks/useWindowSize';
const HIDE_LOGO_TEXT_LIMIT = 700;
import { useConceptTheme } from '@/context/ThemeContext';
function Logo() {
const { darkMode } = useConceptTheme();
const windowSize = useWindowSize();
return (
<Link to='/' tabIndex={-1}
className='flex items-center h-full mr-2'
>
{(windowSize.width && windowSize.width >= HIDE_LOGO_TEXT_LIMIT && !darkMode) ?
<img alt=''
src='/logo_full.svg'
className='max-h-[1.6rem] min-w-[1.6rem]'
/> : null}
{(windowSize.width && windowSize.width >= HIDE_LOGO_TEXT_LIMIT && darkMode) ?
<img alt=''
src='/logo_full_dark.svg'
className='max-h-[1.6rem] min-w-[1.6rem]'
/> : null}
{(!windowSize.width || windowSize.width < HIDE_LOGO_TEXT_LIMIT) ?
<img alt=''
src='/logo_sign.svg'
className='max-h-[1.6rem] min-w-[2.2rem]'
/> : null}
</Link>);
<img alt='Логотип КонцептПортал'
className='max-h-[1.6rem]'
src={!darkMode ? '/logo_full.svg' : '/logo_full_dark.svg'}
/>);
}
export default Logo;
export default Logo;

View File

@ -1,25 +1,27 @@
import { useConceptNavigation } from '../../context/NagivationContext';
import { useConceptTheme } from '../../context/ThemeContext';
import { EducationIcon, LibraryIcon, PlusIcon } from '../Icons';
import Logo from './Logo'
import { useConceptNavigation } from '@/context/NagivationContext';
import { useConceptTheme } from '@/context/ThemeContext';
import { EducationIcon, LibraryIcon, PlusIcon } from '@/components/Icons';
import Logo from './Logo';
import NavigationButton from './NavigationButton';
import ToggleNavigationButton from './ToggleNavigationButton';
import UserMenu from './UserMenu';
function Navigation () {
const { navigateTo } = useConceptNavigation();
const router = useConceptNavigation();
const { noNavigation } = useConceptTheme();
const navigateLibrary = () => navigateTo('/library');
const navigateHelp = () => navigateTo('/manuals');
const navigateCreateNew = () => navigateTo('/rsform-create');
const navigateHome = () => router.push('/');
const navigateLibrary = () => router.push('/library');
const navigateHelp = () => router.push('/manuals');
const navigateCreateNew = () => router.push('/library/create');
return (
<nav className='sticky top-0 left-0 right-0 select-none clr-app z-navigation h-fit'>
<nav className='sticky top-0 left-0 right-0 select-none clr-app z-navigation'>
<ToggleNavigationButton />
{!noNavigation ?
<div className='flex items-stretch justify-between pl-2 pr-[0.8rem] border-b-2 rounded-none h-[3rem]'>
<div className='flex items-center justify-start'>
<div className='flex items-center mr-2 cursor-pointer' onClick={navigateHome} tabIndex={-1}>
<Logo />
</div>
<div className='flex items-center h-full'>

View File

@ -1,5 +1,6 @@
import { useConceptTheme } from '../../context/ThemeContext';
import { DarkThemeIcon, LightThemeIcon } from '../Icons';
import { DarkThemeIcon, LightThemeIcon } from '@/components/Icons';
import { useConceptTheme } from '@/context/ThemeContext';
import NavigationButton from './NavigationButton';
function ThemeSwitcher() {

View File

@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { useConceptTheme } from '../../context/ThemeContext';
import { useConceptTheme } from '@/context/ThemeContext';
function ToggleNavigationButton() {
const { noNavigation, toggleNoNavigation } = useConceptTheme();

View File

@ -1,8 +1,8 @@
import { useAuth } from '../../context/AuthContext';
import { useConceptNavigation } from '../../context/NagivationContext';
import { useConceptTheme } from '../../context/ThemeContext';
import Dropdown from '../Common/Dropdown';
import DropdownButton from '../Common/DropdownButton';
import Dropdown from '@/components/Common/Dropdown';
import DropdownButton from '@/components/Common/DropdownButton';
import { useAuth } from '@/context/AuthContext';
import { useConceptNavigation } from '@/context/NagivationContext';
import { useConceptTheme } from '@/context/ThemeContext';
interface UserDropdownProps {
hideDropdown: () => void
@ -10,18 +10,18 @@ interface UserDropdownProps {
function UserDropdown({ hideDropdown }: UserDropdownProps) {
const { darkMode, toggleDarkMode } = useConceptTheme();
const { navigateTo } = useConceptNavigation();
const router = useConceptNavigation();
const { user, logout } = useAuth();
const navigateProfile = () => {
hideDropdown();
navigateTo('/profile');
router.push('/profile');
};
const logoutAndRedirect =
() => {
hideDropdown();
logout(() => navigateTo('/login/'));
logout(() => router.push('/login/'));
};
return (

View File

@ -1,22 +1,22 @@
import { useAuth } from '../../context/AuthContext';
import { useConceptNavigation } from '../../context/NagivationContext';
import useDropdown from '../../hooks/useDropdown';
import { InDoorIcon, UserIcon } from '../Icons';
import { InDoorIcon, UserIcon } from '@/components/Icons';
import { useAuth } from '@/context/AuthContext';
import { useConceptNavigation } from '@/context/NagivationContext';
import useDropdown from '@/hooks/useDropdown';
import NavigationButton from './NavigationButton';
import UserDropdown from './UserDropdown';
function UserMenu() {
const { navigateTo } = useConceptNavigation();
const router = useConceptNavigation();
const { user } = useAuth();
const menu = useDropdown();
const navigateLogin = () => navigateTo('/login');
const navigateLogin = () => router.push('/login');
return (
<div ref={menu.ref} className='h-full'>
<div className='flex items-center justify-end h-full w-fit'>
{!user ?
<NavigationButton
text='Войти...'
description='Перейти на страницу логина'
icon={<InDoorIcon />}
onClick={navigateLogin}

View File

@ -6,9 +6,10 @@ import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef
import { EditorView } from 'codemirror';
import { RefObject, useCallback, useMemo, useRef } from 'react';
import { useRSForm } from '../../context/RSFormContext';
import { useConceptTheme } from '../../context/ThemeContext';
import Label from '../Common/Label';
import Label from '@/components/Common/Label';
import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext';
import { ccBracketMatching } from './bracketMatching';
import { RSLanguage } from './rslang';
import { getSymbolSubstitute,RSTextWrapper } from './textEditing';

View File

@ -1,7 +1,7 @@
import { bracketMatching, MatchResult } from '@codemirror/language';
import { Decoration, EditorView } from '@codemirror/view';
import { bracketsDarkT, bracketsLightT } from '../../utils/color';
import { bracketsDarkT, bracketsLightT } from '@/utils/color';
const matchingMark = Decoration.mark({class: 'cc-matchingBracket'});
const nonmatchingMark = Decoration.mark({class: 'cc-nonmatchingBracket'});

View File

@ -28,9 +28,9 @@ const testData = [
['(X1)', '[Expression[Boolean[][Boolean[][(][Global][)]]]]'],
['P2[S1]', '[Expression[PredicateCall[Predicate][[][Global][]]]]'],
['[σ∈R1×R1] F6[σ]', '[Expression[FunctionDeclaration[[][Local][∈][BinaryOperation[Radical][×][Radical]][]][FunctionCall[Function][[][Local][]]]]]'],
['D{ξ∈red(S1) | ξ=ξ}', '[Expression[Declarative[PrefixD][{][Variable[Local]][∈][TextFunctionExpression[TextFunction][(][Global][)]][LogicPredicate[Local][=][Local]][}]]]'],
['I{(σ, γ) | σ:∈X1; γ:=F1[σ]; P1[σ, γ]}', '[Expression[Imperative[PrefixI][{][Tuple[(][Local][Local][)]][ImperativeBlocks[ImperativeBlocks[ImperativeBlocks[ImperativeIteration[Local][:∈][Global]]][ImperativeAssignment[Local][:=][FunctionCall[Function][[][Local][]]]]][ImperativeCondition[PredicateCall[Predicate][[][Local][Local][]]]]][}]]]'],
['R{ξ:=D1 | F1[ξ]≠∅ | ξF1[ξ]}', '[Expression[Recursion[PrefixR][{][Variable[Local]][:=][Global][LogicPredicate[FunctionCall[Function][[][Local][]]][≠][Literal]][BinaryOperation[Local][][FunctionCall[Function][[][Local][]]]][}]]]'],
['D{ξ∈red(S1) | ξ=ξ}', '[Expression[Declarative[PrefixD][{][Variable[Local]][∈][TextFunctionExpression[TextFunction][(][Global][)]][|][LogicPredicate[Local][=][Local]][}]]]'],
['I{(σ, γ) | σ:∈X1; γ:=F1[σ]; P1[σ, γ]}', '[Expression[Imperative[PrefixI][{][Tuple[(][Local][Local][)]][|][ImperativeBlocks[ImperativeBlocks[ImperativeBlocks[ImperativeIteration[Local][:∈][Global]]][;][ImperativeAssignment[Local][:=][FunctionCall[Function][[][Local][]]]]][;][ImperativeCondition[PredicateCall[Predicate][[][Local][Local][]]]]][}]]]'],
['R{ξ:=D1 | F1[ξ]≠∅ | ξF1[ξ]}', '[Expression[Recursion[PrefixR][{][Variable[Local]][:=][Global][|][LogicPredicate[FunctionCall[Function][[][Local][]]][≠][Literal]][|][BinaryOperation[Local][][FunctionCall[Function][[][Local][]]]][}]]]'],
['∀ξ∈∅ 1=1', '[Expression[LogicQuantor[∀][QuantorVariable[Variable[Local]]][∈][Literal][LogicPredicate[Literal][=][Literal]]]]'],
['∀ξ1∈β (ξ1≠∅ & ∀ξ2∈β ξ1∩ξ2=∅)', '[Expression[LogicQuantor[∀][QuantorVariable[Variable[Local[Index]]]][∈][Local][(][LogicBinary[LogicPredicate[Local[Index]][≠][Literal]][&][LogicQuantor[∀][QuantorVariable[Variable[Local[Index]]]][∈][Local][LogicPredicate[BinaryOperation[Local[Index]][∩][Local[Index]]][=][Literal]]]][)]]]']
];

View File

@ -1,6 +1,6 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr"
import {highlighting} from "./highlight.ts"
import {highlighting} from "./highlight"
export const parser = LRParser.deserialize({
version: 14,
states: "7WO!sQPOOOOQO'#C_'#C_O!zQPO'#C`O&bQPO'#D{OVQPO'#CdO&iQPO'#CqO'yQPO'#CsO(RQPO'#CuO(WQPO'#C|O(]QPO'#DVOOQO'#ES'#ESO(bQPO'#DXO(gQQO'#D]OOQO'#D]'#D]O(lQQO'#D_O(qQPO'#D[O(vQPO'#D[OOQO'#D}'#D}O({QPO'#DjOVQPO'#DlO)QQPO'#DnOOQO'#Ea'#EaO)YQPO'#D{OOQO'#D|'#D|O)TQPO'#DwQOQPOOOOQO'#Ca'#CaOOQO,58z,58zO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,59OO&iQPO,58xO)kQPO'#ETO+PQPO,59OO+ZQPO'#EUO+`QPO,59^O+hQPO,5:}O,eQPO'#ETO&iQPO'#CdO,rQPO,59]OOQO'#ET'#ETO-fQPO,59aO&iQPO,59_OOQO,59_,59_O)QQPO,59aO&iQPO,59hO)QQPO,59qO&iQPO,59sOOQO,59w,59wOOQO,59y,59yO&iQPO,59vO&iQPO,59vO&iQPO,5:UO%TQPO'#C^OOQO,5:W,5:WOOQO'#Cy'#CyO)QQPO'#CyO-sQPO,5:YOOQO'#Dp'#DpOVQPO,5:^OVQPO,5:^OVQPO,5:^OVQPO,5:^O-{QPO'#EeOOQO'#Ed'#EdO.QQPO,5:cOOQO1G.j1G.jO0VQPO1G.jO0^QPO1G.jO2bQPO1G.jO4fQPO1G.jO4mQPO1G.jO4tQPO1G.jO5^QPO1G.jO7PQPO1G.dO&iQPO,5:pOOQO1G.x1G.xOOQO1G0i1G0iOOQO1G.w1G.wO&iQPO1G.{O7pQPO1G.yO7wQPO1G.{O7|QPO1G/SO8TQPO1G/]O8YQPO1G/_O8bQPO1G/bO8iQPO1G/bO8qQPO1G/pOOQO'#EW'#EWO8yQPO,59eO9RQPO'#CzO)QQPO,5:|O9WQPO1G/tOOQO1G/x1G/xO;SQPO1G/xO;ZQPO1G/xO;bQPO1G/xO&iQPO,5;PO)TQPO,5;OOVQPO1G/}O<PQPO1G0[O<aQPO7+$gOOQO7+$e7+$eO&iQPO7+$gOVQPO7+$nO&iQPO7+$wOOQO7+$y7+$yOOQO7+$|7+$|O<hQPO7+$|OOQO7+%[7+%[OOQO1G/P1G/PO)QQPO,59fOOQO1G0h1G0hOOQO'#C`'#C`O<mQPO7+%`O=ZQPO1G0kOOQO1G0j1G0jOOQO7+%i7+%iOVQPO<<HRO=eQPO<<HRO=lQPO'#D}O=vQPO'#DSOOQO'#EX'#EXOOQO'#C}'#C}O>[QPO<<HYO>dQPO<<HcO&iQPO<<HhOOQO1G/Q1G/QO>kQPO<<HzO?YQPOAN=mOVQPOAN=mO&iQPO,59jO&iQPO,59lOVQPO,59iOOQOAN=tAN=tOVQPOAN=}O?kQPOAN>SOOQOG23XG23XO?rQPOG23XO@TQPO1G/UO@_QPO1G/WOOQO1G/T1G/TO@iQPOG23iO@pQPOG23iOOQOG23nG23nOOQOLD(sLD(sOOQOLD)TLD)TO&iQPOLD)TOARQPO!$'LoOOQO!)9BZ!)9BZO9WQPO,59OO9WQPO,59OO9WQPO,59OO9WQPO,59OO9WQPO,59OO9WQPO,59OO9WQPO,59OO9WQPO,59OOAYQPO1G.jOCRQPO1G.jOF}QPO1G.jOIXQPO1G.jOI`QPO1G.jOIgQPO1G.jOInQPO1G.j",

View File

@ -197,4 +197,4 @@ ImperativeCondition { logic }
@detectDelim
@external propSource highlighting from "./highlight.ts"
@external propSource highlighting from "./highlight"

View File

@ -51,4 +51,4 @@ token {
@detectDelim
@external propSource highlighting from "./highlight.ts"
@external propSource highlighting from "./highlight"

View File

@ -2,8 +2,8 @@
import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
import { TokenID } from '../../models/rslang';
import { CodeMirrorWrapper } from '../../utils/codemirror';
import { TokenID } from '@/models/rslang';
import { CodeMirrorWrapper } from '@/utils/codemirror';
export function getSymbolSubstitute(keyCode: string, shiftPressed: boolean): string | undefined {
if (shiftPressed) {

View File

@ -3,9 +3,9 @@ import { Extension } from '@codemirror/state';
import { hoverTooltip } from '@codemirror/view';
import { EditorState } from '@uiw/react-codemirror';
import { IConstituenta } from '../../models/rsform';
import { findEnvelopingNodes } from '../../utils/codemirror';
import { domTooltipConstituenta } from '../../utils/codemirror';
import { IConstituenta } from '@/models/rsform';
import { findEnvelopingNodes } from '@/utils/codemirror';
import { domTooltipConstituenta } from '@/utils/codemirror';
import { GlobalTokens } from './rslang';
function findAliasAt(pos: number, state: EditorState) {

View File

@ -6,16 +6,17 @@ import CodeMirror, { BasicSetupOptions, ReactCodeMirrorProps, ReactCodeMirrorRef
import { EditorView } from 'codemirror';
import { RefObject, useCallback, useMemo, useRef, useState } from 'react';
import { useRSForm } from '../../context/RSFormContext';
import { useConceptTheme } from '../../context/ThemeContext';
import DlgEditReference from '../../dialogs/DlgEditReference';
import useResolveText from '../../hooks/useResolveText';
import { ReferenceType } from '../../models/language';
import { IConstituenta } from '../../models/rsform';
import { CodeMirrorWrapper } from '../../utils/codemirror';
import Label from '../Common/Label';
import Modal from '../Common/Modal';
import PrettyJson from '../Common/PrettyJSON';
import Label from '@/components/Common/Label';
import Modal from '@/components/Common/Modal';
import PrettyJson from '@/components/Common/PrettyJSON';
import { useRSForm } from '@/context/RSFormContext';
import { useConceptTheme } from '@/context/ThemeContext';
import DlgEditReference from '@/dialogs/DlgEditReference';
import useResolveText from '@/hooks/useResolveText';
import { ReferenceType } from '@/models/language';
import { IConstituenta } from '@/models/rsform';
import { CodeMirrorWrapper } from '@/utils/codemirror';
import { NaturalLanguage, ReferenceTokens } from './parse';
import { RefEntity } from './parse/parser.terms';
import { refsHoverTooltip } from './tooltip';

View File

@ -1,6 +1,6 @@
// This file was generated by lezer-generator. You probably shouldn't edit it.
import {LRParser} from "@lezer/lr"
import {highlighting} from "./highlight.ts"
import {highlighting} from "./highlight"
export const parser = LRParser.deserialize({
version: 14,
states: "$nQVQPOOObQQO'#C^OOQO'#Cl'#ClOjQPO'#CuOxQPO'#CdOOQO'#Ce'#CeOOQO'#Ck'#CkOOQO'#Cf'#CfQVQPOOO}QPO,58xO!SQPO,58{OOQO,59a,59aO!XQPO,59OOOQO-E6d-E6dO!^QSO1G.dO!cQPO1G.gOOQO1G.j1G.jO!hQQO'#CpOOQO'#C`'#C`O!pQPO7+$OOOQO'#Cg'#CgO!uQPO'#CcO!}QPO7+$RO!^QSO,59[OOQO<<Gj<<GjOOQO-E6e-E6eOOQO<<Gm<<GmOOQO1G.v1G.v",

View File

@ -56,4 +56,4 @@ Nominal { word+ }
@detectDelim
@external propSource highlighting from "./highlight.ts"
@external propSource highlighting from "./highlight"

View File

@ -2,10 +2,10 @@ import { syntaxTree } from '@codemirror/language'
import { Extension } from '@codemirror/state';
import { hoverTooltip } from '@codemirror/view';
import { parseEntityReference, parseSyntacticReference } from '../../models/languageAPI';
import { IConstituenta } from '../../models/rsform';
import { domTooltipEntityReference, domTooltipSyntacticReference, findContainedNodes, findEnvelopingNodes } from '../../utils/codemirror';
import { IColorTheme } from '../../utils/color';
import { parseEntityReference, parseSyntacticReference } from '@/models/languageAPI';
import { IConstituenta } from '@/models/rsform';
import { domTooltipEntityReference, domTooltipSyntacticReference, findContainedNodes, findEnvelopingNodes } from '@/utils/codemirror';
import { IColorTheme } from '@/utils/color';
import { ReferenceTokens } from './parse';
import { RefEntity, RefSyntactic } from './parse/parser.terms';

View File

@ -1,4 +1,7 @@
import { useAuth } from '../context/AuthContext';
'use client';
import { useAuth } from '@/context/AuthContext';
import TextURL from './Common/TextURL';
interface RequireAuthProps {

View File

@ -1,9 +1,9 @@
import { IConstituenta } from '../../models/rsform';
import { isMockCst } from '../../models/rsformAPI';
import { colorfgCstStatus,IColorTheme } from '../../utils/color';
import { describeExpressionStatus } from '../../utils/labels';
import ConceptTooltip from '../Common/ConceptTooltip';
import ConstituentaTooltip from '../Help/ConstituentaTooltip';
import ConceptTooltip from '@/components/Common/ConceptTooltip';
import ConstituentaTooltip from '@/components/Help/ConstituentaTooltip';
import { IConstituenta } from '@/models/rsform';
import { isMockCst } from '@/models/rsformAPI';
import { colorfgCstStatus,IColorTheme } from '@/utils/color';
import { describeExpressionStatus } from '@/utils/labels';
interface ConstituentaBadgeProps {
prefixID?: string

View File

@ -1,13 +1,14 @@
import { useEffect, useMemo, useState } from 'react';
import { useConceptTheme } from '../../context/ThemeContext';
import { CstMatchMode } from '../../models/miscelanious';
import { IConstituenta } from '../../models/rsform';
import { matchConstituenta } from '../../models/rsformAPI';
import { prefixes } from '../../utils/constants';
import { describeConstituenta } from '../../utils/labels';
import ConceptSearch from '../Common/ConceptSearch';
import DataTable, { createColumnHelper, IConditionalStyle } from '../DataTable';
import ConceptSearch from '@/components/Common/ConceptSearch';
import DataTable, { createColumnHelper, IConditionalStyle } from '@/components/DataTable';
import { useConceptTheme } from '@/context/ThemeContext';
import { CstMatchMode } from '@/models/miscelanious';
import { IConstituenta } from '@/models/rsform';
import { matchConstituenta } from '@/models/rsformAPI';
import { prefixes } from '@/utils/constants';
import { describeConstituenta } from '@/utils/labels';
import ConstituentaBadge from './ConstituentaBadge';
interface ConstituentaPickerProps {

View File

@ -1,7 +1,7 @@
import { useConceptTheme } from '../../context/ThemeContext';
import { GramData } from '../../models/language';
import { colorfgGrammeme } from '../../utils/color';
import { labelGrammeme } from '../../utils/labels';
import { useConceptTheme } from '@/context/ThemeContext';
import { GramData } from '@/models/language';
import { colorfgGrammeme } from '@/utils/color';
import { labelGrammeme } from '@/utils/labels';
interface GrammemeBadgeProps {
key?: string

View File

@ -1,5 +1,5 @@
import { IConstituenta } from '../../models/rsform';
import { labelCstTypification } from '../../utils/labels';
import { IConstituenta } from '@/models/rsform';
import { labelCstTypification } from '@/utils/labels';
interface InfoConstituentaProps
extends React.HTMLAttributes<HTMLDivElement> {

View File

@ -1,8 +1,8 @@
import { useConceptTheme } from '../../context/ThemeContext';
import { CstClass } from '../../models/rsform';
import { colorbgCstClass } from '../../utils/color';
import { prefixes } from '../../utils/constants';
import { describeCstClass, labelCstClass } from '../../utils/labels';
import { useConceptTheme } from '@/context/ThemeContext';
import { CstClass } from '@/models/rsform';
import { colorbgCstClass } from '@/utils/color';
import { prefixes } from '@/utils/constants';
import { describeCstClass, labelCstClass } from '@/utils/labels';
interface InfoCstClassProps {
title?: string

View File

@ -1,8 +1,8 @@
import { useConceptTheme } from '../../context/ThemeContext';
import { ExpressionStatus } from '../../models/rsform';
import { colorbgCstStatus } from '../../utils/color';
import { prefixes } from '../../utils/constants';
import { describeExpressionStatus, labelExpressionStatus } from '../../utils/labels';
import { useConceptTheme } from '@/context/ThemeContext';
import { ExpressionStatus } from '@/models/rsform';
import { colorbgCstStatus } from '@/utils/color';
import { prefixes } from '@/utils/constants';
import { describeExpressionStatus, labelExpressionStatus } from '@/utils/labels';
interface InfoCstStatusProps {
title?: string

View File

@ -1,7 +1,7 @@
import { useIntl } from 'react-intl';
import { useUsers } from '../../context/UsersContext';
import { ILibraryItemEx } from '../../models/library';
import { useUsers } from '@/context/UsersContext';
import { ILibraryItemEx } from '@/models/library';
interface InfoLibraryItemProps {
item?: ILibraryItemEx

View File

@ -1,9 +1,9 @@
import { useEffect, useState } from 'react';
import { Grammeme } from '../../models/language';
import { getCompatibleGrams } from '../../models/languageAPI';
import { compareGrammemeOptions,IGrammemeOption, SelectorGrammems } from '../../utils/selectors';
import SelectMulti, { SelectMultiProps } from '../Common/SelectMulti';
import SelectMulti, { SelectMultiProps } from '@/components/Common/SelectMulti';
import { Grammeme } from '@/models/language';
import { getCompatibleGrams } from '@/models/languageAPI';
import { compareGrammemeOptions,IGrammemeOption, SelectorGrammems } from '@/utils/selectors';
interface SelectGrammemeProps extends
Omit<SelectMultiProps<IGrammemeOption>, 'value' | 'onChange'> {

View File

@ -1,4 +1,4 @@
import Overlay from '../Common/Overlay';
import Overlay from '@/components/Common/Overlay';
interface SelectedCounterProps {
total: number

View File

@ -1,4 +1,5 @@
import { IWordForm } from '../../models/language';
import { IWordForm } from '@/models/language';
import GrammemeBadge from './GrammemeBadge';
interface WordFormBadgeProps {

View File

@ -1,14 +1,17 @@
'use client';
import { createContext, useCallback, useContext, useLayoutEffect, useState } from 'react';
import { type ErrorInfo } from '../components/BackendError';
import useLocalStorage from '../hooks/useLocalStorage';
import { IUserLoginData } from '../models/library';
import { ICurrentUser } from '../models/library';
import { IUserSignupData } from '../models/library';
import { IUserProfile } from '../models/library';
import { IUserInfo } from '../models/library';
import { IUserUpdatePassword } from '../models/library';
import { type DataCallback, getAuth, patchPassword,postLogin, postLogout, postSignup } from '../utils/backendAPI';
import { type ErrorData } from '@/components/InfoError';
import useLocalStorage from '@/hooks/useLocalStorage';
import { IUserLoginData } from '@/models/library';
import { ICurrentUser } from '@/models/library';
import { IUserSignupData } from '@/models/library';
import { IUserProfile } from '@/models/library';
import { IUserInfo } from '@/models/library';
import { IUserUpdatePassword } from '@/models/library';
import { type DataCallback, getAuth, patchPassword,postLogin, postLogout, postSignup } from '@/utils/backendAPI';
import { useUsers } from './UsersContext';
interface IAuthContext {
@ -18,8 +21,8 @@ interface IAuthContext {
signup: (data: IUserSignupData, callback?: DataCallback<IUserProfile>) => void
updatePassword: (data: IUserUpdatePassword, callback?: () => void) => void
loading: boolean
error: ErrorInfo
setError: (error: ErrorInfo) => void
error: ErrorData
setError: (error: ErrorData) => void
}
const AuthContext = createContext<IAuthContext | null>(null);
@ -41,7 +44,7 @@ export const AuthState = ({ children }: AuthStateProps) => {
const { users } = useUsers();
const [user, setUser] = useLocalStorage<ICurrentUser | undefined>('user', undefined);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<ErrorInfo>(undefined);
const [error, setError] = useState<ErrorData>(undefined);
const reload = useCallback(
(callback?: () => void) => {

View File

@ -1,12 +1,15 @@
'use client';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { ErrorInfo } from '../components/BackendError';
import { ILibraryItem } from '../models/library';
import { matchLibraryItem } from '../models/libraryAPI';
import { ILibraryFilter } from '../models/miscelanious';
import { IRSForm, IRSFormCreateData, IRSFormData } from '../models/rsform';
import { loadRSFormData } from '../models/rsformAPI';
import { DataCallback, deleteLibraryItem, getLibrary, getRSFormDetails, getTemplates, postCloneLibraryItem, postNewRSForm } from '../utils/backendAPI';
import { ErrorData } from '@/components/InfoError';
import { ILibraryItem } from '@/models/library';
import { matchLibraryItem } from '@/models/libraryAPI';
import { ILibraryFilter } from '@/models/miscelanious';
import { IRSForm, IRSFormCreateData, IRSFormData } from '@/models/rsform';
import { loadRSFormData } from '@/models/rsformAPI';
import { DataCallback, deleteLibraryItem, getLibrary, getRSFormDetails, getTemplates, postCloneLibraryItem, postNewRSForm } from '@/utils/backendAPI';
import { useAuth } from './AuthContext';
interface ILibraryContext {
@ -14,8 +17,8 @@ interface ILibraryContext {
templates: ILibraryItem[]
loading: boolean
processing: boolean
error: ErrorInfo
setError: (error: ErrorInfo) => void
error: ErrorData
setError: (error: ErrorData) => void
applyFilter: (params: ILibraryFilter) => ILibraryItem[]
retrieveTemplate: (templateID: number, callback: (schema: IRSForm) => void) => void
@ -49,7 +52,7 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
const [templates, setTemplates] = useState<ILibraryItem[]>([]);
const [loading, setLoading] = useState(false);
const [processing, setProcessing] = useState(false);
const [error, setError] = useState<ErrorInfo>(undefined);
const [error, setError] = useState<ErrorData>(undefined);
const [cachedTemplates, setCachedTemplates] = useState<IRSForm[]>([]);
const applyFilter = useCallback(
@ -196,4 +199,4 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
}}>
{children}
</LibraryContext.Provider>);
}
}

View File

@ -1,11 +1,20 @@
import { createContext, useCallback, useContext, useEffect } from 'react';
import { NavigateOptions, useLocation, useNavigate } from 'react-router-dom';
'use client';
import { globalIDs } from '../utils/constants';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { unstable_usePrompt, useLocation, useNavigate } from 'react-router-dom';
import { globalIDs } from '@/utils/constants';
interface INagivationContext{
navigateTo: (path: string, options?: NavigateOptions) => void
navigateHistory: (offset: number) => void
push: (path: string) => void
replace: (path: string) => void
back: () => void
forward: () => void
canBack: () => boolean
isBlocked: boolean
setIsBlocked: (value: boolean) => void
}
const NagivationContext = createContext<INagivationContext | null>(null);
@ -22,37 +31,65 @@ interface NavigationStateProps {
}
export const NavigationState = ({ children }: NavigationStateProps) => {
const implNavigate = useNavigate();
const router = useNavigate();
const { pathname } = useLocation();
function scrollTop() {
const [isBlocked, setIsBlocked] = useState(false);
unstable_usePrompt({
when: isBlocked,
message: 'Изменения не сохранены. Вы уверены что хотите совершить переход?'
});
const canBack = useCallback(
() => {
return (!!window.history && window.history?.length !== 0);
}, []);
const scrollTop = useCallback(
() => {
window.scrollTo(0, 0);
const mainScroll = document.getElementById(globalIDs.main_scroll);
if (mainScroll) {
mainScroll.scroll(0,0);
}
}
}, []);
const navigateTo = useCallback(
(path: string, options?: NavigateOptions) => {
const push = useCallback(
(path: string) => {
scrollTop();
implNavigate(path, options);
}, [implNavigate]);
setIsBlocked(false);
router(path);
}, [router, scrollTop]);
const navigateHistory = useCallback(
(offset: number) => {
const replace = useCallback(
(path: string) => {
scrollTop();
implNavigate(offset);
}, [implNavigate]);
setIsBlocked(false);
router(path, {replace: true});
}, [router, scrollTop]);
const back = useCallback(
() => {
scrollTop();
setIsBlocked(false);
router(-1);
}, [router, scrollTop]);
const forward = useCallback(
() => {
scrollTop();
setIsBlocked(false);
router(1);
}, [router, scrollTop]);
useEffect(() => {
scrollTop();
}, [pathname]);
}, [pathname, scrollTop]);
return (
<NagivationContext.Provider value={{
navigateTo, navigateHistory
push, replace, back, forward,
canBack, isBlocked, setIsBlocked
}}>
{children}
</NagivationContext.Provider>);

View File

@ -1,28 +1,32 @@
'use client';
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
import { type ErrorInfo } from '../components/BackendError';
import { useRSFormDetails } from '../hooks/useRSFormDetails';
import { ILibraryItem } from '../models/library';
import { ILibraryUpdateData } from '../models/library';
import { type ErrorData } from '@/components/InfoError';
import useRSFormDetails from '@/hooks/useRSFormDetails';
import { ILibraryItem } from '@/models/library';
import { ILibraryUpdateData } from '@/models/library';
import {
IConstituentaList, IConstituentaMeta, ICstCreateData,
ICstMovetoData, ICstRenameData, ICstUpdateData,
IRSForm, IRSFormUploadData
} from '../models/rsform';
} from '@/models/rsform';
import {
type DataCallback, deleteUnsubscribe,
getTRSFile,
getTRSFile,
patchConstituenta, patchDeleteConstituenta,
patchLibraryItem,
patchLibraryItem,
patchMoveConstituenta, patchRenameConstituenta,
patchResetAliases, patchUploadTRS, postClaimLibraryItem, postNewConstituenta, postSubscribe} from '../utils/backendAPI';
patchResetAliases, patchUploadTRS, postClaimLibraryItem, postNewConstituenta, postSubscribe
} from '@/utils/backendAPI';
import { useAuth } from './AuthContext';
import { useLibrary } from './LibraryContext';
interface IRSFormContext {
schema?: IRSForm
error: ErrorInfo
error: ErrorData
loading: boolean
processing: boolean
@ -329,4 +333,4 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
}}>
{ children }
</RSFormContext.Provider>);
}
}

View File

@ -1,7 +1,9 @@
'use client';
import { createContext, useContext, useLayoutEffect, useMemo, useState } from 'react';
import useLocalStorage from '../hooks/useLocalStorage';
import { darkT, IColorTheme, lightT } from '../utils/color';
import useLocalStorage from '@/hooks/useLocalStorage';
import { darkT, IColorTheme, lightT } from '@/utils/color';
interface IThemeContext {
viewportHeight: string
@ -53,7 +55,7 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
}
useLayoutEffect(() => {
setDarkClass(darkMode)
setDarkClass(darkMode);
}, [darkMode]);
useLayoutEffect(() => {
@ -85,4 +87,4 @@ export const ThemeState = ({ children }: ThemeStateProps) => {
}}>
{children}
</ThemeContext.Provider>);
}
}

View File

@ -1,17 +1,20 @@
'use client';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { ErrorInfo } from '../components/BackendError';
import { IUserProfile } from '../models/library';
import { IUserUpdateData } from '../models/library';
import { DataCallback, getProfile, patchProfile } from '../utils/backendAPI';
import { ErrorData } from '@/components/InfoError';
import { IUserProfile } from '@/models/library';
import { IUserUpdateData } from '@/models/library';
import { DataCallback, getProfile, patchProfile } from '@/utils/backendAPI';
import { useUsers } from './UsersContext';
interface IUserProfileContext {
user: IUserProfile | undefined
loading: boolean
processing: boolean
error: ErrorInfo
setError: (error: ErrorInfo) => void
error: ErrorData
setError: (error: ErrorData) => void
updateUser: (data: IUserUpdateData, callback?: DataCallback<IUserProfile>) => void
}
@ -36,7 +39,7 @@ export const UserProfileState = ({ children }: UserProfileStateProps) => {
const [user, setUser] = useState<IUserProfile | undefined>(undefined);
const [loading, setLoading] = useState(false);
const [processing, setProcessing] = useState(false);
const [error, setError] = useState<ErrorInfo>(undefined);
const [error, setError] = useState<ErrorData>(undefined);
const reload = useCallback(
() => {
@ -81,4 +84,4 @@ export const UserProfileState = ({ children }: UserProfileStateProps) => {
{children}
</ProfileContext.Provider>
);
};
};

View File

@ -1,7 +1,9 @@
'use client';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { type IUserInfo } from '../models/library';
import { getActiveUsers } from '../utils/backendAPI';
import { type IUserInfo } from '@/models/library';
import { getActiveUsers } from '@/utils/backendAPI';
interface IUsersContext {
users: IUserInfo[]
@ -68,4 +70,4 @@ export const UsersState = ({ children }: UsersStateProps) => {
}}>
{ children }
</UsersContext.Provider>);
}
}

View File

@ -1,15 +1,17 @@
'use client';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'react-toastify';
import Checkbox from '../components/Common/Checkbox';
import Modal, { ModalProps } from '../components/Common/Modal';
import TextArea from '../components/Common/TextArea';
import TextInput from '../components/Common/TextInput';
import { useLibrary } from '../context/LibraryContext';
import { useConceptNavigation } from '../context/NagivationContext';
import { ILibraryItem } from '../models/library';
import { IRSFormCreateData } from '../models/rsform';
import { cloneTitle } from '../utils/misc';
import Checkbox from '@/components/Common/Checkbox';
import Modal, { ModalProps } from '@/components/Common/Modal';
import TextArea from '@/components/Common/TextArea';
import TextInput from '@/components/Common/TextInput';
import { useLibrary } from '@/context/LibraryContext';
import { useConceptNavigation } from '@/context/NagivationContext';
import { ILibraryItem } from '@/models/library';
import { IRSFormCreateData } from '@/models/rsform';
import { cloneTitle } from '@/utils/misc';
interface DlgCloneLibraryItemProps
extends Pick<ModalProps, 'hideWindow'> {
@ -17,7 +19,7 @@ extends Pick<ModalProps, 'hideWindow'> {
}
function DlgCloneLibraryItem({ hideWindow, base }: DlgCloneLibraryItemProps) {
const { navigateTo } = useConceptNavigation();
const router = useConceptNavigation();
const [title, setTitle] = useState('');
const [alias, setAlias] = useState('');
const [comment, setComment] = useState('');
@ -49,7 +51,7 @@ function DlgCloneLibraryItem({ hideWindow, base }: DlgCloneLibraryItemProps) {
};
cloneItem(base.id, data, newSchema => {
toast.success(`Копия создана: ${newSchema.alias}`);
navigateTo(`/rsforms/${newSchema.id}`);
router.push(`/rsforms/${newSchema.id}`);
});
}
@ -86,4 +88,4 @@ function DlgCloneLibraryItem({ hideWindow, base }: DlgCloneLibraryItemProps) {
</Modal>);
}
export default DlgCloneLibraryItem;
export default DlgCloneLibraryItem;

View File

@ -1,15 +1,17 @@
'use client';
import { createColumnHelper } from '@tanstack/react-table';
import { Dispatch, useCallback, useEffect, useMemo, useState } from 'react';
import MiniButton from '../../components/Common/MiniButton';
import DataTable, { IConditionalStyle } from '../../components/DataTable';
import { ArrowsRotateIcon, CheckIcon, CrossIcon } from '../../components/Icons';
import RSInput from '../../components/RSInput';
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
import { useConceptTheme } from '../../context/ThemeContext';
import { IConstituenta, IRSForm } from '../../models/rsform';
import { IArgumentValue } from '../../models/rslang';
import { prefixes } from '../../utils/constants';
import MiniButton from '@/components/Common/MiniButton';
import DataTable, { IConditionalStyle } from '@/components/DataTable';
import { ArrowsRotateIcon, CheckIcon, CrossIcon } from '@/components/Icons';
import RSInput from '@/components/RSInput';
import ConstituentaPicker from '@/components/Shared/ConstituentaPicker';
import { useConceptTheme } from '@/context/ThemeContext';
import { IConstituenta, IRSForm } from '@/models/rsform';
import { IArgumentValue } from '@/models/rslang';
import { prefixes } from '@/utils/constants';
interface ArgumentsTabProps {
state: IArgumentsState
@ -203,4 +205,4 @@ function ArgumentsTab({ state, schema, partialUpdate }: ArgumentsTabProps) {
</div>);
}
export default ArgumentsTab;
export default ArgumentsTab;

View File

@ -1,12 +1,14 @@
'use client';
import { Dispatch } from 'react';
import SelectSingle from '../../components/Common/SelectSingle';
import TextArea from '../../components/Common/TextArea';
import TextInput from '../../components/Common/TextInput';
import RSInput from '../../components/RSInput';
import { CstType, ICstCreateData } from '../../models/rsform';
import { labelCstType } from '../../utils/labels';
import { SelectorCstType } from '../../utils/selectors';
import SelectSingle from '@/components/Common/SelectSingle';
import TextArea from '@/components/Common/TextArea';
import TextInput from '@/components/Common/TextInput';
import RSInput from '@/components/RSInput';
import { CstType, ICstCreateData } from '@/models/rsform';
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
interface ConstituentaTabProps {
state: ICstCreateData
@ -61,4 +63,4 @@ function ConstituentaTab({state, partialUpdate}: ConstituentaTabProps) {
</div>);
}
export default ConstituentaTab;
export default ConstituentaTab;

View File

@ -1,15 +1,18 @@
'use client';
import { useLayoutEffect, useState } from 'react';
import { TabList, TabPanel, Tabs } from 'react-tabs';
import ConceptTab from '../../components/Common/ConceptTab';
import Modal, { ModalProps } from '../../components/Common/Modal';
import Overlay from '../../components/Common/Overlay';
import HelpButton from '../../components/Help/HelpButton';
import usePartialUpdate from '../../hooks/usePartialUpdate';
import { HelpTopic } from '../../models/miscelanious';
import { CstType, ICstCreateData, IRSForm } from '../../models/rsform';
import { inferTemplatedType, substituteTemplateArgs } from '../../models/rslangAPI';
import { createAliasFor, validateCstAlias } from '../../utils/misc';
import ConceptTab from '@/components/Common/ConceptTab';
import Modal, { ModalProps } from '@/components/Common/Modal';
import Overlay from '@/components/Common/Overlay';
import HelpButton from '@/components/Help/HelpButton';
import usePartialUpdate from '@/hooks/usePartialUpdate';
import { HelpTopic } from '@/models/miscelanious';
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { inferTemplatedType, substituteTemplateArgs } from '@/models/rslangAPI';
import { createAliasFor, validateCstAlias } from '@/utils/misc';
import ArgumentsTab, { IArgumentsState } from './ArgumentsTab';
import ConstituentaTab from './ConstituentaTab';
import TemplateTab, { ITemplateState } from './TemplateTab';
@ -172,4 +175,4 @@ function DlgConstituentaTemplate({ hideWindow, schema, onCreate, insertAfter }:
</Modal>);
}
export default DlgConstituentaTemplate;
export default DlgConstituentaTemplate;

View File

@ -1,13 +1,15 @@
'use client';
import { Dispatch, useEffect, useMemo, useState } from 'react';
import SelectSingle from '../../components/Common/SelectSingle';
import TextArea from '../../components/Common/TextArea';
import RSInput from '../../components/RSInput';
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
import { useLibrary } from '../../context/LibraryContext';
import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '../../models/rsform';
import { applyFilterCategory } from '../../models/rsformAPI';
import { prefixes } from '../../utils/constants';
import SelectSingle from '@/components/Common/SelectSingle';
import TextArea from '@/components/Common/TextArea';
import RSInput from '@/components/RSInput';
import ConstituentaPicker from '@/components/Shared/ConstituentaPicker';
import { useLibrary } from '@/context/LibraryContext';
import { CATEGORY_CST_TYPE, IConstituenta, IRSForm } from '@/models/rsform';
import { applyFilterCategory } from '@/models/rsformAPI';
import { prefixes } from '@/utils/constants';
export interface ITemplateState {
templateID?: number
prototype?: IConstituenta

View File

@ -1,15 +1,17 @@
'use client';
import { useEffect, useLayoutEffect, useState } from 'react';
import Modal, { ModalProps } from '../components/Common/Modal';
import SelectSingle from '../components/Common/SelectSingle';
import TextArea from '../components/Common/TextArea';
import TextInput from '../components/Common/TextInput';
import RSInput from '../components/RSInput';
import usePartialUpdate from '../hooks/usePartialUpdate';
import { CstType,ICstCreateData, IRSForm } from '../models/rsform';
import { labelCstType } from '../utils/labels';
import { createAliasFor, validateCstAlias } from '../utils/misc';
import { SelectorCstType } from '../utils/selectors';
import Modal, { ModalProps } from '@/components/Common/Modal';
import SelectSingle from '@/components/Common/SelectSingle';
import TextArea from '@/components/Common/TextArea';
import TextInput from '@/components/Common/TextInput';
import RSInput from '@/components/RSInput';
import usePartialUpdate from '@/hooks/usePartialUpdate';
import { CstType,ICstCreateData, IRSForm } from '@/models/rsform';
import { labelCstType } from '@/utils/labels';
import { createAliasFor, validateCstAlias } from '@/utils/misc';
import { SelectorCstType } from '@/utils/selectors';
interface DlgCreateCstProps
extends Pick<ModalProps, 'hideWindow'> {
@ -100,4 +102,4 @@ function DlgCreateCst({ hideWindow, initial, schema, onCreate }: DlgCreateCstPro
</Modal>);
}
export default DlgCreateCst;
export default DlgCreateCst;

View File

@ -1,5 +1,5 @@
import { IConstituenta } from '../../models/rsform';
import { labelConstituenta } from '../../utils/labels';
import { IConstituenta } from '@/models/rsform';
import { labelConstituenta } from '@/utils/labels';
interface ConstituentsListProps {
list: number[]

View File

@ -1,9 +1,12 @@
'use client';
import { useMemo, useState } from 'react';
import Checkbox from '../../components/Common/Checkbox';
import Modal, { ModalProps } from '../../components/Common/Modal';
import { IRSForm } from '../../models/rsform';
import { prefixes } from '../../utils/constants';
import Checkbox from '@/components/Common/Checkbox';
import Modal, { ModalProps } from '@/components/Common/Modal';
import { IRSForm } from '@/models/rsform';
import { prefixes } from '@/utils/constants';
import ConstituentsList from './ConstituentsList';
interface DlgDeleteCstProps
@ -54,4 +57,4 @@ function DlgDeleteCst({ hideWindow, selected, schema, onDelete }: DlgDeleteCstPr
</Modal>);
}
export default DlgDeleteCst;
export default DlgDeleteCst;

View File

@ -1,14 +1,17 @@
'use client';
import { useState } from 'react';
import { TabList, TabPanel, Tabs } from 'react-tabs';
import ConceptTab from '../../components/Common/ConceptTab';
import Modal from '../../components/Common/Modal';
import Overlay from '../../components/Common/Overlay';
import HelpButton from '../../components/Help/HelpButton';
import { ReferenceType } from '../../models/language';
import { HelpTopic } from '../../models/miscelanious';
import { IConstituenta } from '../../models/rsform';
import { labelReferenceType } from '../../utils/labels';
import ConceptTab from '@/components/Common/ConceptTab';
import Modal from '@/components/Common/Modal';
import Overlay from '@/components/Common/Overlay';
import HelpButton from '@/components/Help/HelpButton';
import { ReferenceType } from '@/models/language';
import { HelpTopic } from '@/models/miscelanious';
import { IConstituenta } from '@/models/rsform';
import { labelReferenceType } from '@/utils/labels';
import EntityTab from './EntityTab';
import SyntacticTab from './SyntacticTab';
@ -95,4 +98,4 @@ function DlgEditReference({ hideWindow, items, initial, onSave }: DlgEditReferen
</Modal>);
}
export default DlgEditReference;
export default DlgEditReference;

View File

@ -1,16 +1,19 @@
'use client';
import { useEffect, useLayoutEffect, useState } from 'react';
import Label from '../../components/Common/Label';
import TextInput from '../../components/Common/TextInput';
import ConstituentaPicker from '../../components/Shared/ConstituentaPicker';
import SelectGrammeme from '../../components/Shared/SelectGrammeme';
import { ReferenceType } from '../../models/language';
import { parseEntityReference, parseGrammemes } from '../../models/languageAPI';
import { CstMatchMode } from '../../models/miscelanious';
import { IConstituenta } from '../../models/rsform';
import { matchConstituenta } from '../../models/rsformAPI';
import { prefixes } from '../../utils/constants';
import { IGrammemeOption, SelectorGrammems } from '../../utils/selectors';
import Label from '@/components/Common/Label';
import TextInput from '@/components/Common/TextInput';
import ConstituentaPicker from '@/components/Shared/ConstituentaPicker';
import SelectGrammeme from '@/components/Shared/SelectGrammeme';
import { ReferenceType } from '@/models/language';
import { parseEntityReference, parseGrammemes } from '@/models/languageAPI';
import { CstMatchMode } from '@/models/miscelanious';
import { IConstituenta } from '@/models/rsform';
import { matchConstituenta } from '@/models/rsformAPI';
import { prefixes } from '@/utils/constants';
import { IGrammemeOption, SelectorGrammems } from '@/utils/selectors';
import { IReferenceInputState } from './DlgEditReference';
import SelectWordForm from './SelectWordForm';

View File

@ -1,8 +1,11 @@
'use client';
import { useCallback } from 'react';
import { Grammeme } from '../../models/language';
import { prefixes } from '../../utils/constants';
import { IGrammemeOption, PremadeWordForms, SelectorGrammems } from '../../utils/selectors';
import { Grammeme } from '@/models/language';
import { prefixes } from '@/utils/constants';
import { IGrammemeOption, PremadeWordForms, SelectorGrammems } from '@/utils/selectors';
import WordformButton from './WordformButton';
interface SelectWordFormProps {

View File

@ -1,8 +1,11 @@
'use client';
import { useEffect, useLayoutEffect, useMemo, useState } from 'react';
import TextInput from '../../components/Common/TextInput';
import { ReferenceType } from '../../models/language';
import { parseSyntacticReference } from '../../models/languageAPI';
import TextInput from '@/components/Common/TextInput';
import { ReferenceType } from '@/models/language';
import { parseSyntacticReference } from '@/models/languageAPI';
import { IReferenceInputState } from './DlgEditReference';
interface SyntacticTabProps {

View File

@ -1,4 +1,4 @@
import { Grammeme } from '../../models/language';
import { Grammeme } from '@/models/language';
interface WordformButtonProps {
text: string
@ -20,4 +20,4 @@ function WordformButton({ text, example, grams, onSelectGrams, isSelected, ...re
</button>);
}
export default WordformButton;
export default WordformButton;

View File

@ -1,19 +1,22 @@
'use client';
import { useLayoutEffect, useState } from 'react';
import Label from '../../components/Common/Label';
import MiniButton from '../../components/Common/MiniButton';
import Modal from '../../components/Common/Modal';
import Overlay from '../../components/Common/Overlay';
import TextArea from '../../components/Common/TextArea';
import HelpButton from '../../components/Help/HelpButton';
import { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDoubleDownIcon } from '../../components/Icons';
import SelectGrammeme from '../../components/Shared/SelectGrammeme';
import useConceptText from '../../hooks/useConceptText';
import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '../../models/language';
import { parseGrammemes, wordFormEquals } from '../../models/languageAPI';
import { HelpTopic } from '../../models/miscelanious';
import { IConstituenta, TermForm } from '../../models/rsform';
import { IGrammemeOption, SelectorGrammemesList, SelectorGrammems } from '../../utils/selectors';
import Label from '@/components/Common/Label';
import MiniButton from '@/components/Common/MiniButton';
import Modal from '@/components/Common/Modal';
import Overlay from '@/components/Common/Overlay';
import TextArea from '@/components/Common/TextArea';
import HelpButton from '@/components/Help/HelpButton';
import { ArrowLeftIcon, ArrowRightIcon, CheckIcon, ChevronDoubleDownIcon } from '@/components/Icons';
import SelectGrammeme from '@/components/Shared/SelectGrammeme';
import useConceptText from '@/hooks/useConceptText';
import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '@/models/language';
import { parseGrammemes, wordFormEquals } from '@/models/languageAPI';
import { HelpTopic } from '@/models/miscelanious';
import { IConstituenta, TermForm } from '@/models/rsform';
import { IGrammemeOption, SelectorGrammemesList, SelectorGrammems } from '@/utils/selectors';
import WordFormsTable from './WordFormsTable';
interface DlgEditWordFormsProps {
@ -206,4 +209,4 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
</Modal>);
}
export default DlgEditWordForms;
export default DlgEditWordForms;

View File

@ -1,11 +1,13 @@
'use client';
import { useCallback, useMemo } from 'react';
import MiniButton from '../../components/Common/MiniButton';
import Overlay from '../../components/Common/Overlay';
import DataTable, { createColumnHelper } from '../../components/DataTable';
import { CrossIcon } from '../../components/Icons';
import WordFormBadge from '../../components/Shared/WordFormBadge';
import { IWordForm } from '../../models/language';
import MiniButton from '@/components/Common/MiniButton';
import Overlay from '@/components/Common/Overlay';
import DataTable, { createColumnHelper } from '@/components/DataTable';
import { CrossIcon } from '@/components/Icons';
import WordFormBadge from '@/components/Shared/WordFormBadge';
import { IWordForm } from '@/models/language';
interface WordFormsTableProps {
forms: IWordForm[]

View File

@ -1,9 +1,11 @@
import Checkbox from '../components/Common/Checkbox';
import Modal, { ModalProps } from '../components/Common/Modal';
import usePartialUpdate from '../hooks/usePartialUpdate';
import { GraphFilterParams } from '../models/miscelanious';
import { CstType } from '../models/rsform';
import { labelCstType } from '../utils/labels';
'use client';
import Checkbox from '@/components/Common/Checkbox';
import Modal, { ModalProps } from '@/components/Common/Modal';
import usePartialUpdate from '@/hooks/usePartialUpdate';
import { GraphFilterParams } from '@/models/miscelanious';
import { CstType } from '@/models/rsform';
import { labelCstType } from '@/utils/labels';
interface DlgGraphParamsProps
extends Pick<ModalProps, 'hideWindow'> {
@ -100,4 +102,4 @@ function DlgGraphParams({ hideWindow, initial, onConfirm } : DlgGraphParamsProps
</Modal>);
}
export default DlgGraphParams;
export default DlgGraphParams;

Some files were not shown because too many files have changed in this diff Show More