mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-25 20:40:36 +03:00
R: Refactoring folder structure: introducing features
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run
This commit is contained in:
parent
80473b0b82
commit
17b94b5e9a
|
@ -1,16 +1,16 @@
|
|||
import { Suspense } from 'react';
|
||||
import { Outlet } from 'react-router';
|
||||
|
||||
import ConceptToaster from '@/app/ConceptToaster';
|
||||
import Footer from '@/app/Footer';
|
||||
import Navigation from '@/app/Navigation';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { ModalLoader } from '@/components/ui/Modal';
|
||||
import { Loader } from '@/components/Loader';
|
||||
import { ModalLoader } from '@/components/Modal';
|
||||
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { Footer } from './Footer';
|
||||
import { GlobalDialogs } from './GlobalDialogs';
|
||||
import ConceptToaster from './GlobalToaster';
|
||||
import { GlobalTooltips } from './GlobalTooltips';
|
||||
import { Navigation } from './Navigation';
|
||||
import { NavigationState } from './Navigation/NavigationContext';
|
||||
|
||||
function ApplicationLayout() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { useNavigate, useRouteError } from 'react-router';
|
||||
|
||||
import InfoError from '@/components/info/InfoError';
|
||||
import { Button } from '@/components/ui/Control';
|
||||
import { Button } from '@/components/Control';
|
||||
import { InfoError } from '@/components/InfoError';
|
||||
|
||||
function ErrorFallback() {
|
||||
export function ErrorFallback() {
|
||||
const error = useRouteError();
|
||||
const router = useNavigate();
|
||||
|
||||
|
@ -18,5 +18,3 @@ function ErrorFallback() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ErrorFallback;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { TextURL } from '@/components/ui/Control';
|
||||
import { TextURL } from '@/components/Control';
|
||||
import { external_urls } from '@/utils/constants';
|
||||
|
||||
function Footer() {
|
||||
export function Footer() {
|
||||
return (
|
||||
<footer
|
||||
className={clsx(
|
||||
|
@ -25,5 +25,3 @@ function Footer() {
|
|||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
|
|
|
@ -2,32 +2,31 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { DialogType } from '@/models/miscellaneous';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { DialogType, useDialogsStore } from '@/stores/dialogs';
|
||||
|
||||
const DlgChangeInputSchema = React.lazy(() => import('@/dialogs/DlgChangeInputSchema'));
|
||||
const DlgChangeLocation = React.lazy(() => import('@/dialogs/DlgChangeLocation'));
|
||||
const DlgCloneLibraryItem = React.lazy(() => import('@/dialogs/DlgCloneLibraryItem'));
|
||||
const DlgCreateCst = React.lazy(() => import('@/dialogs/DlgCreateCst'));
|
||||
const DlgCreateOperation = React.lazy(() => import('@/dialogs/DlgCreateOperation'));
|
||||
const DlgCreateVersion = React.lazy(() => import('@/dialogs/DlgCreateVersion'));
|
||||
const DlgCstTemplate = React.lazy(() => import('@/dialogs/DlgCstTemplate'));
|
||||
const DlgDeleteCst = React.lazy(() => import('@/dialogs/DlgDeleteCst'));
|
||||
const DlgDeleteOperation = React.lazy(() => import('@/dialogs/DlgDeleteOperation'));
|
||||
const DlgEditEditors = React.lazy(() => import('@/dialogs/DlgEditEditors'));
|
||||
const DlgEditOperation = React.lazy(() => import('@/dialogs/DlgEditOperation'));
|
||||
const DlgEditReference = React.lazy(() => import('@/dialogs/DlgEditReference'));
|
||||
const DlgEditVersions = React.lazy(() => import('@/dialogs/DlgEditVersions'));
|
||||
const DlgEditWordForms = React.lazy(() => import('@/dialogs/DlgEditWordForms'));
|
||||
const DlgGraphParams = React.lazy(() => import('@/dialogs/DlgGraphParams'));
|
||||
const DlgInlineSynthesis = React.lazy(() => import('@/dialogs/DlgInlineSynthesis'));
|
||||
const DlgRelocateConstituents = React.lazy(() => import('@/dialogs/DlgRelocateConstituents'));
|
||||
const DlgRenameCst = React.lazy(() => import('@/dialogs/DlgRenameCst'));
|
||||
const DlgShowAST = React.lazy(() => import('@/dialogs/DlgShowAST'));
|
||||
const DlgShowQR = React.lazy(() => import('@/dialogs/DlgShowQR'));
|
||||
const DlgShowTypeGraph = React.lazy(() => import('@/dialogs/DlgShowTypeGraph'));
|
||||
const DlgSubstituteCst = React.lazy(() => import('@/dialogs/DlgSubstituteCst'));
|
||||
const DlgUploadRSForm = React.lazy(() => import('@/dialogs/DlgUploadRSForm'));
|
||||
const DlgChangeInputSchema = React.lazy(() => import('@/features/oss/dialogs/DlgChangeInputSchema'));
|
||||
const DlgChangeLocation = React.lazy(() => import('@/features/library/dialogs/DlgChangeLocation'));
|
||||
const DlgCloneLibraryItem = React.lazy(() => import('@/features/rsform/dialogs/DlgCloneLibraryItem'));
|
||||
const DlgCreateCst = React.lazy(() => import('@/features/rsform/dialogs/DlgCreateCst'));
|
||||
const DlgCreateOperation = React.lazy(() => import('@/features/oss/dialogs/DlgCreateOperation'));
|
||||
const DlgCreateVersion = React.lazy(() => import('@/features/rsform/dialogs/DlgCreateVersion'));
|
||||
const DlgCstTemplate = React.lazy(() => import('@/features/rsform/dialogs/DlgCstTemplate'));
|
||||
const DlgDeleteCst = React.lazy(() => import('@/features/rsform/dialogs/DlgDeleteCst'));
|
||||
const DlgDeleteOperation = React.lazy(() => import('@/features/oss/dialogs/DlgDeleteOperation'));
|
||||
const DlgEditEditors = React.lazy(() => import('@/features/rsform/dialogs/DlgEditEditors'));
|
||||
const DlgEditOperation = React.lazy(() => import('@/features/oss/dialogs/DlgEditOperation'));
|
||||
const DlgEditReference = React.lazy(() => import('@/features/rsform/dialogs/DlgEditReference'));
|
||||
const DlgEditVersions = React.lazy(() => import('@/features/rsform/dialogs/DlgEditVersions'));
|
||||
const DlgEditWordForms = React.lazy(() => import('@/features/rsform/dialogs/DlgEditWordForms'));
|
||||
const DlgGraphParams = React.lazy(() => import('@/features/rsform/dialogs/DlgGraphParams'));
|
||||
const DlgInlineSynthesis = React.lazy(() => import('@/features/rsform/dialogs/DlgInlineSynthesis'));
|
||||
const DlgRelocateConstituents = React.lazy(() => import('@/features/oss/dialogs/DlgRelocateConstituents'));
|
||||
const DlgRenameCst = React.lazy(() => import('@/features/rsform/dialogs/DlgRenameCst'));
|
||||
const DlgShowAST = React.lazy(() => import('@/features/rsform/dialogs/DlgShowAST'));
|
||||
const DlgShowQR = React.lazy(() => import('@/features/rsform/dialogs/DlgShowQR'));
|
||||
const DlgShowTypeGraph = React.lazy(() => import('@/features/rsform/dialogs/DlgShowTypeGraph'));
|
||||
const DlgSubstituteCst = React.lazy(() => import('@/features/rsform/dialogs/DlgSubstituteCst'));
|
||||
const DlgUploadRSForm = React.lazy(() => import('@/features/rsform/dialogs/DlgUploadRSForm'));
|
||||
|
||||
export const GlobalDialogs = () => {
|
||||
const active = useDialogsStore(state => state.active);
|
||||
|
|
|
@ -6,7 +6,6 @@ interface ToasterThemedProps extends Omit<ToastContainerProps, 'theme'> {}
|
|||
|
||||
function ToasterThemed(props: ToasterThemedProps) {
|
||||
const darkMode = usePreferencesStore(state => state.darkMode);
|
||||
|
||||
return <ToastContainer theme={darkMode ? 'dark' : 'light'} {...props} />;
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import InfoConstituenta from '@/components/info/InfoConstituenta';
|
||||
import { Tooltip } from '@/components/ui/Container';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { Tooltip } from '@/components/Container';
|
||||
import { Loader } from '@/components/Loader';
|
||||
import InfoConstituenta from '@/features/rsform/components/InfoConstituenta';
|
||||
import { useTooltipsStore } from '@/stores/tooltips';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { IconLibrary2, IconManuals, IconNewItem2 } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
|
@ -10,10 +9,11 @@ import { PARAMETER } from '@/utils/constants';
|
|||
import { urls } from '../urls';
|
||||
import Logo from './Logo';
|
||||
import NavigationButton from './NavigationButton';
|
||||
import { useConceptNavigation } from './NavigationContext';
|
||||
import ToggleNavigation from './ToggleNavigation';
|
||||
import UserMenu from './UserMenu';
|
||||
|
||||
function Navigation() {
|
||||
export function Navigation() {
|
||||
const router = useConceptNavigation();
|
||||
const size = useWindowSize();
|
||||
const noNavigationAnimation = useAppLayoutStore(state => state.noNavigationAnimation);
|
||||
|
@ -65,5 +65,3 @@ function Navigation() {
|
|||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
export default Navigation;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useAuthSuspense } from '@/backend/auth/useAuth';
|
||||
import { IconLogin, IconUser2 } from '@/components/Icons';
|
||||
import { useAuthSuspense } from '@/features/auth/backend/useAuth';
|
||||
import { usePreferencesStore } from '@/stores/preferences';
|
||||
|
||||
import NavigationButton from './NavigationButton';
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { useAuthSuspense } from '@/backend/auth/useAuth';
|
||||
import { useLogout } from '@/backend/auth/useLogout';
|
||||
import { Dropdown, DropdownButton } from '@/components/Dropdown';
|
||||
import {
|
||||
IconAdmin,
|
||||
IconAdminOff,
|
||||
|
@ -16,10 +14,12 @@ import {
|
|||
IconUser
|
||||
} from '@/components/Icons';
|
||||
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 { urls } from '../urls';
|
||||
import { useConceptNavigation } from './NavigationContext';
|
||||
|
||||
interface UserDropdownProps {
|
||||
isOpen: boolean;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Suspense } from 'react';
|
||||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { useDropdown } from '@/components/ui/Dropdown';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { useDropdown } from '@/components/Dropdown';
|
||||
import { Loader } from '@/components/Loader';
|
||||
|
||||
import { urls } from '../urls';
|
||||
import { useConceptNavigation } from './NavigationContext';
|
||||
import UserButton from './UserButton';
|
||||
import UserDropdown from './UserDropdown';
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { default } from './Navigation';
|
||||
export { Navigation } from './Navigation';
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { createBrowserRouter } from 'react-router';
|
||||
|
||||
import { prefetchAuth } from '@/backend/auth/useAuth';
|
||||
import { prefetchLibrary } from '@/backend/library/useLibrary';
|
||||
import { prefetchOSS } from '@/backend/oss/useOSS';
|
||||
import { prefetchRSForm } from '@/backend/rsform/useRSForm';
|
||||
import { prefetchProfile } from '@/backend/users/useProfile';
|
||||
import { prefetchUsers } from '@/backend/users/useUsers';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import CreateItemPage from '@/pages/CreateItemPage';
|
||||
import HomePage from '@/pages/HomePage';
|
||||
import LoginPage from '@/pages/LoginPage';
|
||||
import NotFoundPage from '@/pages/NotFoundPage';
|
||||
import { Loader } from '@/components/Loader';
|
||||
import { prefetchAuth } from '@/features/auth/backend/useAuth';
|
||||
import LoginPage from '@/features/auth/pages/LoginPage';
|
||||
import HomePage from '@/features/home/HomePage';
|
||||
import NotFoundPage from '@/features/home/NotFoundPage';
|
||||
import { prefetchLibrary } from '@/features/library/backend/useLibrary';
|
||||
import CreateItemPage from '@/features/library/pages/CreateItemPage';
|
||||
import { prefetchOSS } from '@/features/oss/backend/useOSS';
|
||||
import { prefetchRSForm } from '@/features/rsform/backend/useRSForm';
|
||||
import { prefetchProfile } from '@/features/users/backend/useProfile';
|
||||
import { prefetchUsers } from '@/features/users/backend/useUsers';
|
||||
|
||||
import ApplicationLayout from './ApplicationLayout';
|
||||
import ErrorFallback from './ErrorFallback';
|
||||
import { ErrorFallback } from './ErrorFallback';
|
||||
import { routes } from './urls';
|
||||
|
||||
export const Router = createBrowserRouter([
|
||||
|
@ -38,25 +38,25 @@ export const Router = createBrowserRouter([
|
|||
},
|
||||
{
|
||||
path: routes.signup,
|
||||
lazy: () => import('@/pages/RegisterPage')
|
||||
lazy: () => import('@/features/users/pages/RegisterPage')
|
||||
},
|
||||
{
|
||||
path: routes.profile,
|
||||
loader: prefetchProfile,
|
||||
lazy: () => import('@/pages/UserProfilePage')
|
||||
lazy: () => import('@/features/users/pages/UserProfilePage')
|
||||
},
|
||||
{
|
||||
path: routes.restore_password,
|
||||
lazy: () => import('@/pages/RestorePasswordPage')
|
||||
lazy: () => import('@/features/auth/pages/RestorePasswordPage')
|
||||
},
|
||||
{
|
||||
path: routes.password_change,
|
||||
lazy: () => import('@/pages/PasswordChangePage')
|
||||
lazy: () => import('@/features/auth/pages/PasswordChangePage')
|
||||
},
|
||||
{
|
||||
path: routes.library,
|
||||
loader: () => Promise.allSettled([prefetchLibrary(), prefetchUsers()]),
|
||||
lazy: () => import('@/pages/LibraryPage')
|
||||
lazy: () => import('@/features/library/pages/LibraryPage')
|
||||
},
|
||||
{
|
||||
path: routes.create_schema,
|
||||
|
@ -65,24 +65,24 @@ export const Router = createBrowserRouter([
|
|||
{
|
||||
path: `${routes.rsforms}/:id`,
|
||||
loader: data => prefetchRSForm(parseRSFormURL(data.params.id, data.request.url)),
|
||||
lazy: () => import('@/pages/RSFormPage')
|
||||
lazy: () => import('@/features/rsform/pages/RSFormPage')
|
||||
},
|
||||
{
|
||||
path: `${routes.oss}/:id`,
|
||||
loader: data => prefetchOSS(parseOssURL(data.params.id)),
|
||||
lazy: () => import('@/pages/OssPage')
|
||||
lazy: () => import('@/features/oss/pages/OssPage')
|
||||
},
|
||||
{
|
||||
path: routes.manuals,
|
||||
lazy: () => import('@/pages/ManualsPage')
|
||||
lazy: () => import('@/features/help/pages/ManualsPage')
|
||||
},
|
||||
{
|
||||
path: `${routes.icons}`,
|
||||
lazy: () => import('@/pages/IconsPage')
|
||||
lazy: () => import('@/features/home/IconsPage')
|
||||
},
|
||||
{
|
||||
path: `${routes.database_schema}`,
|
||||
lazy: () => import('@/pages/DatabaseSchemaPage')
|
||||
lazy: () => import('@/features/home/DatabaseSchemaPage')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
export { useConceptNavigation } from './Navigation/NavigationContext';
|
||||
export { useBlockNavigation } from './Navigation/NavigationContext';
|
||||
export { urls } from './urls';
|
||||
import { RouterProvider } from 'react-router';
|
||||
|
||||
import { Router } from './Router';
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
/**
|
||||
* Module: generic API for backend REST communications using axios library.
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import { AxiosError, AxiosRequestConfig } from 'axios';
|
||||
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { buildConstants } from '@/utils/buildConstants';
|
||||
import { extractErrorMessage } from '@/utils/utils';
|
||||
|
||||
export { AxiosError } from 'axios';
|
||||
export const isAxiosError = axios.isAxiosError;
|
||||
|
||||
const defaultOptions = {
|
||||
xsrfCookieName: 'csrftoken',
|
||||
xsrfHeaderName: 'x-csrftoken',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { QueryClient } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import { AxiosError } from './apiTransport';
|
||||
import { DELAYS } from './configuration';
|
||||
|
||||
declare module '@tanstack/react-query' {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface DividerProps extends CProps.Styling {
|
||||
/** Indicates whether the divider is vertical. */
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
/**
|
||||
* `flex` column container.
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface OverlayProps extends CProps.Styling {
|
||||
/** Id of the overlay. */
|
|
@ -1,8 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface ButtonProps extends CProps.Control, CProps.Colors, CProps.Button {
|
||||
/** Icon to display first. */
|
||||
icon?: React.ReactNode;
|
|
@ -1,8 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface MiniButtonProps extends CProps.Button {
|
||||
/** Button type. */
|
||||
type?: 'button' | 'submit';
|
|
@ -1,8 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface SelectorButtonProps extends CProps.Button {
|
||||
/** Text to display in the button. */
|
||||
text?: string;
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface SubmitButtonProps extends CProps.Button {
|
||||
/** Text to display in the button. */
|
|
@ -1,5 +1,4 @@
|
|||
export { Button } from './Button';
|
||||
export { LinkTopic } from './LinkTopic';
|
||||
export { MiniButton } from './MiniButton';
|
||||
export { SelectorButton } from './SelectorButton';
|
||||
export { SubmitButton } from './SubmitButton';
|
|
@ -17,8 +17,7 @@ import {
|
|||
} from '@tanstack/react-table';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
|
||||
import { CProps } from '../props';
|
||||
import DefaultNoData from './DefaultNoData';
|
||||
import PaginationTools from './PaginationTools';
|
||||
import TableBody from './TableBody';
|
|
@ -5,9 +5,10 @@ import { Table } from '@tanstack/react-table';
|
|||
import clsx from 'clsx';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '@/components/Icons';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
|
||||
import { IconPageFirst, IconPageLast, IconPageLeft, IconPageRight } from '../Icons';
|
||||
|
||||
interface PaginationToolsProps<TData> {
|
||||
id?: string;
|
||||
table: Table<TData>;
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { Table } from '@tanstack/react-table';
|
||||
|
||||
import { CheckboxTristate } from '@/components/ui/Input';
|
||||
import { CheckboxTristate } from '../Input';
|
||||
|
||||
interface SelectAllProps<TData> {
|
||||
table: Table<TData>;
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { Row } from '@tanstack/react-table';
|
||||
|
||||
import { Checkbox } from '@/components/ui/Input';
|
||||
import { Checkbox } from '../Input';
|
||||
|
||||
interface SelectRowProps<TData> {
|
||||
row: Row<TData>;
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { Column } from '@tanstack/react-table';
|
||||
|
||||
import { IconSortAsc, IconSortDesc } from '@/components/Icons';
|
||||
import { IconSortAsc, IconSortDesc } from '../Icons';
|
||||
|
||||
interface SortingIconProps<TData> {
|
||||
column: Column<TData>;
|
|
@ -3,8 +3,7 @@
|
|||
import { Cell, flexRender, Row, Table } from '@tanstack/react-table';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
|
||||
import { CProps } from '../props';
|
||||
import { IConditionalStyle } from '.';
|
||||
import SelectRow from './SelectRow';
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library';
|
||||
import { CstMatchMode, DependencyMode } from '@/models/miscellaneous';
|
||||
import { CstType, ExpressionStatus } from '@/models/rsform';
|
||||
import { AccessPolicy, LibraryItemType, LocationHead } from '@/features/library/models/library';
|
||||
import { CstType, ExpressionStatus } from '@/features/rsform/models/rsform';
|
||||
import { CstMatchMode, DependencyMode } from '@/features/rsform/stores/cstSearch';
|
||||
|
||||
import {
|
||||
IconAlias,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface DropdownProps extends CProps.Styling {
|
||||
/** Indicates whether the dropdown should stretch to the left. */
|
||||
stretchLeft?: boolean;
|
|
@ -1,9 +1,10 @@
|
|||
import axios, { type AxiosError } from 'axios';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { PrettyJson } from '@/components/ui/View';
|
||||
import { AxiosError, isAxiosError } from '@/backend/apiTransport';
|
||||
import { isResponseHtml } from '@/utils/utils';
|
||||
|
||||
import { PrettyJson } from './View';
|
||||
|
||||
export type ErrorData = string | Error | AxiosError | undefined | null;
|
||||
|
||||
interface InfoErrorProps {
|
||||
|
@ -15,7 +16,7 @@ function DescribeError({ error }: { error: ErrorData }) {
|
|||
return <p>Ошибки отсутствуют</p>;
|
||||
} else if (typeof error === 'string') {
|
||||
return <p>{error}</p>;
|
||||
} else if (!axios.isAxiosError(error)) {
|
||||
} else if (!isAxiosError(error)) {
|
||||
return (
|
||||
<div className='mt-6'>
|
||||
<p>
|
||||
|
@ -76,7 +77,7 @@ function DescribeError({ error }: { error: ErrorData }) {
|
|||
);
|
||||
}
|
||||
|
||||
function InfoError({ error }: InfoErrorProps) {
|
||||
export function InfoError({ error }: InfoErrorProps) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
|
@ -97,5 +98,3 @@ function InfoError({ error }: InfoErrorProps) {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default InfoError;
|
|
@ -1,9 +1,10 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CheckboxChecked } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CheckboxChecked } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
|
||||
export interface CheckboxProps extends Omit<CProps.Button, 'value' | 'onClick' | 'onChange'> {
|
||||
/** Label to display next to the checkbox. */
|
||||
label?: string;
|
|
@ -1,9 +1,9 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CheckboxChecked, CheckboxNull } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CheckboxChecked, CheckboxNull } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
import { CheckboxProps } from './Checkbox';
|
||||
|
||||
export interface CheckboxTristateProps extends Omit<CheckboxProps, 'value' | 'onChange'> {
|
|
@ -1,7 +1,7 @@
|
|||
import clsx from 'clsx';
|
||||
import { FieldError, GlobalError } from 'react-hook-form';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface ErrorFieldProps extends CProps.Styling {
|
||||
error?: FieldError | GlobalError;
|
|
@ -3,10 +3,9 @@
|
|||
import clsx from 'clsx';
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
import { IconUpload } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
|
||||
import { Button } from '../Control';
|
||||
import { IconUpload } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
import { Label } from './Label';
|
||||
|
||||
interface FileInputProps extends Omit<CProps.Input, 'accept' | 'type'> {
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface LabelProps extends CProps.Label {
|
||||
/** Text to display. */
|
|
@ -9,10 +9,11 @@ import Select, {
|
|||
StylesConfig
|
||||
} from 'react-select';
|
||||
|
||||
import { IconClose, IconDropArrow, IconDropArrowUp } from '@/components/Icons';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
import { APP_COLORS, SELECT_THEME } from '@/styling/color';
|
||||
|
||||
import { IconClose, IconDropArrow, IconDropArrowUp } from '../Icons';
|
||||
|
||||
function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
|
||||
props: DropdownIndicatorProps<Option, true, Group>
|
||||
) {
|
|
@ -9,10 +9,11 @@ import Select, {
|
|||
StylesConfig
|
||||
} from 'react-select';
|
||||
|
||||
import { IconClose, IconDropArrow, IconDropArrowUp } from '@/components/Icons';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
import { APP_COLORS, SELECT_THEME } from '@/styling/color';
|
||||
|
||||
import { IconClose, IconDropArrow, IconDropArrowUp } from '../Icons';
|
||||
|
||||
function DropdownIndicator<Option, Group extends GroupBase<Option> = GroupBase<Option>>(
|
||||
props: DropdownIndicatorProps<Option, false, Group>
|
||||
) {
|
|
@ -1,12 +1,12 @@
|
|||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { IconDropArrow, IconPageRight } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals, PARAMETER } from '@/utils/constants';
|
||||
|
||||
import { Overlay } from '../Container';
|
||||
import { MiniButton } from '../Control';
|
||||
import { IconDropArrow, IconPageRight } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface SelectTreeProps<ItemType> extends CProps.Styling {
|
||||
/** Current value. */
|
|
@ -1,8 +1,7 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { Label } from '@/components/ui/Input/Label';
|
||||
|
||||
import { Label } from '../Input/Label';
|
||||
import { CProps } from '../props';
|
||||
import { ErrorField } from './ErrorField';
|
||||
|
||||
export interface TextAreaProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.TextArea {
|
|
@ -1,8 +1,7 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { Label } from '@/components/ui/Input/Label';
|
||||
|
||||
import { Label } from '../Input/Label';
|
||||
import { CProps } from '../props';
|
||||
import { ErrorField } from './ErrorField';
|
||||
|
||||
interface TextInputProps extends CProps.Editor, CProps.ErrorProcessing, CProps.Colors, CProps.Input {
|
|
@ -54,7 +54,7 @@ const animatePulse = (startBig: boolean, duration: string) => {
|
|||
/**
|
||||
* Displays animated loader.
|
||||
*/
|
||||
function Loader({ scale = 5, circular }: LoaderProps) {
|
||||
export function Loader({ scale = 5, circular }: LoaderProps) {
|
||||
if (circular) {
|
||||
return (
|
||||
<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;
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { IconClose } from '@/components/Icons';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import { CProps } from '@/components/props';
|
||||
import { HelpTopic } from '@/features/help/models/helpTopic';
|
||||
import useEscapeKey from '@/hooks/useEscapeKey';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
import { prepareTooltip } from '@/utils/labels';
|
||||
|
||||
import { Button, MiniButton, SubmitButton } from '../Control';
|
||||
import { IconClose } from '../Icons';
|
||||
import { CProps } from '../props';
|
||||
import BadgeHelp from '../shared/BadgeHelp';
|
||||
import { ModalBackdrop } from './ModalBackdrop';
|
||||
|
||||
export interface ModalProps extends CProps.Styling {
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { Loader } from '@/components/Loader';
|
||||
|
||||
export function ModalLoader() {
|
||||
return (
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { IconClose } from '@/components/Icons';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import useEscapeKey from '@/hooks/useEscapeKey';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { PARAMETER } from '@/utils/constants';
|
||||
import { prepareTooltip } from '@/utils/labels';
|
||||
|
||||
import { Button, MiniButton } from '../Control';
|
||||
import { IconClose } from '../Icons';
|
||||
import BadgeHelp from '../shared/BadgeHelp';
|
||||
import { ModalBackdrop } from './ModalBackdrop';
|
||||
import { ModalProps } from './ModalForm';
|
||||
|
|
@ -2,9 +2,10 @@ import clsx from 'clsx';
|
|||
import type { TabProps as TabPropsImpl } from 'react-tabs';
|
||||
import { Tab as TabImpl } from 'react-tabs';
|
||||
|
||||
import { CProps } from '@/components/props';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import { CProps } from '../props';
|
||||
|
||||
interface TabLabelProps extends Omit<TabPropsImpl, 'children'>, CProps.Titled {
|
||||
/** Label to display in the tab. */
|
||||
label?: string;
|
|
@ -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;
|
|
@ -1,14 +1,14 @@
|
|||
import React, { Suspense } from 'react';
|
||||
|
||||
import { PlacesType, Tooltip } from '@/components/Container';
|
||||
import { TextURL } from '@/components/Control';
|
||||
import { IconHelp } from '@/components/Icons';
|
||||
import { Loader } from '@/components/Loader';
|
||||
import { CProps } from '@/components/props';
|
||||
import { PlacesType, Tooltip } from '@/components/ui/Container';
|
||||
import { TextURL } from '@/components/ui/Control';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { HelpTopic } from '@/features/help/models/helpTopic';
|
||||
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 {
|
||||
/** Topic to display in a tooltip. */
|
|
@ -1,11 +1,10 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { Overlay } from '@/components/Container';
|
||||
import { IconSearch } from '@/components/Icons';
|
||||
import { TextInput } from '@/components/Input';
|
||||
import { CProps } from '@/components/props';
|
||||
|
||||
import { Overlay } from './Container';
|
||||
import { TextInput } from './Input';
|
||||
|
||||
interface SearchBarProps extends CProps.Styling {
|
||||
/** Id of the search bar. */
|
||||
id?: string;
|
|
@ -3,9 +3,20 @@ import { z } from 'zod';
|
|||
|
||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||
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';
|
||||
|
||||
/**
|
||||
* Represents CurrentUser information.
|
||||
*/
|
||||
export interface ICurrentUser {
|
||||
id: UserID | null;
|
||||
username: string;
|
||||
is_staff: boolean;
|
||||
editor: LibraryItemID[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents login data, used to authenticate users.
|
||||
*/
|
|
@ -1,6 +1,7 @@
|
|||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
import { queryClient } from '../queryClient';
|
||||
import { queryClient } from '@/backend/queryClient';
|
||||
|
||||
import { authApi } from './api';
|
||||
|
||||
export function useAuth() {
|
|
@ -1,9 +1,8 @@
|
|||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { useAuthSuspense } from '@/backend/auth/useAuth';
|
||||
import { useLogout } from '@/backend/auth/useLogout';
|
||||
import { urls, useConceptNavigation } from '@/app';
|
||||
import { TextURL } from '@/components/Control';
|
||||
|
||||
import { TextURL } from './ui/Control';
|
||||
import { useAuthSuspense } from '../backend/useAuth';
|
||||
import { useLogout } from '../backend/useLogout';
|
||||
|
||||
function ExpectedAnonymous() {
|
||||
const { user } = useAuthSuspense();
|
|
@ -1,8 +1,8 @@
|
|||
'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) {
|
||||
const { isAnonymous } = useAuthSuspense();
|
|
@ -1,22 +1,22 @@
|
|||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import axios from 'axios';
|
||||
import clsx from 'clsx';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { IUserLoginDTO, UserLoginSchema } from '@/backend/auth/api';
|
||||
import { useAuthSuspense } from '@/backend/auth/useAuth';
|
||||
import { useLogin } from '@/backend/auth/useLogin';
|
||||
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 { urls, useConceptNavigation } from '@/app';
|
||||
import { isAxiosError } from '@/backend/apiTransport';
|
||||
import { SubmitButton, TextURL } from '@/components/Control';
|
||||
import { ErrorData } from '@/components/InfoError';
|
||||
import { TextInput } from '@/components/Input';
|
||||
import useQueryStrings from '@/hooks/useQueryStrings';
|
||||
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() {
|
||||
const router = useConceptNavigation();
|
||||
const query = useQueryStrings();
|
||||
|
@ -97,7 +97,7 @@ export default LoginPage;
|
|||
|
||||
// ====== Internals =========
|
||||
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 (
|
||||
<div className='text-sm select-text text-warn-600'>
|
||||
На Портале отсутствует такое сочетание имени пользователя и пароля
|
|
@ -1,18 +1,18 @@
|
|||
'use client';
|
||||
|
||||
import axios from 'axios';
|
||||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { useResetPassword } from '@/backend/auth/useResetPassword';
|
||||
import InfoError, { ErrorData } from '@/components/info/InfoError';
|
||||
import { SubmitButton } from '@/components/ui/Control';
|
||||
import { TextInput } from '@/components/ui/Input';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { urls, useConceptNavigation } from '@/app';
|
||||
import { isAxiosError } from '@/backend/apiTransport';
|
||||
import { SubmitButton } from '@/components/Control';
|
||||
import { ErrorData, InfoError } from '@/components/InfoError';
|
||||
import { TextInput } from '@/components/Input';
|
||||
import { Loader } from '@/components/Loader';
|
||||
import useQueryStrings from '@/hooks/useQueryStrings';
|
||||
|
||||
import { useResetPassword } from '../backend/useResetPassword';
|
||||
|
||||
export function Component() {
|
||||
const router = useConceptNavigation();
|
||||
const token = useQueryStrings().get('token') ?? '';
|
||||
|
@ -95,7 +95,7 @@ export function Component() {
|
|||
|
||||
// ====== Internals =========
|
||||
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 <InfoError error={error} />;
|
|
@ -1,13 +1,14 @@
|
|||
'use client';
|
||||
|
||||
import axios from 'axios';
|
||||
import clsx from 'clsx';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useRequestPasswordReset } from '@/backend/auth/useRequestPasswordReset';
|
||||
import { ErrorData } from '@/components/info/InfoError';
|
||||
import { SubmitButton, TextURL } from '@/components/ui/Control';
|
||||
import { TextInput } from '@/components/ui/Input';
|
||||
import { isAxiosError } from '@/backend/apiTransport';
|
||||
import { SubmitButton, TextURL } from '@/components/Control';
|
||||
import { ErrorData } from '@/components/InfoError';
|
||||
import { TextInput } from '@/components/Input';
|
||||
|
||||
import { useRequestPasswordReset } from '../backend/useRequestPasswordReset';
|
||||
|
||||
export function Component() {
|
||||
const { requestPasswordReset, isPending, error: serverError, reset: clearServerError } = useRequestPasswordReset();
|
||||
|
@ -61,7 +62,7 @@ export function Component() {
|
|||
|
||||
// ====== Internals =========
|
||||
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 (
|
||||
<div className='mx-auto mt-6 text-sm select-text text-warn-600'>Данный email не используется на Портале.</div>
|
||||
);
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { CstClass } from '@/models/rsform';
|
||||
import { CstClass } from '@/features/rsform/models/rsform';
|
||||
import { colorBgCstClass } from '@/styling/color';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
import { describeCstClass, labelCstClass } from '@/utils/labels';
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { ExpressionStatus } from '@/models/rsform';
|
||||
import { ExpressionStatus } from '@/features/rsform/models/rsform';
|
||||
import { colorBgCstStatus } from '@/styling/color';
|
||||
import { prefixes } from '@/utils/constants';
|
||||
import { describeExpressionStatus, labelExpressionStatus } from '@/utils/labels';
|
|
@ -1,7 +1,7 @@
|
|||
import { urls } from '@/app/urls';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { urls } from '@/app';
|
||||
import { TextURL } from '@/components/Control';
|
||||
|
||||
import { TextURL } from './TextURL';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
interface TextURLProps {
|
||||
/** Text to display. */
|
|
@ -1,13 +1,14 @@
|
|||
import { HelpTopic, topicParent } from '@/models/miscellaneous';
|
||||
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 {
|
||||
headTopic: HelpTopic;
|
||||
}
|
||||
|
||||
function Subtopics({ headTopic }: SubtopicsProps) {
|
||||
export function Subtopics({ headTopic }: SubtopicsProps) {
|
||||
return (
|
||||
<>
|
||||
<h2>Содержание раздела</h2>
|
||||
|
@ -19,5 +20,3 @@ function Subtopics({ headTopic }: SubtopicsProps) {
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Subtopics;
|
|
@ -1,17 +1,16 @@
|
|||
import { LinkTopic } from '@/components/ui/Control';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { describeHelpTopic, labelHelpTopic, removeTags } from '@/utils/labels';
|
||||
|
||||
import { LinkTopic } from '../components/LinkTopic';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
interface TopicItemProps {
|
||||
topic: HelpTopic;
|
||||
}
|
||||
|
||||
function TopicItem({ topic }: TopicItemProps) {
|
||||
export function TopicItem({ topic }: TopicItemProps) {
|
||||
return (
|
||||
<li>
|
||||
<LinkTopic text={labelHelpTopic(topic)} topic={topic} /> – {removeTags(describeHelpTopic(topic))}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export default TopicItem;
|
|
@ -1,8 +1,8 @@
|
|||
import { TextURL } from '@/components/ui/Control';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { TextURL } from '@/components/Control';
|
||||
import { external_urls } from '@/utils/constants';
|
||||
|
||||
import Subtopics from '../Subtopics';
|
||||
import { Subtopics } from '../components/Subtopics';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
function HelpConceptSystem() {
|
||||
return (
|
|
@ -1,4 +1,4 @@
|
|||
import { TextURL } from '@/components/ui/Control';
|
||||
import { TextURL } from '@/components/Control';
|
||||
import { external_urls, PARAMETER } from '@/utils/constants';
|
||||
|
||||
function HelpExteor() {
|
|
@ -1,6 +1,5 @@
|
|||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
|
||||
import Subtopics from '../Subtopics';
|
||||
import { Subtopics } from '../components/Subtopics';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
function HelpInfo() {
|
||||
return (
|
|
@ -8,9 +8,9 @@ import {
|
|||
IconPin,
|
||||
IconUser2
|
||||
} from '@/components/Icons';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
|
||||
import Subtopics from '../Subtopics';
|
||||
import { Subtopics } from '../components/Subtopics';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
function HelpInterface() {
|
||||
return (
|
|
@ -1,8 +1,9 @@
|
|||
import { LinkTopic, TextURL } from '@/components/ui/Control';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { TextURL } from '@/components/Control';
|
||||
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() {
|
||||
return (
|
|
@ -1,9 +1,9 @@
|
|||
import { EmbedYoutube } from '@/components/ui/View';
|
||||
import { EmbedYoutube } from '@/components/View';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
import { HelpTopic } from '@/models/miscellaneous';
|
||||
import { external_urls, youtube } from '@/utils/constants';
|
||||
|
||||
import Subtopics from '../Subtopics';
|
||||
import { Subtopics } from '../components/Subtopics';
|
||||
import { HelpTopic } from '../models/helpTopic';
|
||||
|
||||
function HelpRSLang() {
|
||||
const windowSize = useWindowSize();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user