mirror of
https://github.com/morpheus65535/bazarr
synced 2025-03-13 15:38:47 +00:00
Update all UI dependencies and update React version to 18 (#2127)
This commit is contained in:
parent
07f6666d46
commit
933a456b03
46 changed files with 1364 additions and 1246 deletions
2161
frontend/package-lock.json
generated
2161
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -13,17 +13,17 @@
|
|||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@mantine/core": "^5.6.0",
|
||||
"@mantine/dropzone": "^5.6.0",
|
||||
"@mantine/form": "^5.6.0",
|
||||
"@mantine/hooks": "^5.6.0",
|
||||
"@mantine/modals": "^5.6.0",
|
||||
"@mantine/notifications": "^5.6.0",
|
||||
"axios": "^0.27.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"@mantine/core": "^6.0.0",
|
||||
"@mantine/dropzone": "^6.0.0",
|
||||
"@mantine/form": "^6.0.0",
|
||||
"@mantine/hooks": "^6.0.0",
|
||||
"@mantine/modals": "^6.0.0",
|
||||
"@mantine/notifications": "^6.0.0",
|
||||
"axios": "^1.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-query": "^3.39.2",
|
||||
"react-router-dom": "~6.3.0",
|
||||
"react-router-dom": "~6.10.0",
|
||||
"socket.io-client": "^4.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -34,36 +34,35 @@
|
|||
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^12.1.0",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/lodash": "^4.14.0",
|
||||
"@types/node": "^18.11.7",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@types/node": "^18.16.0",
|
||||
"@types/react": "^18.2.0",
|
||||
"@types/react-dom": "^18.2.0",
|
||||
"@types/react-table": "^7.7.0",
|
||||
"@vitejs/plugin-react": "^2.2.0",
|
||||
"@vitest/coverage-c8": "^0.28.5",
|
||||
"@vitest/ui": "^0.29.1",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"vitest": "^0.30.1",
|
||||
"@vitest/coverage-c8": "^0.30.0",
|
||||
"@vitest/ui": "^0.30.0",
|
||||
"clsx": "^1.2.0",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-testing-library": "^5.9.0",
|
||||
"husky": "^8.0.2",
|
||||
"jsdom": "^20.0.1",
|
||||
"jsdom": "^21.0.0",
|
||||
"lodash": "^4.17.0",
|
||||
"moment": "^2.29",
|
||||
"prettier": "^2.7.0",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-organize-imports": "^3.1.0",
|
||||
"pretty-quick": "^3.1.0",
|
||||
"react-table": "^7.8.0",
|
||||
"recharts": "~2.1.0",
|
||||
"sass": "^1.55.0",
|
||||
"typescript": "^4",
|
||||
"vite": "^3.2.1",
|
||||
"vite-plugin-checker": "^0.5.5",
|
||||
"vitest": "^0.25.0"
|
||||
"recharts": "~2.5.0",
|
||||
"sass": "^1.62.0",
|
||||
"typescript": "^5",
|
||||
"vite": "^4.3.0",
|
||||
"vite-plugin-checker": "^0.5.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
|
|
|
@ -15,12 +15,12 @@ import {
|
|||
Avatar,
|
||||
Badge,
|
||||
Burger,
|
||||
createStyles,
|
||||
Divider,
|
||||
Group,
|
||||
Header,
|
||||
MediaQuery,
|
||||
Menu,
|
||||
createStyles,
|
||||
} from "@mantine/core";
|
||||
import { FunctionComponent } from "react";
|
||||
|
||||
|
|
|
@ -357,9 +357,11 @@ const NavbarItem: FunctionComponent<NavbarItemProps> = ({
|
|||
></FontAwesomeIcon>
|
||||
)}
|
||||
{name}
|
||||
<Badge className={classes.badge} radius="xs" hidden={shouldHideBadge}>
|
||||
{badge}
|
||||
</Badge>
|
||||
{shouldHideBadge === false && (
|
||||
<Badge className={classes.badge} radius="xs">
|
||||
{badge}
|
||||
</Badge>
|
||||
)}
|
||||
</Text>
|
||||
</NavLink>
|
||||
);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import AppNavbar from "@/App/Navbar";
|
||||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import ErrorBoundary from "@/components/ErrorBoundary";
|
||||
import { Layout } from "@/constants";
|
||||
import NavbarProvider from "@/contexts/Navbar";
|
||||
import OnlineProvider from "@/contexts/Online";
|
||||
import { notification } from "@/modules/task";
|
||||
import CriticalError from "@/pages/errors/CriticalError";
|
||||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import { Environment } from "@/utilities";
|
||||
import { AppShell } from "@mantine/core";
|
||||
import { useWindowEvent } from "@mantine/hooks";
|
||||
|
|
|
@ -6,7 +6,13 @@ import {
|
|||
MantineThemeOverride,
|
||||
} from "@mantine/core";
|
||||
import { useColorScheme } from "@mantine/hooks";
|
||||
import { FunctionComponent, useCallback, useEffect, useState } from "react";
|
||||
import {
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
const theme: MantineThemeOverride = {
|
||||
fontFamily: "Roboto, open sans, Helvetica Neue, Helvetica, Arial, sans-serif",
|
||||
|
@ -45,7 +51,7 @@ function useAutoColorScheme() {
|
|||
|
||||
const emotionCache = createEmotionCache({ key: "bazarr" });
|
||||
|
||||
const ThemeProvider: FunctionComponent = ({ children }) => {
|
||||
const ThemeProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
const { colorScheme, toggleColorScheme } = useAutoColorScheme();
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import App from "@/App";
|
||||
import { useBadges } from "@/apis/hooks";
|
||||
import { useEnabledStatus } from "@/apis/hooks/site";
|
||||
import App from "@/App";
|
||||
import { Lazy } from "@/components/async";
|
||||
import Authentication from "@/pages/Authentication";
|
||||
import BlacklistMoviesView from "@/pages/Blacklist/Movies";
|
||||
import BlacklistSeriesView from "@/pages/Blacklist/Series";
|
||||
import Episodes from "@/pages/Episodes";
|
||||
import NotFound from "@/pages/errors/NotFound";
|
||||
import MoviesHistoryView from "@/pages/History/Movies";
|
||||
import SeriesHistoryView from "@/pages/History/Series";
|
||||
import MovieView from "@/pages/Movies";
|
||||
|
@ -31,6 +30,7 @@ import SystemReleasesView from "@/pages/System/Releases";
|
|||
import SystemTasksView from "@/pages/System/Tasks";
|
||||
import WantedMoviesView from "@/pages/Wanted/Movies";
|
||||
import WantedSeriesView from "@/pages/Wanted/Series";
|
||||
import NotFound from "@/pages/errors/NotFound";
|
||||
import { Environment } from "@/utilities";
|
||||
import {
|
||||
faClock,
|
||||
|
@ -42,13 +42,13 @@ import {
|
|||
faPlay,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import {
|
||||
createContext,
|
||||
FunctionComponent,
|
||||
createContext,
|
||||
lazy,
|
||||
useContext,
|
||||
useMemo,
|
||||
} from "react";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||
import Redirector from "./Redirector";
|
||||
import { RouterNames } from "./RouterNames";
|
||||
import { CustomRouteObject } from "./type";
|
||||
|
@ -315,12 +315,18 @@ function useRoutes(): CustomRouteObject[] {
|
|||
|
||||
const RouterItemContext = createContext<CustomRouteObject[]>([]);
|
||||
|
||||
export const Router: FunctionComponent = ({ children }) => {
|
||||
export const Router: FunctionComponent = () => {
|
||||
const routes = useRoutes();
|
||||
|
||||
// TODO: Move this outside the function component scope
|
||||
const router = useMemo(
|
||||
() => createBrowserRouter(routes, { basename: Environment.baseUrl }),
|
||||
[routes]
|
||||
);
|
||||
|
||||
return (
|
||||
<RouterItemContext.Provider value={routes}>
|
||||
<BrowserRouter basename={Environment.baseUrl}>{children}</BrowserRouter>
|
||||
<RouterProvider router={router}></RouterProvider>
|
||||
</RouterItemContext.Provider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,9 +3,9 @@ import { usePageSize } from "@/utilities/storage";
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import {
|
||||
QueryKey,
|
||||
UseQueryResult,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
UseQueryResult,
|
||||
} from "react-query";
|
||||
import { QueryKeys } from "./keys";
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import UIError from "@/pages/errors/UIError";
|
||||
import { Component } from "react";
|
||||
import { Component, PropsWithChildren } from "react";
|
||||
|
||||
interface State {
|
||||
error: Error | null;
|
||||
}
|
||||
|
||||
class ErrorBoundary extends Component<object, State> {
|
||||
class ErrorBoundary extends Component<PropsWithChildren, State> {
|
||||
constructor(props: object) {
|
||||
super(props);
|
||||
this.state = { error: null };
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { LoadingOverlay } from "@mantine/core";
|
||||
import { FunctionComponent, Suspense } from "react";
|
||||
import { FunctionComponent, PropsWithChildren, Suspense } from "react";
|
||||
|
||||
const Lazy: FunctionComponent = ({ children }) => {
|
||||
const Lazy: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
return <Suspense fallback={<LoadingOverlay visible />}>{children}</Suspense>;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useMovieSubtitleModification } from "@/apis/hooks";
|
||||
import { useModals, withModal } from "@/modules/modals";
|
||||
import { task, TaskGroup } from "@/modules/task";
|
||||
import { TaskGroup, task } from "@/modules/task";
|
||||
import { useTableStyles } from "@/styles";
|
||||
import { useArrayAction, useSelectorOptions } from "@/utilities";
|
||||
import FormUtils from "@/utilities/form";
|
||||
|
@ -28,9 +28,9 @@ import { useForm } from "@mantine/form";
|
|||
import { isString } from "lodash";
|
||||
import { FunctionComponent, useEffect, useMemo } from "react";
|
||||
import { Column } from "react-table";
|
||||
import TextPopover from "../TextPopover";
|
||||
import { Action, Selector } from "../inputs";
|
||||
import { SimpleTable } from "../tables";
|
||||
import TextPopover from "../TextPopover";
|
||||
|
||||
type SubtitleFile = {
|
||||
file: File;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export * from "./inputs";
|
||||
export { default as Search } from "./Search";
|
||||
export * from "./inputs";
|
||||
export * from "./tables";
|
||||
export { default as Toolbox } from "./toolbox";
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
faXmark,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { createStyles, Group, Stack, Text } from "@mantine/core";
|
||||
import { Group, Stack, Text, createStyles } from "@mantine/core";
|
||||
import { Dropzone } from "@mantine/dropzone";
|
||||
import { FunctionComponent } from "react";
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ import { Badge, Center, Text } from "@mantine/core";
|
|||
import { FunctionComponent, useMemo } from "react";
|
||||
import { Column } from "react-table";
|
||||
import { PageTable } from "..";
|
||||
import TextPopover from "../TextPopover";
|
||||
import MutateAction from "../async/MutateAction";
|
||||
import QueryOverlay from "../async/QueryOverlay";
|
||||
import { HistoryIcon } from "../bazarr";
|
||||
import Language from "../bazarr/Language";
|
||||
import TextPopover from "../TextPopover";
|
||||
|
||||
interface MovieHistoryViewProps {
|
||||
movie: Item.Movie;
|
||||
|
|
|
@ -105,7 +105,7 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
|
|||
</Anchor>
|
||||
);
|
||||
} else {
|
||||
return value;
|
||||
return <Text>{value}</Text>;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -4,7 +4,7 @@ import { SimpleTable } from "@/components/tables";
|
|||
import { useCustomSelection } from "@/components/tables/plugins";
|
||||
import { withModal } from "@/modules/modals";
|
||||
import { isMovie } from "@/utilities";
|
||||
import { Badge, Button, Divider, Group, Stack } from "@mantine/core";
|
||||
import { Badge, Button, Divider, Group, Stack, Text } from "@mantine/core";
|
||||
import { FunctionComponent, useMemo, useState } from "react";
|
||||
import { Column, useRowSelect } from "react-table";
|
||||
|
||||
|
@ -60,9 +60,9 @@ const SubtitleToolView: FunctionComponent<SubtitleToolViewProps> = ({
|
|||
}
|
||||
|
||||
if (idx !== -1) {
|
||||
return path.slice(idx + 1);
|
||||
return <Text>{path.slice(idx + 1)}</Text>;
|
||||
} else {
|
||||
return path;
|
||||
return <Text>{path}</Text>;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -30,7 +30,7 @@ const PageControl: FunctionComponent<Props> = ({
|
|||
<Pagination
|
||||
size="sm"
|
||||
color={isLoading ? "gray" : "primary"}
|
||||
page={index + 1}
|
||||
value={index + 1}
|
||||
onChange={(page) => goto(page - 1)}
|
||||
hidden={count <= 1}
|
||||
total={count}
|
||||
|
|
|
@ -3,8 +3,8 @@ import { useEffect } from "react";
|
|||
import { usePagination, useTable } from "react-table";
|
||||
import BaseTable from "./BaseTable";
|
||||
import PageControl from "./PageControl";
|
||||
import { useDefaultSettings } from "./plugins";
|
||||
import { SimpleTableProps } from "./SimpleTable";
|
||||
import { useDefaultSettings } from "./plugins";
|
||||
|
||||
type Props<T extends object> = SimpleTableProps<T> & {
|
||||
autoScroll?: boolean;
|
||||
|
|
|
@ -4,12 +4,12 @@ import {
|
|||
CellProps,
|
||||
Column,
|
||||
ColumnInstance,
|
||||
ensurePluginOrder,
|
||||
HeaderProps,
|
||||
Hooks,
|
||||
MetaBase,
|
||||
TableInstance,
|
||||
TableToggleCommonProps,
|
||||
ensurePluginOrder,
|
||||
} from "react-table";
|
||||
|
||||
const pluginName = "useCustomSelection";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { createStyles, Group } from "@mantine/core";
|
||||
import { FunctionComponent } from "react";
|
||||
import { FunctionComponent, PropsWithChildren } from "react";
|
||||
import ToolboxButton, { ToolboxMutateButton } from "./Button";
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
|
@ -11,7 +11,7 @@ const useStyles = createStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
declare type ToolboxComp = FunctionComponent & {
|
||||
declare type ToolboxComp = FunctionComponent<PropsWithChildren> & {
|
||||
Button: typeof ToolboxButton;
|
||||
MutateButton: typeof ToolboxMutateButton;
|
||||
};
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import { StrictMode } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { useRoutes } from "react-router-dom";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Router } from "./Router";
|
||||
import { AllProviders } from "./providers";
|
||||
import { useRouteItems } from "./Router";
|
||||
|
||||
const RouteApp = () => {
|
||||
const items = useRouteItems();
|
||||
const container = document.getElementById("root");
|
||||
|
||||
return useRoutes(items);
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<StrictMode>
|
||||
<AllProviders>
|
||||
<RouteApp />
|
||||
</AllProviders>
|
||||
</StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
if (container === null) {
|
||||
Error("Cannot initialize app, root not found");
|
||||
} else {
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<AllProviders>
|
||||
<Router />
|
||||
</AllProviders>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,19 +2,19 @@ import {
|
|||
ModalsProvider as MantineModalsProvider,
|
||||
ModalsProviderProps as MantineModalsProviderProps,
|
||||
} from "@mantine/modals";
|
||||
import { FunctionComponent, useMemo } from "react";
|
||||
import { FunctionComponent, PropsWithChildren, useMemo } from "react";
|
||||
import { ModalComponent, StaticModals } from "./WithModal";
|
||||
|
||||
const DefaultModalProps: MantineModalsProviderProps["modalProps"] = {
|
||||
centered: true,
|
||||
styles: {
|
||||
modal: {
|
||||
maxWidth: "100%",
|
||||
},
|
||||
// modals: {
|
||||
// maxWidth: "100%",
|
||||
// },
|
||||
},
|
||||
};
|
||||
|
||||
const ModalsProvider: FunctionComponent = ({ children }) => {
|
||||
const ModalsProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
const modals = useMemo(
|
||||
() =>
|
||||
StaticModals.reduce<Record<string, ModalComponent>>((prev, curr) => {
|
||||
|
|
|
@ -5,8 +5,11 @@ import { useCallback, useContext, useMemo } from "react";
|
|||
import { ModalComponent, ModalIdContext } from "./WithModal";
|
||||
|
||||
export function useModals() {
|
||||
const { openContextModal: openMantineContextModal, ...rest } =
|
||||
useMantineModals();
|
||||
const {
|
||||
openContextModal: openMantineContextModal,
|
||||
closeContextModal: closeContextModalRaw,
|
||||
...rest
|
||||
} = useMantineModals();
|
||||
|
||||
const openContextModal = useCallback(
|
||||
<ARGS extends {}>(
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export * from "./hooks";
|
||||
export { default as ModalsProvider } from "./ModalsProvider";
|
||||
export { default as withModal } from "./WithModal";
|
||||
export * from "./hooks";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { debounce, forIn, remove, uniq } from "lodash";
|
||||
import { onlineManager } from "react-query";
|
||||
import { io, Socket } from "socket.io-client";
|
||||
import { Socket, io } from "socket.io-client";
|
||||
import { Environment, isDevEnv, isTestEnv } from "../../utilities";
|
||||
import { ENSURE, GROUP, LOG } from "../../utilities/console";
|
||||
import { createDefaultReducer } from "./reducer";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import {
|
||||
useEpisodesBySeriesId,
|
||||
useIsAnyActionRunning,
|
||||
|
@ -11,9 +12,8 @@ import { ItemEditModal } from "@/components/forms/ItemEditForm";
|
|||
import { SeriesUploadModal } from "@/components/forms/SeriesUploadForm";
|
||||
import { SubtitleToolsModal } from "@/components/modals";
|
||||
import { useModals } from "@/modules/modals";
|
||||
import { notification, task, TaskGroup } from "@/modules/task";
|
||||
import { TaskGroup, notification, task } from "@/modules/task";
|
||||
import ItemOverview from "@/pages/views/ItemOverview";
|
||||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import { useLanguageProfileBy } from "@/utilities/languages";
|
||||
import {
|
||||
faAdjust,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useDownloadEpisodeSubtitles, useEpisodesProvider } from "@/apis/hooks";
|
||||
import { useShowOnlyDesired } from "@/apis/hooks/site";
|
||||
import { Action, GroupTable } from "@/components";
|
||||
import TextPopover from "@/components/TextPopover";
|
||||
import { AudioList } from "@/components/bazarr";
|
||||
import { EpisodeHistoryModal } from "@/components/modals";
|
||||
import { EpisodeSearchModal } from "@/components/modals/ManualSearchModal";
|
||||
import TextPopover from "@/components/TextPopover";
|
||||
import { useModals } from "@/modules/modals";
|
||||
import { useTableStyles } from "@/styles";
|
||||
import { BuildKey, filterSubtitleBy } from "@/utilities";
|
||||
|
@ -84,7 +84,7 @@ const Table: FunctionComponent<Props> = ({ episodes, profile, disabled }) => {
|
|||
{
|
||||
accessor: "season",
|
||||
Cell: (row) => {
|
||||
return `Season ${row.value}`;
|
||||
return <Text>Season {row.value}</Text>;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -11,8 +11,8 @@ import { useSelectorOptions } from "@/utilities";
|
|||
import {
|
||||
Box,
|
||||
Container,
|
||||
createStyles,
|
||||
SimpleGrid,
|
||||
createStyles,
|
||||
useMantineTheme,
|
||||
} from "@mantine/core";
|
||||
import { useDocumentTitle } from "@mantine/hooks";
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import {
|
||||
useDownloadMovieSubtitles,
|
||||
useIsMovieActionRunning,
|
||||
|
@ -15,9 +16,8 @@ import { MovieUploadModal } from "@/components/forms/MovieUploadForm";
|
|||
import { MovieHistoryModal, SubtitleToolsModal } from "@/components/modals";
|
||||
import { MovieSearchModal } from "@/components/modals/ManualSearchModal";
|
||||
import { useModals } from "@/modules/modals";
|
||||
import { notification, task, TaskGroup } from "@/modules/task";
|
||||
import { TaskGroup, notification, task } from "@/modules/task";
|
||||
import ItemOverview from "@/pages/views/ItemOverview";
|
||||
import { RouterNames } from "@/Router/RouterNames";
|
||||
import { useLanguageProfileBy } from "@/utilities/languages";
|
||||
import {
|
||||
faCloudUploadAlt,
|
||||
|
|
|
@ -65,15 +65,19 @@ const MovieView: FunctionComponent = () => {
|
|||
accessor: "missing_subtitles",
|
||||
Cell: (row) => {
|
||||
const missing = row.value;
|
||||
return missing.map((v) => (
|
||||
<Badge
|
||||
mr="xs"
|
||||
color="yellow"
|
||||
key={BuildKey(v.code2, v.hi, v.forced)}
|
||||
>
|
||||
<Language.Text value={v}></Language.Text>
|
||||
</Badge>
|
||||
));
|
||||
return (
|
||||
<>
|
||||
{missing.map((v) => (
|
||||
<Badge
|
||||
mr="xs"
|
||||
color="yellow"
|
||||
key={BuildKey(v.code2, v.hi, v.forced)}
|
||||
>
|
||||
<Language.Text value={v}></Language.Text>
|
||||
</Badge>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Action, SimpleTable } from "@/components";
|
||||
import {
|
||||
anyCutoff,
|
||||
ProfileEditModal,
|
||||
anyCutoff,
|
||||
} from "@/components/forms/ProfileEditForm";
|
||||
import { useModals } from "@/modules/modals";
|
||||
import { BuildKey, useArrayAction } from "@/utilities";
|
||||
|
@ -87,15 +87,19 @@ const Table: FunctionComponent = () => {
|
|||
Cell: (row) => {
|
||||
const items = row.value;
|
||||
if (!items) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return items.map((v, idx) => {
|
||||
return (
|
||||
<Badge key={BuildKey(idx, v)} color="gray">
|
||||
{v}
|
||||
</Badge>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<>
|
||||
{items.map((v, idx) => {
|
||||
return (
|
||||
<Badge key={BuildKey(idx, v)} color="gray">
|
||||
{v}
|
||||
</Badge>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -104,15 +108,19 @@ const Table: FunctionComponent = () => {
|
|||
Cell: (row) => {
|
||||
const items = row.value;
|
||||
if (!items) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return items.map((v, idx) => {
|
||||
return (
|
||||
<Badge key={BuildKey(idx, v)} color="gray">
|
||||
{v}
|
||||
</Badge>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<>
|
||||
{items.map((v, idx) => {
|
||||
return (
|
||||
<Badge key={BuildKey(idx, v)} color="gray">
|
||||
{v}
|
||||
</Badge>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -6,15 +6,15 @@ import {
|
|||
Button,
|
||||
Divider,
|
||||
Group,
|
||||
Text as MantineText,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text as MantineText,
|
||||
} from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { capitalize } from "lodash";
|
||||
import {
|
||||
forwardRef,
|
||||
FunctionComponent,
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useRef,
|
||||
|
@ -28,8 +28,8 @@ import {
|
|||
useFormActions,
|
||||
useStagedValues,
|
||||
} from "../utilities/FormValues";
|
||||
import { useSettingValue } from "../utilities/hooks";
|
||||
import { SettingsProvider, useSettings } from "../utilities/SettingsProvider";
|
||||
import { useSettingValue } from "../utilities/hooks";
|
||||
import { ProviderInfo, ProviderList } from "./list";
|
||||
|
||||
const ProviderKey = "settings-general-enabled_providers";
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
import { Text } from "@mantine/core";
|
||||
import { FunctionComponent } from "react";
|
||||
import { FunctionComponent, PropsWithChildren } from "react";
|
||||
|
||||
export const Message: FunctionComponent<{
|
||||
interface MessageProps {
|
||||
type?: "warning" | "info";
|
||||
}> = ({ type = "info", children }) => {
|
||||
}
|
||||
|
||||
type Props = PropsWithChildren<MessageProps>;
|
||||
|
||||
export const Message: FunctionComponent<Props> = ({
|
||||
type = "info",
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<Text size="sm" color={type === "info" ? "dimmed" : "yellow"} my={0}>
|
||||
{children}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { Divider, Stack, Title } from "@mantine/core";
|
||||
import { FunctionComponent } from "react";
|
||||
import { FunctionComponent, PropsWithChildren } from "react";
|
||||
|
||||
interface SectionProps {
|
||||
header: string;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
export const Section: FunctionComponent<SectionProps> = ({
|
||||
type Props = PropsWithChildren<SectionProps>;
|
||||
|
||||
export const Section: FunctionComponent<Props> = ({
|
||||
header,
|
||||
hidden,
|
||||
children,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Collapse, Stack } from "@mantine/core";
|
||||
import { FunctionComponent, useMemo, useRef } from "react";
|
||||
import { FunctionComponent, PropsWithChildren, useMemo, useRef } from "react";
|
||||
import { useSettingValue } from "../utilities/hooks";
|
||||
|
||||
interface ContentProps {
|
||||
|
@ -8,7 +8,9 @@ interface ContentProps {
|
|||
indent?: boolean;
|
||||
}
|
||||
|
||||
const CollapseBox: FunctionComponent<ContentProps> = ({
|
||||
type Props = PropsWithChildren<ContentProps>;
|
||||
|
||||
const CollapseBox: FunctionComponent<Props> = ({
|
||||
on,
|
||||
indent,
|
||||
children,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { rawRender, RenderOptions, screen } from "@/tests";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { FunctionComponent, ReactElement } from "react";
|
||||
import { FunctionComponent, PropsWithChildren, ReactElement } from "react";
|
||||
import { describe, it } from "vitest";
|
||||
import { FormContext, FormValues } from "../utilities/FormValues";
|
||||
import { Number, Text } from "./forms";
|
||||
|
||||
const FormSupport: FunctionComponent = ({ children }) => {
|
||||
const FormSupport: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
const form = useForm<FormValues>({
|
||||
initialValues: {
|
||||
settings: {},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
Action as GlobalAction,
|
||||
FileBrowser,
|
||||
FileBrowserProps,
|
||||
Action as GlobalAction,
|
||||
MultiSelector as GlobalMultiSelector,
|
||||
MultiSelectorProps as GlobalMultiSelectorProps,
|
||||
Selector as GlobalSelector,
|
||||
|
@ -12,17 +12,17 @@ import ChipInput, { ChipInputProps } from "@/components/inputs/ChipInput";
|
|||
import { useSliderMarks } from "@/utilities";
|
||||
import {
|
||||
Input,
|
||||
Slider as MantineSlider,
|
||||
SliderProps as MantineSliderProps,
|
||||
NumberInput,
|
||||
NumberInputProps,
|
||||
PasswordInput,
|
||||
PasswordInputProps,
|
||||
Slider as MantineSlider,
|
||||
SliderProps as MantineSliderProps,
|
||||
Switch,
|
||||
TextInput,
|
||||
TextInputProps,
|
||||
} from "@mantine/core";
|
||||
import { FunctionComponent, ReactText } from "react";
|
||||
import { FunctionComponent, ReactNode, ReactText } from "react";
|
||||
import { BaseInput, useBaseInput } from "../utilities/hooks";
|
||||
|
||||
export type NumberProps = BaseInput<number> & NumberInputProps;
|
||||
|
@ -34,7 +34,10 @@ export const Number: FunctionComponent<NumberProps> = (props) => {
|
|||
<NumberInput
|
||||
{...rest}
|
||||
value={value ?? 0}
|
||||
onChange={(val = 0) => {
|
||||
onChange={(val) => {
|
||||
if (val === "") {
|
||||
val = 0;
|
||||
}
|
||||
update(val);
|
||||
}}
|
||||
></NumberInput>
|
||||
|
@ -126,7 +129,9 @@ export function MultiSelector<T extends string | number>(
|
|||
}
|
||||
|
||||
type SliderProps = BaseInput<number> &
|
||||
Omit<MantineSliderProps, "onChange" | "onChangeEnd" | "marks">;
|
||||
Omit<MantineSliderProps, "onChange" | "onChangeEnd" | "marks" | "label"> & {
|
||||
label?: ReactNode;
|
||||
};
|
||||
|
||||
export const Slider: FunctionComponent<SliderProps> = (props) => {
|
||||
const { value, update, rest } = useBaseInput(props);
|
||||
|
|
|
@ -63,11 +63,11 @@ export const URLTestButton: FunctionComponent<{
|
|||
};
|
||||
|
||||
export * from "./Card";
|
||||
export * from "./collapse";
|
||||
export { default as CollapseBox } from "./collapse";
|
||||
export * from "./forms";
|
||||
export * from "./Layout";
|
||||
export { default as Layout } from "./Layout";
|
||||
export * from "./Message";
|
||||
export * from "./pathMapper";
|
||||
export * from "./Section";
|
||||
export * from "./collapse";
|
||||
export { default as CollapseBox } from "./collapse";
|
||||
export * from "./forms";
|
||||
export * from "./pathMapper";
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { createContext, FunctionComponent, useContext } from "react";
|
||||
import {
|
||||
createContext,
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
useContext,
|
||||
} from "react";
|
||||
|
||||
const SettingsContext = createContext<Settings | null>(null);
|
||||
|
||||
|
@ -12,7 +17,9 @@ type SettingsProviderProps = {
|
|||
value: Settings | null;
|
||||
};
|
||||
|
||||
export const SettingsProvider: FunctionComponent<SettingsProviderProps> = ({
|
||||
type Props = PropsWithChildren<SettingsProviderProps>;
|
||||
|
||||
export const SettingsProvider: FunctionComponent<Props> = ({
|
||||
value,
|
||||
children,
|
||||
}) => {
|
||||
|
|
|
@ -13,7 +13,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|||
import { Anchor, Container, Divider, Grid, Stack, Text } from "@mantine/core";
|
||||
import { useDocumentTitle } from "@mantine/hooks";
|
||||
import moment from "moment";
|
||||
import { FunctionComponent, ReactNode, useCallback, useState } from "react";
|
||||
import {
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useState,
|
||||
} from "react";
|
||||
import Table from "./table";
|
||||
|
||||
interface InfoProps {
|
||||
|
@ -53,10 +59,13 @@ function Label(props: IconProps): JSX.Element {
|
|||
);
|
||||
}
|
||||
|
||||
const InfoContainer: FunctionComponent<{ title: string }> = ({
|
||||
title,
|
||||
children,
|
||||
}) => {
|
||||
interface InfoContainerProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const InfoContainer: FunctionComponent<
|
||||
PropsWithChildren<InfoContainerProps>
|
||||
> = ({ title, children }) => {
|
||||
return (
|
||||
<Stack>
|
||||
<h4>{title}</h4>
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
useMovieWantedPagination,
|
||||
} from "@/apis/hooks";
|
||||
import Language from "@/components/bazarr/Language";
|
||||
import { task, TaskGroup } from "@/modules/task";
|
||||
import { TaskGroup, task } from "@/modules/task";
|
||||
import WantedView from "@/pages/views/WantedView";
|
||||
import { BuildKey } from "@/utilities";
|
||||
import { faSearch } from "@fortawesome/free-solid-svg-icons";
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
useSeriesAction,
|
||||
} from "@/apis/hooks";
|
||||
import Language from "@/components/bazarr/Language";
|
||||
import { task, TaskGroup } from "@/modules/task";
|
||||
import { TaskGroup, task } from "@/modules/task";
|
||||
import WantedView from "@/pages/views/WantedView";
|
||||
import { useTableStyles } from "@/styles";
|
||||
import { BuildKey } from "@/utilities";
|
||||
|
|
|
@ -5,17 +5,17 @@ import {
|
|||
useProfileItemsToLanguages,
|
||||
} from "@/utilities/languages";
|
||||
import {
|
||||
faBookmark as farBookmark,
|
||||
faFolder,
|
||||
faBookmark as farBookmark,
|
||||
} from "@fortawesome/free-regular-svg-icons";
|
||||
import {
|
||||
IconDefinition,
|
||||
faBookmark,
|
||||
faClone,
|
||||
faLanguage,
|
||||
faMusic,
|
||||
faStream,
|
||||
faTags,
|
||||
IconDefinition,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
|
@ -23,7 +23,6 @@ import {
|
|||
Badge,
|
||||
BadgeProps,
|
||||
Box,
|
||||
createStyles,
|
||||
Grid,
|
||||
Group,
|
||||
HoverCard,
|
||||
|
@ -33,6 +32,7 @@ import {
|
|||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
createStyles,
|
||||
} from "@mantine/core";
|
||||
import { FunctionComponent, useMemo } from "react";
|
||||
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
import queryClient from "@/apis/queries";
|
||||
import ThemeProvider from "@/App/theme";
|
||||
import queryClient from "@/apis/queries";
|
||||
import { ModalsProvider } from "@/modules/modals";
|
||||
import "@fontsource/roboto/300.css";
|
||||
import { NotificationsProvider } from "@mantine/notifications";
|
||||
import { FunctionComponent } from "react";
|
||||
import { Notifications } from "@mantine/notifications";
|
||||
import { FunctionComponent, PropsWithChildren } from "react";
|
||||
import { QueryClientProvider } from "react-query";
|
||||
import { ReactQueryDevtools } from "react-query/devtools";
|
||||
import { Router } from "./Router";
|
||||
import { Environment } from "./utilities";
|
||||
|
||||
export const AllProviders: FunctionComponent = ({ children }) => {
|
||||
export const AllProviders: FunctionComponent<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<ThemeProvider>
|
||||
<ModalsProvider>
|
||||
<NotificationsProvider limit={5}>
|
||||
<Router>
|
||||
{/* c8 ignore next 3 */}
|
||||
{Environment.queryDev && (
|
||||
<ReactQueryDevtools initialIsOpen={false} />
|
||||
)}
|
||||
{children}
|
||||
</Router>
|
||||
</NotificationsProvider>
|
||||
<Notifications limit={5} />
|
||||
{/* c8 ignore next 3 */}
|
||||
{Environment.queryDev && <ReactQueryDevtools initialIsOpen={false} />}
|
||||
{children}
|
||||
</ModalsProvider>
|
||||
</ThemeProvider>
|
||||
</QueryClientProvider>
|
||||
|
|
|
@ -1,11 +1,33 @@
|
|||
import { AllProviders } from "@/providers";
|
||||
import { render, RenderOptions } from "@testing-library/react";
|
||||
import { FunctionComponent, ReactElement, StrictMode } from "react";
|
||||
import {
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
ReactElement,
|
||||
StrictMode,
|
||||
} from "react";
|
||||
import {
|
||||
createBrowserRouter,
|
||||
RouteObject,
|
||||
RouterProvider,
|
||||
} from "react-router-dom";
|
||||
|
||||
const AllProvidersWithStrictMode: FunctionComponent<PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const route: RouteObject = {
|
||||
path: "/",
|
||||
element: children,
|
||||
};
|
||||
|
||||
// TODO: Update router system
|
||||
const router = createBrowserRouter([route]);
|
||||
|
||||
const AllProvidersWithStrictMode: FunctionComponent = ({ children }) => {
|
||||
return (
|
||||
<StrictMode>
|
||||
<AllProviders>{children}</AllProviders>
|
||||
<AllProviders>
|
||||
<RouterProvider router={router} />
|
||||
</AllProviders>
|
||||
</StrictMode>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,41 +1,9 @@
|
|||
// A workaround of built-in hooks in React-Router v6
|
||||
// https://gist.github.com/rmorse/426ffcc579922a82749934826fa9f743
|
||||
|
||||
import type { Blocker, History, Transition } from "history";
|
||||
import { useContext, useEffect } from "react";
|
||||
// eslint-disable-next-line camelcase
|
||||
import { UNSAFE_NavigationContext } from "react-router-dom";
|
||||
|
||||
export function useBlocker(blocker: Blocker, when = true) {
|
||||
const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
|
||||
|
||||
useEffect(() => {
|
||||
if (!when) return;
|
||||
|
||||
const unblock = navigator.block((tx: Transition) => {
|
||||
const autoUnblockingTx = {
|
||||
...tx,
|
||||
retry() {
|
||||
// Automatically unblock the transition so it can play all the way
|
||||
// through before retrying it. TODO: Figure out how to re-enable
|
||||
// this block if the transition is cancelled for some reason.
|
||||
unblock();
|
||||
tx.retry();
|
||||
},
|
||||
};
|
||||
|
||||
blocker(autoUnblockingTx);
|
||||
});
|
||||
|
||||
return unblock;
|
||||
}, [navigator, blocker, when]);
|
||||
}
|
||||
import { unstable_usePrompt as useUnstablePrompt } from "react-router-dom";
|
||||
|
||||
// TODO: Replace with Mantine's confirmation modal
|
||||
export function usePrompt(when: boolean, message: string) {
|
||||
useBlocker((tx) => {
|
||||
if (window.confirm(message)) {
|
||||
tx.retry();
|
||||
}
|
||||
}, when);
|
||||
useUnstablePrompt({ when, message });
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue