R: Refactoring folder structure: introducing features

This commit is contained in:
Ivan 2025-02-10 01:32:16 +03:00
parent 8d611d5471
commit 9f84154237
435 changed files with 1786 additions and 1746 deletions

View File

@ -1,16 +1,16 @@
import { Suspense } from 'react'; import { Suspense } from 'react';
import { Outlet } from 'react-router'; import { Outlet } from 'react-router';
import ConceptToaster from '@/app/ConceptToaster'; import { Loader } from '@/components/Loader';
import Footer from '@/app/Footer'; import { ModalLoader } from '@/components/Modal';
import Navigation from '@/app/Navigation';
import Loader from '@/components/ui/Loader';
import { ModalLoader } from '@/components/ui/Modal';
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout'; import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { Footer } from './Footer';
import { GlobalDialogs } from './GlobalDialogs'; import { GlobalDialogs } from './GlobalDialogs';
import ConceptToaster from './GlobalToaster';
import { GlobalTooltips } from './GlobalTooltips'; import { GlobalTooltips } from './GlobalTooltips';
import { Navigation } from './Navigation';
import { NavigationState } from './Navigation/NavigationContext'; import { NavigationState } from './Navigation/NavigationContext';
function ApplicationLayout() { function ApplicationLayout() {

View File

@ -1,9 +1,9 @@
import { useNavigate, useRouteError } from 'react-router'; import { useNavigate, useRouteError } from 'react-router';
import InfoError from '@/components/info/InfoError'; import { Button } from '@/components/Control';
import { Button } from '@/components/ui/Control'; import { InfoError } from '@/components/InfoError';
function ErrorFallback() { export function ErrorFallback() {
const error = useRouteError(); const error = useRouteError();
const router = useNavigate(); const router = useNavigate();
@ -18,5 +18,3 @@ function ErrorFallback() {
</div> </div>
); );
} }
export default ErrorFallback;

View File

@ -1,9 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { TextURL } from '@/components/ui/Control'; import { TextURL } from '@/components/Control';
import { external_urls } from '@/utils/constants'; import { external_urls } from '@/utils/constants';
function Footer() { export function Footer() {
return ( return (
<footer <footer
className={clsx( className={clsx(
@ -25,5 +25,3 @@ function Footer() {
</footer> </footer>
); );
} }
export default Footer;

View File

@ -2,32 +2,31 @@
import React from 'react'; import React from 'react';
import { DialogType } from '@/models/miscellaneous'; import { DialogType, useDialogsStore } from '@/stores/dialogs';
import { useDialogsStore } from '@/stores/dialogs';
const DlgChangeInputSchema = React.lazy(() => import('@/dialogs/DlgChangeInputSchema')); const DlgChangeInputSchema = React.lazy(() => import('@/features/oss/dialogs/DlgChangeInputSchema'));
const DlgChangeLocation = React.lazy(() => import('@/dialogs/DlgChangeLocation')); const DlgChangeLocation = React.lazy(() => import('@/features/library/dialogs/DlgChangeLocation'));
const DlgCloneLibraryItem = React.lazy(() => import('@/dialogs/DlgCloneLibraryItem')); const DlgCloneLibraryItem = React.lazy(() => import('@/features/rsform/dialogs/DlgCloneLibraryItem'));
const DlgCreateCst = React.lazy(() => import('@/dialogs/DlgCreateCst')); const DlgCreateCst = React.lazy(() => import('@/features/rsform/dialogs/DlgCreateCst'));
const DlgCreateOperation = React.lazy(() => import('@/dialogs/DlgCreateOperation')); const DlgCreateOperation = React.lazy(() => import('@/features/oss/dialogs/DlgCreateOperation'));
const DlgCreateVersion = React.lazy(() => import('@/dialogs/DlgCreateVersion')); const DlgCreateVersion = React.lazy(() => import('@/features/rsform/dialogs/DlgCreateVersion'));
const DlgCstTemplate = React.lazy(() => import('@/dialogs/DlgCstTemplate')); const DlgCstTemplate = React.lazy(() => import('@/features/rsform/dialogs/DlgCstTemplate'));
const DlgDeleteCst = React.lazy(() => import('@/dialogs/DlgDeleteCst')); const DlgDeleteCst = React.lazy(() => import('@/features/rsform/dialogs/DlgDeleteCst'));
const DlgDeleteOperation = React.lazy(() => import('@/dialogs/DlgDeleteOperation')); const DlgDeleteOperation = React.lazy(() => import('@/features/oss/dialogs/DlgDeleteOperation'));
const DlgEditEditors = React.lazy(() => import('@/dialogs/DlgEditEditors')); const DlgEditEditors = React.lazy(() => import('@/features/rsform/dialogs/DlgEditEditors'));
const DlgEditOperation = React.lazy(() => import('@/dialogs/DlgEditOperation')); const DlgEditOperation = React.lazy(() => import('@/features/oss/dialogs/DlgEditOperation'));
const DlgEditReference = React.lazy(() => import('@/dialogs/DlgEditReference')); const DlgEditReference = React.lazy(() => import('@/features/rsform/dialogs/DlgEditReference'));
const DlgEditVersions = React.lazy(() => import('@/dialogs/DlgEditVersions')); const DlgEditVersions = React.lazy(() => import('@/features/rsform/dialogs/DlgEditVersions'));
const DlgEditWordForms = React.lazy(() => import('@/dialogs/DlgEditWordForms')); const DlgEditWordForms = React.lazy(() => import('@/features/rsform/dialogs/DlgEditWordForms'));
const DlgGraphParams = React.lazy(() => import('@/dialogs/DlgGraphParams')); const DlgGraphParams = React.lazy(() => import('@/features/rsform/dialogs/DlgGraphParams'));
const DlgInlineSynthesis = React.lazy(() => import('@/dialogs/DlgInlineSynthesis')); const DlgInlineSynthesis = React.lazy(() => import('@/features/rsform/dialogs/DlgInlineSynthesis'));
const DlgRelocateConstituents = React.lazy(() => import('@/dialogs/DlgRelocateConstituents')); const DlgRelocateConstituents = React.lazy(() => import('@/features/oss/dialogs/DlgRelocateConstituents'));
const DlgRenameCst = React.lazy(() => import('@/dialogs/DlgRenameCst')); const DlgRenameCst = React.lazy(() => import('@/features/rsform/dialogs/DlgRenameCst'));
const DlgShowAST = React.lazy(() => import('@/dialogs/DlgShowAST')); const DlgShowAST = React.lazy(() => import('@/features/rsform/dialogs/DlgShowAST'));
const DlgShowQR = React.lazy(() => import('@/dialogs/DlgShowQR')); const DlgShowQR = React.lazy(() => import('@/features/rsform/dialogs/DlgShowQR'));
const DlgShowTypeGraph = React.lazy(() => import('@/dialogs/DlgShowTypeGraph')); const DlgShowTypeGraph = React.lazy(() => import('@/features/rsform/dialogs/DlgShowTypeGraph'));
const DlgSubstituteCst = React.lazy(() => import('@/dialogs/DlgSubstituteCst')); const DlgSubstituteCst = React.lazy(() => import('@/features/rsform/dialogs/DlgSubstituteCst'));
const DlgUploadRSForm = React.lazy(() => import('@/dialogs/DlgUploadRSForm')); const DlgUploadRSForm = React.lazy(() => import('@/features/rsform/dialogs/DlgUploadRSForm'));
export const GlobalDialogs = () => { export const GlobalDialogs = () => {
const active = useDialogsStore(state => state.active); const active = useDialogsStore(state => state.active);

View File

@ -6,7 +6,6 @@ interface ToasterThemedProps extends Omit<ToastContainerProps, 'theme'> {}
function ToasterThemed(props: ToasterThemedProps) { function ToasterThemed(props: ToasterThemedProps) {
const darkMode = usePreferencesStore(state => state.darkMode); const darkMode = usePreferencesStore(state => state.darkMode);
return <ToastContainer theme={darkMode ? 'dark' : 'light'} {...props} />; return <ToastContainer theme={darkMode ? 'dark' : 'light'} {...props} />;
} }

View File

@ -1,8 +1,8 @@
'use client'; 'use client';
import InfoConstituenta from '@/components/info/InfoConstituenta'; import { Tooltip } from '@/components/Container';
import { Tooltip } from '@/components/ui/Container'; import { Loader } from '@/components/Loader';
import Loader from '@/components/ui/Loader'; import InfoConstituenta from '@/features/rsform/components/InfoConstituenta';
import { useTooltipsStore } from '@/stores/tooltips'; import { useTooltipsStore } from '@/stores/tooltips';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';

View File

@ -1,6 +1,5 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons'; import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons';
import { CProps } from '@/components/props'; import { CProps } from '@/components/props';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
@ -10,10 +9,11 @@ import { PARAMETER } from '@/utils/constants';
import { urls } from '../urls'; import { urls } from '../urls';
import Logo from './Logo'; import Logo from './Logo';
import NavigationButton from './NavigationButton'; import NavigationButton from './NavigationButton';
import { useConceptNavigation } from './NavigationContext';
import ToggleNavigation from './ToggleNavigation'; import ToggleNavigation from './ToggleNavigation';
import UserMenu from './UserMenu'; import UserMenu from './UserMenu';
function Navigation() { export function Navigation() {
const router = useConceptNavigation(); const router = useConceptNavigation();
const size = useWindowSize(); const size = useWindowSize();
const noNavigationAnimation = useAppLayoutStore(state => state.noNavigationAnimation); const noNavigationAnimation = useAppLayoutStore(state => state.noNavigationAnimation);
@ -65,5 +65,3 @@ function Navigation() {
</nav> </nav>
); );
} }
export default Navigation;

View File

@ -1,5 +1,5 @@
import { useAuthSuspense } from '@/backend/auth/useAuth';
import { IconLogin, IconUser2 } from '@/components/Icons'; import { IconLogin, IconUser2 } from '@/components/Icons';
import { useAuthSuspense } from '@/features/auth/backend/useAuth';
import { usePreferencesStore } from '@/stores/preferences'; import { usePreferencesStore } from '@/stores/preferences';
import NavigationButton from './NavigationButton'; import NavigationButton from './NavigationButton';

View File

@ -1,6 +1,4 @@
import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { Dropdown, DropdownButton } from '@/components/Dropdown';
import { useAuthSuspense } from '@/backend/auth/useAuth';
import { useLogout } from '@/backend/auth/useLogout';
import { import {
IconAdmin, IconAdmin,
IconAdminOff, IconAdminOff,
@ -16,10 +14,12 @@ import {
IconUser IconUser
} from '@/components/Icons'; } from '@/components/Icons';
import { CProps } from '@/components/props'; import { CProps } from '@/components/props';
import { Dropdown, DropdownButton } from '@/components/ui/Dropdown'; import { useAuthSuspense } from '@/features/auth/backend/useAuth';
import { useLogout } from '@/features/auth/backend/useLogout';
import { usePreferencesStore } from '@/stores/preferences'; import { usePreferencesStore } from '@/stores/preferences';
import { urls } from '../urls'; import { urls } from '../urls';
import { useConceptNavigation } from './NavigationContext';
interface UserDropdownProps { interface UserDropdownProps {
isOpen: boolean; isOpen: boolean;

View File

@ -1,10 +1,10 @@
import { Suspense } from 'react'; import { Suspense } from 'react';
import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { useDropdown } from '@/components/Dropdown';
import { useDropdown } from '@/components/ui/Dropdown'; import { Loader } from '@/components/Loader';
import Loader from '@/components/ui/Loader';
import { urls } from '../urls'; import { urls } from '../urls';
import { useConceptNavigation } from './NavigationContext';
import UserButton from './UserButton'; import UserButton from './UserButton';
import UserDropdown from './UserDropdown'; import UserDropdown from './UserDropdown';

View File

@ -1 +1 @@
export { default } from './Navigation'; export { Navigation } from './Navigation';

View File

@ -1,19 +1,19 @@
import { createBrowserRouter } from 'react-router'; import { createBrowserRouter } from 'react-router';
import { prefetchAuth } from '@/backend/auth/useAuth'; import { Loader } from '@/components/Loader';
import { prefetchLibrary } from '@/backend/library/useLibrary'; import { prefetchAuth } from '@/features/auth/backend/useAuth';
import { prefetchOSS } from '@/backend/oss/useOSS'; import LoginPage from '@/features/auth/pages/LoginPage';
import { prefetchRSForm } from '@/backend/rsform/useRSForm'; import HomePage from '@/features/home/HomePage';
import { prefetchProfile } from '@/backend/users/useProfile'; import NotFoundPage from '@/features/home/NotFoundPage';
import { prefetchUsers } from '@/backend/users/useUsers'; import { prefetchLibrary } from '@/features/library/backend/useLibrary';
import Loader from '@/components/ui/Loader'; import CreateItemPage from '@/features/library/pages/CreateItemPage';
import CreateItemPage from '@/pages/CreateItemPage'; import { prefetchOSS } from '@/features/oss/backend/useOSS';
import HomePage from '@/pages/HomePage'; import { prefetchRSForm } from '@/features/rsform/backend/useRSForm';
import LoginPage from '@/pages/LoginPage'; import { prefetchProfile } from '@/features/users/backend/useProfile';
import NotFoundPage from '@/pages/NotFoundPage'; import { prefetchUsers } from '@/features/users/backend/useUsers';
import ApplicationLayout from './ApplicationLayout'; import ApplicationLayout from './ApplicationLayout';
import ErrorFallback from './ErrorFallback'; import { ErrorFallback } from './ErrorFallback';
import { routes } from './urls'; import { routes } from './urls';
export const Router = createBrowserRouter([ export const Router = createBrowserRouter([
@ -38,25 +38,25 @@ export const Router = createBrowserRouter([
}, },
{ {
path: routes.signup, path: routes.signup,
lazy: () => import('@/pages/RegisterPage') lazy: () => import('@/features/users/pages/RegisterPage')
}, },
{ {
path: routes.profile, path: routes.profile,
loader: prefetchProfile, loader: prefetchProfile,
lazy: () => import('@/pages/UserProfilePage') lazy: () => import('@/features/users/pages/UserProfilePage')
}, },
{ {
path: routes.restore_password, path: routes.restore_password,
lazy: () => import('@/pages/RestorePasswordPage') lazy: () => import('@/features/auth/pages/RestorePasswordPage')
}, },
{ {
path: routes.password_change, path: routes.password_change,
lazy: () => import('@/pages/PasswordChangePage') lazy: () => import('@/features/auth/pages/PasswordChangePage')
}, },
{ {
path: routes.library, path: routes.library,
loader: () => Promise.allSettled([prefetchLibrary(), prefetchUsers()]), loader: () => Promise.allSettled([prefetchLibrary(), prefetchUsers()]),
lazy: () => import('@/pages/LibraryPage') lazy: () => import('@/features/library/pages/LibraryPage')
}, },
{ {
path: routes.create_schema, path: routes.create_schema,
@ -65,24 +65,24 @@ export const Router = createBrowserRouter([
{ {
path: `${routes.rsforms}/:id`, path: `${routes.rsforms}/:id`,
loader: data => prefetchRSForm(parseRSFormURL(data.params.id, data.request.url)), loader: data => prefetchRSForm(parseRSFormURL(data.params.id, data.request.url)),
lazy: () => import('@/pages/RSFormPage') lazy: () => import('@/features/rsform/pages/RSFormPage')
}, },
{ {
path: `${routes.oss}/:id`, path: `${routes.oss}/:id`,
loader: data => prefetchOSS(parseOssURL(data.params.id)), loader: data => prefetchOSS(parseOssURL(data.params.id)),
lazy: () => import('@/pages/OssPage') lazy: () => import('@/features/oss/pages/OssPage')
}, },
{ {
path: routes.manuals, path: routes.manuals,
lazy: () => import('@/pages/ManualsPage') lazy: () => import('@/features/help/pages/ManualsPage')
}, },
{ {
path: `${routes.icons}`, path: `${routes.icons}`,
lazy: () => import('@/pages/IconsPage') lazy: () => import('@/features/home/IconsPage')
}, },
{ {
path: `${routes.database_schema}`, path: `${routes.database_schema}`,
lazy: () => import('@/pages/DatabaseSchemaPage') lazy: () => import('@/features/home/DatabaseSchemaPage')
} }
] ]
} }

View File

@ -1,3 +1,6 @@
export { useConceptNavigation } from './Navigation/NavigationContext';
export { useBlockNavigation } from './Navigation/NavigationContext';
export { urls } from './urls';
import { RouterProvider } from 'react-router'; import { RouterProvider } from 'react-router';
import { Router } from './Router'; import { Router } from './Router';

View File

@ -1,13 +1,15 @@
/** /**
* Module: generic API for backend REST communications using axios library. * Module: generic API for backend REST communications using axios library.
*/ */
import axios from 'axios'; import axios, { AxiosError, AxiosRequestConfig } from 'axios';
import { AxiosError, AxiosRequestConfig } from 'axios';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { buildConstants } from '@/utils/buildConstants'; import { buildConstants } from '@/utils/buildConstants';
import { extractErrorMessage } from '@/utils/utils'; import { extractErrorMessage } from '@/utils/utils';
export { AxiosError } from 'axios';
export const isAxiosError = axios.isAxiosError;
const defaultOptions = { const defaultOptions = {
xsrfCookieName: 'csrftoken', xsrfCookieName: 'csrftoken',
xsrfHeaderName: 'x-csrftoken', xsrfHeaderName: 'x-csrftoken',

View File

@ -1,6 +1,6 @@
import { QueryClient } from '@tanstack/react-query'; import { QueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { AxiosError } from './apiTransport';
import { DELAYS } from './configuration'; import { DELAYS } from './configuration';
declare module '@tanstack/react-query' { declare module '@tanstack/react-query' {

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
interface DividerProps extends CProps.Styling { interface DividerProps extends CProps.Styling {
/** Indicates whether the divider is vertical. */ /** Indicates whether the divider is vertical. */

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
/** /**
* `flex` column container. * `flex` column container.

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
interface OverlayProps extends CProps.Styling { interface OverlayProps extends CProps.Styling {
/** Id of the overlay. */ /** Id of the overlay. */

View File

@ -1,8 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CProps } from '../props';
interface ButtonProps extends CProps.Control, CProps.Colors, CProps.Button { interface ButtonProps extends CProps.Control, CProps.Colors, CProps.Button {
/** Icon to display first. */ /** Icon to display first. */
icon?: React.ReactNode; icon?: React.ReactNode;

View File

@ -1,8 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CProps } from '../props';
interface MiniButtonProps extends CProps.Button { interface MiniButtonProps extends CProps.Button {
/** Button type. */ /** Button type. */
type?: 'button' | 'submit'; type?: 'button' | 'submit';

View File

@ -1,8 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CProps } from '../props';
interface SelectorButtonProps extends CProps.Button { interface SelectorButtonProps extends CProps.Button {
/** Text to display in the button. */ /** Text to display in the button. */
text?: string; text?: string;

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
interface SubmitButtonProps extends CProps.Button { interface SubmitButtonProps extends CProps.Button {
/** Text to display in the button. */ /** Text to display in the button. */

View File

@ -1,5 +1,4 @@
export { Button } from './Button'; export { Button } from './Button';
export { LinkTopic } from './LinkTopic';
export { MiniButton } from './MiniButton'; export { MiniButton } from './MiniButton';
export { SelectorButton } from './SelectorButton'; export { SelectorButton } from './SelectorButton';
export { SubmitButton } from './SubmitButton'; export { SubmitButton } from './SubmitButton';

View File

@ -17,8 +17,7 @@ import {
} from '@tanstack/react-table'; } from '@tanstack/react-table';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { CProps } from '@/components/props'; import { CProps } from '../props';
import DefaultNoData from './DefaultNoData'; import DefaultNoData from './DefaultNoData';
import PaginationTools from './PaginationTools'; import PaginationTools from './PaginationTools';
import TableBody from './TableBody'; import TableBody from './TableBody';

View File

@ -5,9 +5,10 @@ import { Table } from '@tanstack/react-table';
import clsx from 'clsx'; import clsx from 'clsx';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '@/components/Icons';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '../Icons';
interface PaginationToolsProps<TData> { interface PaginationToolsProps<TData> {
id?: string; id?: string;
table: Table<TData>; table: Table<TData>;

View File

@ -2,7 +2,7 @@
import { Table } from '@tanstack/react-table'; import { Table } from '@tanstack/react-table';
import { CheckboxTristate } from '@/components/ui/Input'; import { CheckboxTristate } from '../Input';
interface SelectAllProps<TData> { interface SelectAllProps<TData> {
table: Table<TData>; table: Table<TData>;

View File

@ -2,7 +2,7 @@
import { Row } from '@tanstack/react-table'; import { Row } from '@tanstack/react-table';
import { Checkbox } from '@/components/ui/Input'; import { Checkbox } from '../Input';
interface SelectRowProps<TData> { interface SelectRowProps<TData> {
row: Row<TData>; row: Row<TData>;

View File

@ -2,7 +2,7 @@
import { Column } from '@tanstack/react-table'; import { Column } from '@tanstack/react-table';
import { IconSortAsc, IconSortDesc } from '@/components/Icons'; import { IconSortAsc, IconSortDesc } from '../Icons';
interface SortingIconProps<TData> { interface SortingIconProps<TData> {
column: Column<TData>; column: Column<TData>;

View File

@ -3,8 +3,7 @@
import { Cell, flexRender, Row, Table } from '@tanstack/react-table'; import { Cell, flexRender, Row, Table } from '@tanstack/react-table';
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
import { IConditionalStyle } from '.'; import { IConditionalStyle } from '.';
import SelectRow from './SelectRow'; import SelectRow from './SelectRow';

View File

@ -1,6 +1,6 @@
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library'; import { AccessPolicy, LibraryItemType, LocationHead } from '@/features/library/models/library';
import { CstMatchMode, DependencyMode } from '@/models/miscellaneous'; import { CstType, ExpressionStatus } from '@/features/rsform/models/rsform';
import { CstType, ExpressionStatus } from '@/models/rsform'; import { CstMatchMode, DependencyMode } from '@/features/rsform/stores/cstSearch';
import { import {
IconAlias, IconAlias,

View File

@ -1,8 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
import { CProps } from '../props';
interface DropdownProps extends CProps.Styling { interface DropdownProps extends CProps.Styling {
/** Indicates whether the dropdown should stretch to the left. */ /** Indicates whether the dropdown should stretch to the left. */
stretchLeft?: boolean; stretchLeft?: boolean;

View File

@ -1,9 +1,10 @@
import axios, { type AxiosError } from 'axios';
import clsx from 'clsx'; import clsx from 'clsx';
import { PrettyJson } from '@/components/ui/View'; import { AxiosError, isAxiosError } from '@/backend/apiTransport';
import { isResponseHtml } from '@/utils/utils'; import { isResponseHtml } from '@/utils/utils';
import { PrettyJson } from './View';
export type ErrorData = string | Error | AxiosError | undefined | null; export type ErrorData = string | Error | AxiosError | undefined | null;
interface InfoErrorProps { interface InfoErrorProps {
@ -15,7 +16,7 @@ function DescribeError({ error }: { error: ErrorData }) {
return <p>Ошибки отсутствуют</p>; return <p>Ошибки отсутствуют</p>;
} else if (typeof error === 'string') { } else if (typeof error === 'string') {
return <p>{error}</p>; return <p>{error}</p>;
} else if (!axios.isAxiosError(error)) { } else if (!isAxiosError(error)) {
return ( return (
<div className='mt-6'> <div className='mt-6'>
<p> <p>
@ -76,7 +77,7 @@ function DescribeError({ error }: { error: ErrorData }) {
); );
} }
function InfoError({ error }: InfoErrorProps) { export function InfoError({ error }: InfoErrorProps) {
return ( return (
<div <div
className={clsx( className={clsx(
@ -97,5 +98,3 @@ function InfoError({ error }: InfoErrorProps) {
</div> </div>
); );
} }
export default InfoError;

View File

@ -1,9 +1,10 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CheckboxChecked } from '@/components/Icons';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CheckboxChecked } from '../Icons';
import { CProps } from '../props';
export interface CheckboxProps extends Omit<CProps.Button, 'value' | 'onClick' | 'onChange'> { export interface CheckboxProps extends Omit<CProps.Button, 'value' | 'onClick' | 'onChange'> {
/** Label to display next to the checkbox. */ /** Label to display next to the checkbox. */
label?: string; label?: string;

View File

@ -1,9 +1,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CheckboxChecked, CheckboxNull } from '@/components/Icons';
import { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CheckboxChecked, CheckboxNull } from '../Icons';
import { CProps } from '../props';
import { CheckboxProps } from './Checkbox'; import { CheckboxProps } from './Checkbox';
export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'onChange'> { export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'onChange'> {

View File

@ -1,7 +1,7 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { FieldError, GlobalError } from 'react-hook-form'; import { FieldError, GlobalError } from 'react-hook-form';
import { CProps } from '@/components/props'; import { CProps } from '../props';
interface ErrorFieldProps extends CProps.Styling { interface ErrorFieldProps extends CProps.Styling {
error?: FieldError | GlobalError; error?: FieldError | GlobalError;

View File

@ -3,10 +3,9 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { IconUpload } from '@/components/Icons';
import { CProps } from '@/components/props';
import { Button } from '../Control'; import { Button } from '../Control';
import { IconUpload } from '../Icons';
import { CProps } from '../props';
import { Label } from './Label'; import { Label } from './Label';
interface FileInputProps extends Omit<CProps.Input, 'accept' | 'type'> { interface FileInputProps extends Omit<CProps.Input, 'accept' | 'type'> {

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { CProps } from '../props';
interface LabelProps extends CProps.Label { interface LabelProps extends CProps.Label {
/** Text to display. */ /** Text to display. */

View File

@ -9,10 +9,11 @@ import Select, {
StylesConfig StylesConfig
} from 'react-select'; } from 'react-select';
import { IconClose, IconDropArrow, IconDropArrowUp } from '@/components/Icons';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
import { APP_COLORS, SELECT_THEME } from '@/styling/color'; import { APP_COLORS, SELECT_THEME } from '@/styling/color';
import { IconClose, IconDropArrow, IconDropArrowUp } from '../Icons';
function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>( function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
props: DropdownIndicatorProps<Option, true, Group> props: DropdownIndicatorProps<Option, true, Group>
) { ) {

View File

@ -9,10 +9,11 @@ import Select, {
StylesConfig StylesConfig
} from 'react-select'; } from 'react-select';
import { IconClose, IconDropArrow, IconDropArrowUp } from '@/components/Icons';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
import { APP_COLORS, SELECT_THEME } from '@/styling/color'; import { APP_COLORS, SELECT_THEME } from '@/styling/color';
import { IconClose, IconDropArrow, IconDropArrowUp } from '../Icons';
function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>( function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
props: DropdownIndicatorProps<Option, false, Group> props: DropdownIndicatorProps<Option, false, Group>
) { ) {

View File

@ -1,12 +1,12 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconDropArrow, IconPageRight } from '@/components/Icons';
import { CProps } from '@/components/props';
import { globals, PARAMETER } from '@/utils/constants'; import { globals, PARAMETER } from '@/utils/constants';
import { Overlay } from '../Container'; import { Overlay } from '../Container';
import { MiniButton } from '../Control'; import { MiniButton } from '../Control';
import { IconDropArrow, IconPageRight } from '../Icons';
import { CProps } from '../props';
interface SelectTreeProps<ItemType> extends CProps.Styling { interface SelectTreeProps<ItemType> extends CProps.Styling {
/** Current value. */ /** Current value. */

View File

@ -1,8 +1,7 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { Label } from '../Input/Label';
import { Label } from '@/components/ui/Input/Label'; import { CProps } from '../props';
import { ErrorField } from './ErrorField'; import { ErrorField } from './ErrorField';
export interface TextAreaProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.TextArea { export interface TextAreaProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.TextArea {

View File

@ -1,8 +1,7 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CProps } from '@/components/props'; import { Label } from '../Input/Label';
import { Label } from '@/components/ui/Input/Label'; import { CProps } from '../props';
import { ErrorField } from './ErrorField'; import { ErrorField } from './ErrorField';
interface TextInputProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.Input { interface TextInputProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.Input {

View File

@ -54,7 +54,7 @@ const animatePulse = (startBig: boolean, duration: string) => {
/** /**
* Displays animated loader. * Displays animated loader.
*/ */
function Loader({ scale = 5, circular }: LoaderProps) { export function Loader({ scale = 5, circular }: LoaderProps) {
if (circular) { if (circular) {
return ( return (
<div className='flex justify-center' aria-label='three-circles-loading' aria-busy='true' role='progressbar'> <div className='flex justify-center' aria-label='three-circles-loading' aria-busy='true' role='progressbar'>
@ -89,5 +89,3 @@ function Loader({ scale = 5, circular }: LoaderProps) {
); );
} }
} }
export default Loader;

View File

@ -2,16 +2,16 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { IconClose } from '@/components/Icons'; import { HelpTopic } from '@/features/help/models/helpTopic';
import BadgeHelp from '@/components/info/BadgeHelp';
import { CProps } from '@/components/props';
import useEscapeKey from '@/hooks/useEscapeKey'; import useEscapeKey from '@/hooks/useEscapeKey';
import { HelpTopic } from '@/models/miscellaneous';
import { useDialogsStore } from '@/stores/dialogs'; import { useDialogsStore } from '@/stores/dialogs';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels'; import { prepareTooltip } from '@/utils/labels';
import { Button, MiniButton, SubmitButton } from '../Control'; import { Button, MiniButton, SubmitButton } from '../Control';
import { IconClose } from '../Icons';
import { CProps } from '../props';
import BadgeHelp from '../shared/BadgeHelp';
import { ModalBackdrop } from './ModalBackdrop'; import { ModalBackdrop } from './ModalBackdrop';
export interface ModalProps extends CProps.Styling { export interface ModalProps extends CProps.Styling {

View File

@ -2,7 +2,7 @@
import clsx from 'clsx'; import clsx from 'clsx';
import Loader from '@/components/ui/Loader'; import { Loader } from '@/components/Loader';
export function ModalLoader() { export function ModalLoader() {
return ( return (

View File

@ -2,14 +2,14 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { IconClose } from '@/components/Icons';
import BadgeHelp from '@/components/info/BadgeHelp';
import useEscapeKey from '@/hooks/useEscapeKey'; import useEscapeKey from '@/hooks/useEscapeKey';
import { useDialogsStore } from '@/stores/dialogs'; import { useDialogsStore } from '@/stores/dialogs';
import { PARAMETER } from '@/utils/constants'; import { PARAMETER } from '@/utils/constants';
import { prepareTooltip } from '@/utils/labels'; import { prepareTooltip } from '@/utils/labels';
import { Button, MiniButton } from '../Control'; import { Button, MiniButton } from '../Control';
import { IconClose } from '../Icons';
import BadgeHelp from '../shared/BadgeHelp';
import { ModalBackdrop } from './ModalBackdrop'; import { ModalBackdrop } from './ModalBackdrop';
import { ModalProps } from './ModalForm'; import { ModalProps } from './ModalForm';

View File

@ -2,9 +2,10 @@ 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 { CProps } from '@/components/props';
import { globals } from '@/utils/constants'; import { globals } from '@/utils/constants';
import { CProps } from '../props';
interface TabLabelProps extends Omit<TabPropsImpl, 'children'>, CProps.Titled { interface TabLabelProps extends Omit<TabPropsImpl, 'children'>, CProps.Titled {
/** Label to display in the tab. */ /** Label to display in the tab. */
label?: string; label?: string;

View File

@ -1,37 +0,0 @@
'use client';
import clsx from 'clsx';
import { CProps } from '@/components/props';
import WordformButton from '@/dialogs/DlgEditReference/WordformButton';
import { Grammeme } from '@/models/language';
import { prefixes } from '@/utils/constants';
import { DefaultWordForms, IGrammemeOption, SelectorGrammemes } from '@/utils/selectors';
interface SelectWordFormProps extends CProps.Styling {
value: IGrammemeOption[];
onChange: React.Dispatch<React.SetStateAction<IGrammemeOption[]>>;
}
function SelectWordForm({ value, onChange, className, ...restProps }: SelectWordFormProps) {
function handleSelect(grams: Grammeme[]) {
onChange(SelectorGrammemes.filter(({ value }) => grams.includes(value as Grammeme)));
}
return (
<div className={clsx('text-xs sm:text-sm', className)} {...restProps}>
{DefaultWordForms.slice(0, 12).map((data, index) => (
<WordformButton
key={`${prefixes.wordform_list}${index}`}
text={data.text}
example={data.example}
grams={data.grams}
isSelected={data.grams.every(gram => value.find(item => (item.value as Grammeme) === gram))}
onSelectGrams={handleSelect}
/>
))}
</div>
);
}
export default SelectWordForm;

View File

@ -1,14 +1,14 @@
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
import { PlacesType, Tooltip } from '@/components/Container';
import { TextURL } from '@/components/Control';
import { IconHelp } from '@/components/Icons'; import { IconHelp } from '@/components/Icons';
import { Loader } from '@/components/Loader';
import { CProps } from '@/components/props'; import { CProps } from '@/components/props';
import { PlacesType, Tooltip } from '@/components/ui/Container'; import { HelpTopic } from '@/features/help/models/helpTopic';
import { TextURL } from '@/components/ui/Control';
import Loader from '@/components/ui/Loader';
import { HelpTopic } from '@/models/miscellaneous';
import { usePreferencesStore } from '@/stores/preferences'; import { usePreferencesStore } from '@/stores/preferences';
const TopicPage = React.lazy(() => import('@/pages/ManualsPage/TopicPage')); const TopicPage = React.lazy(() => import('@/features/help/pages/ManualsPage/TopicPage'));
interface BadgeHelpProps extends CProps.Styling { interface BadgeHelpProps extends CProps.Styling {
/** Topic to display in a tooltip. */ /** Topic to display in a tooltip. */

View File

@ -1,11 +1,10 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { Overlay } from '@/components/Container';
import { IconSearch } from '@/components/Icons'; import { IconSearch } from '@/components/Icons';
import { TextInput } from '@/components/Input';
import { CProps } from '@/components/props'; import { CProps } from '@/components/props';
import { Overlay } from './Container';
import { TextInput } from './Input';
interface SearchBarProps extends CProps.Styling { interface SearchBarProps extends CProps.Styling {
/** Id of the search bar. */ /** Id of the search bar. */
id?: string; id?: string;

View File

@ -3,9 +3,20 @@ import { z } from 'zod';
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport'; import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
import { DELAYS } from '@/backend/configuration'; import { DELAYS } from '@/backend/configuration';
import { ICurrentUser } from '@/models/user'; import { LibraryItemID } from '@/features/library/models/library';
import { UserID } from '@/features/users/models/user';
import { errors, information } from '@/utils/labels'; import { errors, information } from '@/utils/labels';
/**
* Represents CurrentUser information.
*/
export interface ICurrentUser {
id: UserID | null;
username: string;
is_staff: boolean;
editor: LibraryItemID[];
}
/** /**
* Represents login data, used to authenticate users. * Represents login data, used to authenticate users.
*/ */

View File

@ -1,6 +1,7 @@
import { useQuery, useSuspenseQuery } from '@tanstack/react-query'; import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
import { queryClient } from '../queryClient'; import { queryClient } from '@/backend/queryClient';
import { authApi } from './api'; import { authApi } from './api';
export function useAuth() { export function useAuth() {

View File

@ -1,9 +1,8 @@
import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { urls, useConceptNavigation } from '@/app';
import { urls } from '@/app/urls'; import { TextURL } from '@/components/Control';
import { useAuthSuspense } from '@/backend/auth/useAuth';
import { useLogout } from '@/backend/auth/useLogout';
import { TextURL } from './ui/Control'; import { useAuthSuspense } from '../backend/useAuth';
import { useLogout } from '../backend/useLogout';
function ExpectedAnonymous() { function ExpectedAnonymous() {
const { user } = useAuthSuspense(); const { user } = useAuthSuspense();

View File

@ -1,8 +1,8 @@
'use client'; 'use client';
import { useAuthSuspense } from '@/backend/auth/useAuth'; import { TextURL } from '@/components/Control';
import { TextURL } from './ui/Control'; import { useAuthSuspense } from '../backend/useAuth';
function RequireAuth({ children }: React.PropsWithChildren) { function RequireAuth({ children }: React.PropsWithChildren) {
const { isAnonymous } = useAuthSuspense(); const { isAnonymous } = useAuthSuspense();

View File

@ -1,22 +1,22 @@
'use client'; 'use client';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import axios from 'axios';
import clsx from 'clsx'; import clsx from 'clsx';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { urls, useConceptNavigation } from '@/app';
import { urls } from '@/app/urls'; import { isAxiosError } from '@/backend/apiTransport';
import { IUserLoginDTO, UserLoginSchema } from '@/backend/auth/api'; import { SubmitButton, TextURL } from '@/components/Control';
import { useAuthSuspense } from '@/backend/auth/useAuth'; import { ErrorData } from '@/components/InfoError';
import { useLogin } from '@/backend/auth/useLogin'; import { TextInput } from '@/components/Input';
import ExpectedAnonymous from '@/components/ExpectedAnonymous';
import { ErrorData } from '@/components/info/InfoError';
import { SubmitButton, TextURL } from '@/components/ui/Control';
import { TextInput } from '@/components/ui/Input';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { resources } from '@/utils/constants'; import { resources } from '@/utils/constants';
import { IUserLoginDTO, UserLoginSchema } from '../backend/api';
import { useAuthSuspense } from '../backend/useAuth';
import { useLogin } from '../backend/useLogin';
import ExpectedAnonymous from '../components/ExpectedAnonymous';
function LoginPage() { function LoginPage() {
const router = useConceptNavigation(); const router = useConceptNavigation();
const query = useQueryStrings(); const query = useQueryStrings();
@ -97,7 +97,7 @@ export default LoginPage;
// ====== Internals ========= // ====== Internals =========
function ServerError({ error }: { error: ErrorData }): React.ReactElement | null { function ServerError({ error }: { error: ErrorData }): React.ReactElement | null {
if (axios.isAxiosError(error) && error.response && error.response.status === 400) { if (isAxiosError(error) && error.response && error.response.status === 400) {
return ( return (
<div className='text-sm select-text text-warn-600'> <div className='text-sm select-text text-warn-600'>
На Портале отсутствует такое сочетание имени пользователя и пароля На Портале отсутствует такое сочетание имени пользователя и пароля

View File

@ -1,18 +1,18 @@
'use client'; 'use client';
import axios from 'axios';
import clsx from 'clsx'; import clsx from 'clsx';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useConceptNavigation } from '@/app/Navigation/NavigationContext'; import { urls, useConceptNavigation } from '@/app';
import { urls } from '@/app/urls'; import { isAxiosError } from '@/backend/apiTransport';
import { useResetPassword } from '@/backend/auth/useResetPassword'; import { SubmitButton } from '@/components/Control';
import InfoError, { ErrorData } from '@/components/info/InfoError'; import { ErrorData, InfoError } from '@/components/InfoError';
import { SubmitButton } from '@/components/ui/Control'; import { TextInput } from '@/components/Input';
import { TextInput } from '@/components/ui/Input'; import { Loader } from '@/components/Loader';
import Loader from '@/components/ui/Loader';
import useQueryStrings from '@/hooks/useQueryStrings'; import useQueryStrings from '@/hooks/useQueryStrings';
import { useResetPassword } from '../backend/useResetPassword';
export function Component() { export function Component() {
const router = useConceptNavigation(); const router = useConceptNavigation();
const token = useQueryStrings().get('token') ?? ''; const token = useQueryStrings().get('token') ?? '';
@ -95,7 +95,7 @@ export function Component() {
// ====== Internals ========= // ====== Internals =========
function ServerError({ error }: { error: ErrorData }): React.ReactElement { function ServerError({ error }: { error: ErrorData }): React.ReactElement {
if (axios.isAxiosError(error) && error.response && error.response.status === 404) { if (isAxiosError(error) && error.response && error.response.status === 404) {
return <div className='mx-auto mt-6 text-sm select-text text-warn-600'>Данная ссылка не действительна</div>; return <div className='mx-auto mt-6 text-sm select-text text-warn-600'>Данная ссылка не действительна</div>;
} }
return <InfoError error={error} />; return <InfoError error={error} />;

View File

@ -1,13 +1,14 @@
'use client'; 'use client';
import axios from 'axios';
import clsx from 'clsx'; import clsx from 'clsx';
import { useState } from 'react'; import { useState } from 'react';
import { useRequestPasswordReset } from '@/backend/auth/useRequestPasswordReset'; import { isAxiosError } from '@/backend/apiTransport';
import { ErrorData } from '@/components/info/InfoError'; import { SubmitButton, TextURL } from '@/components/Control';
import { SubmitButton, TextURL } from '@/components/ui/Control'; import { ErrorData } from '@/components/InfoError';
import { TextInput } from '@/components/ui/Input'; import { TextInput } from '@/components/Input';
import { useRequestPasswordReset } from '../backend/useRequestPasswordReset';
export function Component() { export function Component() {
const { requestPasswordReset, isPending, error: serverError, reset: clearServerError } = useRequestPasswordReset(); const { requestPasswordReset, isPending, error: serverError, reset: clearServerError } = useRequestPasswordReset();
@ -61,7 +62,7 @@ export function Component() {
// ====== Internals ========= // ====== Internals =========
function ServerError({ error }: { error: ErrorData }): React.ReactElement { function ServerError({ error }: { error: ErrorData }): React.ReactElement {
if (axios.isAxiosError(error) && error.response && error.response.status === 400) { if (isAxiosError(error) && error.response && error.response.status === 400) {
return ( return (
<div className='mx-auto mt-6 text-sm select-text text-warn-600'>Данный email не используется на Портале.</div> <div className='mx-auto mt-6 text-sm select-text text-warn-600'>Данный email не используется на Портале.</div>
); );

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { CstClass } from '@/models/rsform'; import { CstClass } from '@/features/rsform/models/rsform';
import { colorBgCstClass } from '@/styling/color'; import { colorBgCstClass } from '@/styling/color';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
import { describeCstClass, labelCstClass } from '@/utils/labels'; import { describeCstClass, labelCstClass } from '@/utils/labels';

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'; import clsx from 'clsx';
import { ExpressionStatus } from '@/models/rsform'; import { ExpressionStatus } from '@/features/rsform/models/rsform';
import { colorBgCstStatus } from '@/styling/color'; import { colorBgCstStatus } from '@/styling/color';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
import { describeExpressionStatus, labelExpressionStatus } from '@/utils/labels'; import { describeExpressionStatus, labelExpressionStatus } from '@/utils/labels';

View File

@ -1,7 +1,7 @@
import { urls } from '@/app/urls'; import { urls } from '@/app';
import { HelpTopic } from '@/models/miscellaneous'; import { TextURL } from '@/components/Control';
import { TextURL } from './TextURL'; import { HelpTopic } from '../models/helpTopic';
interface TextURLProps { interface TextURLProps {
/** Text to display. */ /** Text to display. */

View File

@ -1,13 +1,14 @@
import { HelpTopic, topicParent } from '@/models/miscellaneous';
import { prefixes } from '@/utils/constants'; import { prefixes } from '@/utils/constants';
import TopicItem from './TopicItem'; import { topicParent } from '../models/helpTopic';
import { HelpTopic } from '../models/helpTopic';
import { TopicItem } from './TopicItem';
interface SubtopicsProps { interface SubtopicsProps {
headTopic: HelpTopic; headTopic: HelpTopic;
} }
function Subtopics({ headTopic }: SubtopicsProps) { export function Subtopics({ headTopic }: SubtopicsProps) {
return ( return (
<> <>
<h2>Содержание раздела</h2> <h2>Содержание раздела</h2>
@ -19,5 +20,3 @@ function Subtopics({ headTopic }: SubtopicsProps) {
</> </>
); );
} }
export default Subtopics;

View File

@ -1,17 +1,16 @@
import { LinkTopic } from '@/components/ui/Control';
import { HelpTopic } from '@/models/miscellaneous';
import { describeHelpTopic, labelHelpTopic, removeTags } from '@/utils/labels'; import { describeHelpTopic, labelHelpTopic, removeTags } from '@/utils/labels';
import { LinkTopic } from '../components/LinkTopic';
import { HelpTopic } from '../models/helpTopic';
interface TopicItemProps { interface TopicItemProps {
topic: HelpTopic; topic: HelpTopic;
} }
function TopicItem({ topic }: TopicItemProps) { export function TopicItem({ topic }: TopicItemProps) {
return ( return (
<li> <li>
<LinkTopic text={labelHelpTopic(topic)} topic={topic} /> {removeTags(describeHelpTopic(topic))} <LinkTopic text={labelHelpTopic(topic)} topic={topic} /> {removeTags(describeHelpTopic(topic))}
</li> </li>
); );
} }
export default TopicItem;

View File

@ -1,8 +1,8 @@
import { TextURL } from '@/components/ui/Control'; import { TextURL } from '@/components/Control';
import { HelpTopic } from '@/models/miscellaneous';
import { external_urls } from '@/utils/constants'; import { external_urls } from '@/utils/constants';
import Subtopics from '../Subtopics'; import { Subtopics } from '../components/Subtopics';
import { HelpTopic } from '../models/helpTopic';
function HelpConceptSystem() { function HelpConceptSystem() {
return ( return (

View File

@ -1,4 +1,4 @@
import { TextURL } from '@/components/ui/Control'; import { TextURL } from '@/components/Control';
import { external_urls, PARAMETER } from '@/utils/constants'; import { external_urls, PARAMETER } from '@/utils/constants';
function HelpExteor() { function HelpExteor() {

View File

@ -1,6 +1,5 @@
import { HelpTopic } from '@/models/miscellaneous'; import { Subtopics } from '../components/Subtopics';
import { HelpTopic } from '../models/helpTopic';
import Subtopics from '../Subtopics';
function HelpInfo() { function HelpInfo() {
return ( return (

View File

@ -8,9 +8,9 @@ import {
IconPin, IconPin,
IconUser2 IconUser2
} from '@/components/Icons'; } from '@/components/Icons';
import { HelpTopic } from '@/models/miscellaneous';
import Subtopics from '../Subtopics'; import { Subtopics } from '../components/Subtopics';
import { HelpTopic } from '../models/helpTopic';
function HelpInterface() { function HelpInterface() {
return ( return (

View File

@ -1,8 +1,9 @@
import { LinkTopic, TextURL } from '@/components/ui/Control'; import { TextURL } from '@/components/Control';
import { HelpTopic } from '@/models/miscellaneous';
import { external_urls, prefixes } from '@/utils/constants'; import { external_urls, prefixes } from '@/utils/constants';
import TopicItem from '../TopicItem'; import { LinkTopic } from '../components/LinkTopic';
import { TopicItem } from '../components/TopicItem';
import { HelpTopic } from '../models/helpTopic';
function HelpMain() { function HelpMain() {
return ( return (

View File

@ -1,9 +1,9 @@
import { EmbedYoutube } from '@/components/ui/View'; import { EmbedYoutube } from '@/components/View';
import useWindowSize from '@/hooks/useWindowSize'; import useWindowSize from '@/hooks/useWindowSize';
import { HelpTopic } from '@/models/miscellaneous';
import { external_urls, youtube } from '@/utils/constants'; import { external_urls, youtube } from '@/utils/constants';
import Subtopics from '../Subtopics'; import { Subtopics } from '../components/Subtopics';
import { HelpTopic } from '../models/helpTopic';
function HelpRSLang() { function HelpRSLang() {
const windowSize = useWindowSize(); const windowSize = useWindowSize();

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