From be8f2d6d183e5206f932be1113e0da7db2a2277a Mon Sep 17 00:00:00 2001 From: Anderson Shindy Oki Date: Fri, 7 Jun 2024 12:00:42 +0900 Subject: Upgraded mantine to v7.x --- frontend/src/pages/System/Status/index.tsx | 9 ++++++--- frontend/src/pages/System/Status/table.tsx | 7 ++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'frontend/src/pages/System/Status') diff --git a/frontend/src/pages/System/Status/index.tsx b/frontend/src/pages/System/Status/index.tsx index 49c88ccd4..05996f7ad 100644 --- a/frontend/src/pages/System/Status/index.tsx +++ b/frontend/src/pages/System/Status/index.tsx @@ -46,7 +46,7 @@ function Row(props: InfoProps): JSX.Element { return ( - + {title} @@ -85,9 +85,12 @@ const InfoContainer: FunctionComponent< return ( + {title} + + } > {children} diff --git a/frontend/src/pages/System/Status/table.tsx b/frontend/src/pages/System/Status/table.tsx index 3b8a87e8a..c139f9d93 100644 --- a/frontend/src/pages/System/Status/table.tsx +++ b/frontend/src/pages/System/Status/table.tsx @@ -1,5 +1,4 @@ import { SimpleTable } from "@/components"; -import { useTableStyles } from "@/styles"; import { Text } from "@mantine/core"; import { FunctionComponent, useMemo } from "react"; import { Column } from "react-table"; @@ -15,16 +14,14 @@ const Table: FunctionComponent = ({ health }) => { Header: "Object", accessor: "object", Cell: ({ value }) => { - const { classes } = useTableStyles(); - return {value}; + return {value}; }, }, { Header: "Issue", accessor: "issue", Cell: ({ value }) => { - const { classes } = useTableStyles(); - return {value}; + return {value}; }, }, ], -- cgit v1.2.3 From bcd8257fda44678e53e184eea8ab3a97709e1d02 Mon Sep 17 00:00:00 2001 From: Anderson Shindy Oki Date: Sat, 8 Jun 2024 09:49:40 +0900 Subject: no log: Apply style linter (#2516) --- frontend/.eslintrc.json | 48 ++++++++++++++++++++- frontend/package-lock.json | 11 +++++ frontend/package.json | 2 + frontend/src/App/Header.tsx | 24 +++++------ frontend/src/App/Navbar.tsx | 44 +++++++++---------- frontend/src/App/ThemeProvider.tsx | 4 +- frontend/src/App/app.test.tsx | 2 +- frontend/src/App/index.tsx | 12 +++--- frontend/src/Router/Redirector.tsx | 4 +- frontend/src/Router/index.tsx | 38 ++++++++-------- frontend/src/Router/type.d.ts | 2 +- frontend/src/apis/hooks/episodes.ts | 6 +-- frontend/src/apis/hooks/histories.ts | 4 +- frontend/src/apis/hooks/languages.ts | 4 +- frontend/src/apis/hooks/movies.ts | 6 +-- frontend/src/apis/hooks/providers.ts | 4 +- frontend/src/apis/hooks/series.ts | 6 +-- frontend/src/apis/hooks/status.ts | 2 +- frontend/src/apis/hooks/subtitles.ts | 4 +- frontend/src/apis/hooks/system.ts | 8 ++-- frontend/src/apis/queries/hooks.ts | 6 +-- frontend/src/apis/raw/client.ts | 6 +-- frontend/src/components/ErrorBoundary.tsx | 2 +- frontend/src/components/Search.tsx | 12 +++--- frontend/src/components/StateIcon.tsx | 8 ++-- frontend/src/components/SubtitleToolsMenu.tsx | 20 ++++----- frontend/src/components/TextPopover.tsx | 2 +- frontend/src/components/async/Lazy.tsx | 2 +- frontend/src/components/async/MutateAction.tsx | 4 +- frontend/src/components/async/MutateButton.tsx | 2 +- frontend/src/components/async/QueryOverlay.tsx | 4 +- frontend/src/components/bazarr/AudioList.tsx | 4 +- frontend/src/components/bazarr/HistoryIcon.tsx | 4 +- frontend/src/components/bazarr/Language.test.tsx | 2 +- frontend/src/components/bazarr/Language.tsx | 4 +- frontend/src/components/bazarr/LanguageProfile.tsx | 2 +- .../src/components/bazarr/LanguageSelector.tsx | 2 +- frontend/src/components/forms/ColorToolForm.tsx | 6 +-- frontend/src/components/forms/FrameRateForm.tsx | 6 +-- frontend/src/components/forms/ItemEditForm.tsx | 8 ++-- frontend/src/components/forms/MovieUploadForm.tsx | 44 +++++++++---------- frontend/src/components/forms/ProfileEditForm.tsx | 18 ++++---- frontend/src/components/forms/SeriesUploadForm.tsx | 46 ++++++++++---------- frontend/src/components/forms/SyncSubtitleForm.tsx | 13 +++--- frontend/src/components/forms/TimeOffsetForm.tsx | 10 ++--- frontend/src/components/forms/TranslationForm.tsx | 10 ++--- frontend/src/components/inputs/Action.test.tsx | 2 +- frontend/src/components/inputs/Action.tsx | 12 +++--- frontend/src/components/inputs/ChipInput.test.tsx | 2 +- frontend/src/components/inputs/DropContent.tsx | 6 +-- frontend/src/components/inputs/FileBrowser.tsx | 8 ++-- frontend/src/components/inputs/Selector.test.tsx | 2 +- frontend/src/components/inputs/Selector.tsx | 4 +- frontend/src/components/modals/HistoryModal.tsx | 22 +++++----- .../src/components/modals/ManualSearchModal.tsx | 30 ++++++------- .../src/components/modals/SubtitleToolsModal.tsx | 6 +-- frontend/src/components/tables/BaseTable.tsx | 6 +-- frontend/src/components/tables/GroupTable.tsx | 6 +-- frontend/src/components/tables/PageControl.tsx | 4 +- frontend/src/components/tables/PageTable.tsx | 6 +-- frontend/src/components/tables/QueryPageTable.tsx | 2 +- .../tables/plugins/useCustomSelection.tsx | 4 +- .../tables/plugins/useDefaultSettings.tsx | 2 +- frontend/src/components/toolbox/Button.tsx | 6 +-- frontend/src/components/toolbox/Toolbox.tsx | 2 +- frontend/src/dom.tsx | 2 +- frontend/src/modules/modals/ModalsProvider.tsx | 2 +- frontend/src/modules/modals/WithModal.tsx | 2 +- frontend/src/modules/modals/hooks.ts | 2 +- frontend/src/modules/socketio/hooks.ts | 2 +- frontend/src/modules/socketio/index.ts | 8 ++-- frontend/src/modules/socketio/reducer.ts | 4 +- frontend/src/modules/task/index.ts | 2 +- frontend/src/pages/Authentication.test.tsx | 2 +- frontend/src/pages/Authentication.tsx | 6 +-- frontend/src/pages/Blacklist/Movies/index.tsx | 8 ++-- frontend/src/pages/Blacklist/Movies/table.tsx | 10 ++--- frontend/src/pages/Blacklist/Series/index.tsx | 8 ++-- frontend/src/pages/Blacklist/Series/table.tsx | 10 ++--- frontend/src/pages/Episodes/components.tsx | 4 +- frontend/src/pages/Episodes/index.tsx | 50 +++++++++++----------- frontend/src/pages/Episodes/table.tsx | 34 +++++++-------- frontend/src/pages/History/Movies/index.tsx | 20 ++++----- frontend/src/pages/History/Series/index.tsx | 20 ++++----- .../src/pages/History/Statistics/HistoryStats.tsx | 18 ++++---- frontend/src/pages/History/history.test.tsx | 2 +- frontend/src/pages/Movies/Details/index.tsx | 40 ++++++++--------- frontend/src/pages/Movies/Details/table.tsx | 10 ++--- frontend/src/pages/Movies/Editor.tsx | 6 +-- frontend/src/pages/Movies/index.tsx | 16 +++---- frontend/src/pages/Movies/movies.test.tsx | 4 +- frontend/src/pages/Series/Editor.tsx | 6 +-- frontend/src/pages/Series/index.tsx | 16 +++---- frontend/src/pages/Series/series.test.tsx | 4 +- frontend/src/pages/Settings/General/index.tsx | 10 ++--- .../src/pages/Settings/Languages/components.tsx | 11 +++-- .../src/pages/Settings/Languages/equals.test.ts | 2 +- frontend/src/pages/Settings/Languages/equals.tsx | 10 ++--- frontend/src/pages/Settings/Languages/index.tsx | 10 ++--- frontend/src/pages/Settings/Languages/table.tsx | 16 +++---- .../pages/Settings/Notifications/components.tsx | 25 ++++++----- .../src/pages/Settings/Notifications/index.tsx | 4 +- .../src/pages/Settings/Providers/components.tsx | 39 +++++++++-------- frontend/src/pages/Settings/Providers/index.tsx | 6 +-- frontend/src/pages/Settings/Providers/list.ts | 2 +- frontend/src/pages/Settings/Radarr/index.tsx | 6 +-- frontend/src/pages/Settings/Scheduler/index.tsx | 4 +- frontend/src/pages/Settings/Sonarr/index.tsx | 8 ++-- frontend/src/pages/Settings/Subtitles/index.tsx | 6 +-- frontend/src/pages/Settings/Subtitles/options.ts | 2 +- frontend/src/pages/Settings/UI/index.tsx | 4 +- frontend/src/pages/Settings/components/Card.tsx | 4 +- .../src/pages/Settings/components/Layout.test.tsx | 2 +- frontend/src/pages/Settings/components/Layout.tsx | 18 +++++--- .../src/pages/Settings/components/LayoutModal.tsx | 18 +++++--- frontend/src/pages/Settings/components/Message.tsx | 2 +- .../src/pages/Settings/components/Section.test.tsx | 2 +- frontend/src/pages/Settings/components/Section.tsx | 2 +- .../src/pages/Settings/components/collapse.tsx | 4 +- .../src/pages/Settings/components/forms.test.tsx | 6 +-- frontend/src/pages/Settings/components/forms.tsx | 30 ++++++------- frontend/src/pages/Settings/components/index.tsx | 6 +-- .../src/pages/Settings/components/pathMapper.tsx | 16 +++---- .../src/pages/Settings/utilities/FormValues.ts | 4 +- frontend/src/pages/Settings/utilities/hooks.ts | 8 ++-- frontend/src/pages/System/Announcements/index.tsx | 6 +-- frontend/src/pages/System/Announcements/table.tsx | 8 ++-- frontend/src/pages/System/Backups/index.tsx | 8 ++-- frontend/src/pages/System/Backups/table.tsx | 8 ++-- frontend/src/pages/System/Logs/index.tsx | 18 ++++---- frontend/src/pages/System/Logs/modal.tsx | 4 +- frontend/src/pages/System/Logs/table.tsx | 8 ++-- frontend/src/pages/System/Providers/index.tsx | 8 ++-- frontend/src/pages/System/Providers/table.tsx | 2 +- frontend/src/pages/System/Releases/index.tsx | 8 ++-- frontend/src/pages/System/Status/index.tsx | 34 +++++++-------- frontend/src/pages/System/Status/table.tsx | 4 +- frontend/src/pages/System/Tasks/index.tsx | 8 ++-- frontend/src/pages/System/Tasks/table.tsx | 8 ++-- frontend/src/pages/Wanted/Movies/index.tsx | 14 +++--- frontend/src/pages/Wanted/Series/index.tsx | 14 +++--- frontend/src/pages/errors/CriticalError.tsx | 6 +-- frontend/src/pages/errors/NotFound.tsx | 4 +- frontend/src/pages/errors/UIError.tsx | 10 ++--- frontend/src/pages/views/HistoryView.tsx | 6 +-- frontend/src/pages/views/ItemOverview.tsx | 42 +++++++++--------- frontend/src/pages/views/ItemView.tsx | 6 +-- frontend/src/pages/views/MassEditor.tsx | 14 +++--- frontend/src/pages/views/WantedView.tsx | 8 ++-- frontend/src/providers.tsx | 10 ++--- frontend/src/tests/index.tsx | 4 +- frontend/src/tests/setup.ts | 2 +- frontend/src/types/react-table.d.ts | 2 +- frontend/src/utilities/hooks.ts | 4 +- frontend/src/utilities/index.ts | 2 +- frontend/src/utilities/languages.ts | 2 +- frontend/src/utilities/storage.ts | 2 +- frontend/src/utilities/validate.ts | 2 +- 158 files changed, 787 insertions(+), 718 deletions(-) (limited to 'frontend/src/pages/System/Status') diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 65e129bc9..97b3d3de5 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -2,6 +2,13 @@ "rules": { "no-console": "error", "camelcase": "warn", + "no-restricted-imports": [ + "error", + { + "patterns": ["..*"] + } + ], + "simple-import-sort/imports": "error", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-empty-function": "warn", "@typescript-eslint/no-empty-interface": "off", @@ -13,7 +20,7 @@ "eslint:recommended", "plugin:@typescript-eslint/recommended" ], - "plugins": ["testing-library"], + "plugins": ["testing-library", "simple-import-sort"], "overrides": [ { "files": [ @@ -21,6 +28,43 @@ "**/?(*.)+(spec|test).[jt]s?(x)" ], "extends": ["plugin:testing-library/react"] + }, + { + "files": ["*.ts", "*.tsx"], + "rules": { + "simple-import-sort/imports": [ + "error", + { + "groups": [ + [ + // React Packages + "^react", + // Mantine Packages + "^@mantine/", + // Vendor Packages + "^(\\w|@\\w)", + // Side Effect Imports + "^\\u0000", + // Internal Packages + "^@/\\w", + // Parent Imports + "^\\.\\.(?!/?$)", + "^\\.\\./?$", + // Relative Imports + "^\\./(?=.*/)(?!/?$)", + "^\\.(?!/?$)", + "^\\./?$", + // Style Imports + "^.+\\.?(css)$" + ] + ] + } + ] + } } - ] + ], + "parserOptions": { + "sourceType": "module", + "ecmaVersion": "latest" + } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f19cbab4d..463a35b79 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -45,6 +45,7 @@ "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^12.1.0", "eslint-plugin-testing-library": "^6.2.0", "husky": "^9.0.11", "jsdom": "^24.0.0", @@ -6101,6 +6102,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.0.tgz", + "integrity": "sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, "node_modules/eslint-plugin-testing-library": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 971065e4d..ad297a715 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -49,6 +49,7 @@ "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^12.1.0", "eslint-plugin-testing-library": "^6.2.0", "husky": "^9.0.11", "jsdom": "^24.0.0", @@ -72,6 +73,7 @@ "build": "vite build", "build:ci": "vite build -m development", "check": "eslint --ext .ts,.tsx src", + "check:fix": "eslint --ext .ts,.tsx src --fix", "check:ts": "tsc --noEmit --incremental false", "check:fmt": "prettier -c .", "test": "vitest", diff --git a/frontend/src/App/Header.tsx b/frontend/src/App/Header.tsx index 6bb47f5b1..9919da9d6 100644 --- a/frontend/src/App/Header.tsx +++ b/frontend/src/App/Header.tsx @@ -1,14 +1,4 @@ -import { useSystem, useSystemSettings } from "@/apis/hooks"; -import { Action, Search } from "@/components"; -import { useNavbar } from "@/contexts/Navbar"; -import { useIsOnline } from "@/contexts/Online"; -import { Environment, useGotoHomepage } from "@/utilities"; -import { - faArrowRotateLeft, - faGear, - faPowerOff, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent } from "react"; import { Anchor, AppShell, @@ -19,7 +9,17 @@ import { Group, Menu, } from "@mantine/core"; -import { FunctionComponent } from "react"; +import { + faArrowRotateLeft, + faGear, + faPowerOff, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useSystem, useSystemSettings } from "@/apis/hooks"; +import { Action, Search } from "@/components"; +import { useNavbar } from "@/contexts/Navbar"; +import { useIsOnline } from "@/contexts/Online"; +import { Environment, useGotoHomepage } from "@/utilities"; import styles from "./Header.module.scss"; const AppHeader: FunctionComponent = () => { diff --git a/frontend/src/App/Navbar.tsx b/frontend/src/App/Navbar.tsx index 8254f2fc0..3b5ce1881 100644 --- a/frontend/src/App/Navbar.tsx +++ b/frontend/src/App/Navbar.tsx @@ -1,16 +1,12 @@ -import { Action } from "@/components"; -import { useNavbar } from "@/contexts/Navbar"; -import { useRouteItems } from "@/Router"; -import { CustomRouteObject, Route } from "@/Router/type"; -import { BuildKey, pathJoin } from "@/utilities"; -import { LOG } from "@/utilities/console"; -import { - faHeart, - faMoon, - faSun, - IconDefinition, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { + createContext, + FunctionComponent, + useContext, + useEffect, + useMemo, + useState, +} from "react"; +import { matchPath, NavLink, RouteObject, useLocation } from "react-router-dom"; import { Anchor, AppShell, @@ -24,16 +20,20 @@ import { useMantineColorScheme, } from "@mantine/core"; import { useHover } from "@mantine/hooks"; +import { + faHeart, + faMoon, + faSun, + IconDefinition, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import clsx from "clsx"; -import React, { - createContext, - FunctionComponent, - useContext, - useEffect, - useMemo, - useState, -} from "react"; -import { matchPath, NavLink, RouteObject, useLocation } from "react-router-dom"; +import { Action } from "@/components"; +import { useNavbar } from "@/contexts/Navbar"; +import { useRouteItems } from "@/Router"; +import { CustomRouteObject, Route } from "@/Router/type"; +import { BuildKey, pathJoin } from "@/utilities"; +import { LOG } from "@/utilities/console"; import styles from "./Navbar.module.scss"; const Selection = createContext<{ diff --git a/frontend/src/App/ThemeProvider.tsx b/frontend/src/App/ThemeProvider.tsx index d3a39cdb0..c67046ce9 100644 --- a/frontend/src/App/ThemeProvider.tsx +++ b/frontend/src/App/ThemeProvider.tsx @@ -1,3 +1,4 @@ +import { FunctionComponent, PropsWithChildren } from "react"; import { ActionIcon, AppShell, @@ -6,15 +7,14 @@ import { createTheme, MantineProvider, } from "@mantine/core"; -import { FunctionComponent, PropsWithChildren } from "react"; import ThemeLoader from "@/App/ThemeLoader"; import "@mantine/core/styles.layer.css"; import "@mantine/notifications/styles.layer.css"; import styleVars from "@/assets/_variables.module.scss"; -import buttonClasses from "@/assets/button.module.scss"; import actionIconClasses from "@/assets/action_icon.module.scss"; import appShellClasses from "@/assets/app_shell.module.scss"; import badgeClasses from "@/assets/badge.module.scss"; +import buttonClasses from "@/assets/button.module.scss"; const themeProvider = createTheme({ fontFamily: "Roboto, open sans, Helvetica Neue, Helvetica, Arial, sans-serif", diff --git a/frontend/src/App/app.test.tsx b/frontend/src/App/app.test.tsx index f6236cdc9..db9895305 100644 --- a/frontend/src/App/app.test.tsx +++ b/frontend/src/App/app.test.tsx @@ -1,5 +1,5 @@ -import { render } from "@/tests"; import { describe, it } from "vitest"; +import { render } from "@/tests"; import App from "."; describe("App", () => { diff --git a/frontend/src/App/index.tsx b/frontend/src/App/index.tsx index 1b27734f4..a8ef9f3fb 100644 --- a/frontend/src/App/index.tsx +++ b/frontend/src/App/index.tsx @@ -1,16 +1,16 @@ +import { FunctionComponent, useEffect, useState } from "react"; +import { Outlet, useNavigate } from "react-router-dom"; +import { AppShell } from "@mantine/core"; +import { useWindowEvent } from "@mantine/hooks"; +import { showNotification } from "@mantine/notifications"; import AppNavbar from "@/App/Navbar"; -import { RouterNames } from "@/Router/RouterNames"; import ErrorBoundary from "@/components/ErrorBoundary"; 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"; -import { showNotification } from "@mantine/notifications"; -import { FunctionComponent, useEffect, useState } from "react"; -import { Outlet, useNavigate } from "react-router-dom"; import AppHeader from "./Header"; import styleVars from "@/assets/_variables.module.scss"; diff --git a/frontend/src/Router/Redirector.tsx b/frontend/src/Router/Redirector.tsx index 064522bbc..07878c9db 100644 --- a/frontend/src/Router/Redirector.tsx +++ b/frontend/src/Router/Redirector.tsx @@ -1,7 +1,7 @@ -import { useSystemSettings } from "@/apis/hooks"; -import { LoadingOverlay } from "@mantine/core"; import { FunctionComponent, useEffect } from "react"; import { useNavigate } from "react-router-dom"; +import { LoadingOverlay } from "@mantine/core"; +import { useSystemSettings } from "@/apis/hooks"; const Redirector: FunctionComponent = () => { const { data } = useSystemSettings(); diff --git a/frontend/src/Router/index.tsx b/frontend/src/Router/index.tsx index efed2edb2..d600fc87d 100644 --- a/frontend/src/Router/index.tsx +++ b/frontend/src/Router/index.tsx @@ -1,11 +1,29 @@ -import App from "@/App"; +import { + createContext, + FunctionComponent, + lazy, + useContext, + useMemo, +} from "react"; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { + faClock, + faCogs, + faExclamationTriangle, + faFileExcel, + faFilm, + faLaptop, + faPlay, +} from "@fortawesome/free-solid-svg-icons"; 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"; @@ -30,25 +48,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, - faCogs, - faExclamationTriangle, - faFileExcel, - faFilm, - faLaptop, - faPlay, -} from "@fortawesome/free-solid-svg-icons"; -import { - FunctionComponent, - createContext, - lazy, - useContext, - useMemo, -} from "react"; -import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Redirector from "./Redirector"; import { RouterNames } from "./RouterNames"; import { CustomRouteObject } from "./type"; diff --git a/frontend/src/Router/type.d.ts b/frontend/src/Router/type.d.ts index 0276a30dd..f1cfdaae7 100644 --- a/frontend/src/Router/type.d.ts +++ b/frontend/src/Router/type.d.ts @@ -1,5 +1,5 @@ -import { IconDefinition } from "@fortawesome/free-solid-svg-icons"; import { RouteObject } from "react-router-dom"; +import { IconDefinition } from "@fortawesome/free-solid-svg-icons"; declare namespace Route { export type Item = { diff --git a/frontend/src/apis/hooks/episodes.ts b/frontend/src/apis/hooks/episodes.ts index d182dc7e6..ae721333a 100644 --- a/frontend/src/apis/hooks/episodes.ts +++ b/frontend/src/apis/hooks/episodes.ts @@ -4,9 +4,9 @@ import { useQuery, useQueryClient, } from "react-query"; -import { usePaginationQuery } from "../queries/hooks"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { usePaginationQuery } from "@/apis/queries/hooks"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; const cacheEpisodes = (client: QueryClient, episodes: Item.Episode[]) => { episodes.forEach((item) => { diff --git a/frontend/src/apis/hooks/histories.ts b/frontend/src/apis/hooks/histories.ts index d8fc0676f..7e3c188e0 100644 --- a/frontend/src/apis/hooks/histories.ts +++ b/frontend/src/apis/hooks/histories.ts @@ -1,6 +1,6 @@ import { useQuery } from "react-query"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; export function useHistoryStats( time: History.TimeFrameOptions, diff --git a/frontend/src/apis/hooks/languages.ts b/frontend/src/apis/hooks/languages.ts index 149d80716..1a639ab15 100644 --- a/frontend/src/apis/hooks/languages.ts +++ b/frontend/src/apis/hooks/languages.ts @@ -1,6 +1,6 @@ import { useQuery } from "react-query"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; export function useLanguages(history?: boolean) { return useQuery( diff --git a/frontend/src/apis/hooks/movies.ts b/frontend/src/apis/hooks/movies.ts index ee8fe1100..344f2db04 100644 --- a/frontend/src/apis/hooks/movies.ts +++ b/frontend/src/apis/hooks/movies.ts @@ -4,9 +4,9 @@ import { useQuery, useQueryClient, } from "react-query"; -import { usePaginationQuery } from "../queries/hooks"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { usePaginationQuery } from "@/apis/queries/hooks"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; const cacheMovies = (client: QueryClient, movies: Item.Movie[]) => { movies.forEach((item) => { diff --git a/frontend/src/apis/hooks/providers.ts b/frontend/src/apis/hooks/providers.ts index 5e4fed602..a96d9ba3c 100644 --- a/frontend/src/apis/hooks/providers.ts +++ b/frontend/src/apis/hooks/providers.ts @@ -1,6 +1,6 @@ import { useMutation, useQuery, useQueryClient } from "react-query"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; export function useSystemProviders(history?: boolean) { return useQuery( diff --git a/frontend/src/apis/hooks/series.ts b/frontend/src/apis/hooks/series.ts index 1e395a6e5..d27773973 100644 --- a/frontend/src/apis/hooks/series.ts +++ b/frontend/src/apis/hooks/series.ts @@ -4,9 +4,9 @@ import { useQuery, useQueryClient, } from "react-query"; -import { usePaginationQuery } from "../queries/hooks"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { usePaginationQuery } from "@/apis/queries/hooks"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; function cacheSeries(client: QueryClient, series: Item.Series[]) { series.forEach((item) => { diff --git a/frontend/src/apis/hooks/status.ts b/frontend/src/apis/hooks/status.ts index 46a73cfda..c5e7c3501 100644 --- a/frontend/src/apis/hooks/status.ts +++ b/frontend/src/apis/hooks/status.ts @@ -1,5 +1,5 @@ import { useIsMutating } from "react-query"; -import { QueryKeys } from "../queries/keys"; +import { QueryKeys } from "@/apis/queries/keys"; export function useIsAnyActionRunning() { return useIsMutating([QueryKeys.Actions]) > 0; diff --git a/frontend/src/apis/hooks/subtitles.ts b/frontend/src/apis/hooks/subtitles.ts index 7864cdcbb..8ea572a00 100644 --- a/frontend/src/apis/hooks/subtitles.ts +++ b/frontend/src/apis/hooks/subtitles.ts @@ -1,6 +1,6 @@ import { useMutation, useQuery, useQueryClient } from "react-query"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; export function useSubtitleAction() { const client = useQueryClient(); diff --git a/frontend/src/apis/hooks/system.ts b/frontend/src/apis/hooks/system.ts index 26946e910..8b877a977 100644 --- a/frontend/src/apis/hooks/system.ts +++ b/frontend/src/apis/hooks/system.ts @@ -1,9 +1,9 @@ -import { Environment } from "@/utilities"; -import { setAuthenticated } from "@/utilities/event"; import { useMemo } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; -import { QueryKeys } from "../queries/keys"; -import api from "../raw"; +import { QueryKeys } from "@/apis/queries/keys"; +import api from "@/apis/raw"; +import { Environment } from "@/utilities"; +import { setAuthenticated } from "@/utilities/event"; export function useBadges() { return useQuery( diff --git a/frontend/src/apis/queries/hooks.ts b/frontend/src/apis/queries/hooks.ts index 5f9bf63d3..e2e53fdf6 100644 --- a/frontend/src/apis/queries/hooks.ts +++ b/frontend/src/apis/queries/hooks.ts @@ -1,12 +1,12 @@ -import { GetItemId, useOnValueChange } from "@/utilities"; -import { usePageSize } from "@/utilities/storage"; import { useCallback, useEffect, useState } from "react"; import { QueryKey, - UseQueryResult, useQuery, useQueryClient, + UseQueryResult, } from "react-query"; +import { GetItemId, useOnValueChange } from "@/utilities"; +import { usePageSize } from "@/utilities/storage"; import { QueryKeys } from "./keys"; export type UsePaginationQueryResult = UseQueryResult< diff --git a/frontend/src/apis/raw/client.ts b/frontend/src/apis/raw/client.ts index d77b81205..f3c2f53a3 100644 --- a/frontend/src/apis/raw/client.ts +++ b/frontend/src/apis/raw/client.ts @@ -1,10 +1,10 @@ +import { showNotification } from "@mantine/notifications"; +import Axios, { AxiosError, AxiosInstance, CancelTokenSource } from "axios"; import socketio from "@/modules/socketio"; import { notification } from "@/modules/task"; +import { Environment } from "@/utilities"; import { LOG } from "@/utilities/console"; import { setAuthenticated } from "@/utilities/event"; -import { showNotification } from "@mantine/notifications"; -import Axios, { AxiosError, AxiosInstance, CancelTokenSource } from "axios"; -import { Environment } from "../../utilities"; function GetErrorMessage(data: unknown, defaultMsg = "Unknown error"): string { if (typeof data === "string") { diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx index a29200e47..4e39dd9dc 100644 --- a/frontend/src/components/ErrorBoundary.tsx +++ b/frontend/src/components/ErrorBoundary.tsx @@ -1,5 +1,5 @@ -import UIError from "@/pages/errors/UIError"; import { Component, PropsWithChildren } from "react"; +import UIError from "@/pages/errors/UIError"; interface State { error: Error | null; diff --git a/frontend/src/components/Search.tsx b/frontend/src/components/Search.tsx index 75341e0a8..03e0b94e8 100644 --- a/frontend/src/components/Search.tsx +++ b/frontend/src/components/Search.tsx @@ -1,15 +1,15 @@ -import { useServerSearch } from "@/apis/hooks"; -import { useDebouncedValue } from "@/utilities"; -import { faSearch } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent, useMemo, useState } from "react"; +import { Link } from "react-router-dom"; import { Anchor, Autocomplete, ComboboxItem, OptionsFilter, } from "@mantine/core"; -import { FunctionComponent, useMemo, useState } from "react"; -import { Link } from "react-router-dom"; +import { faSearch } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useServerSearch } from "@/apis/hooks"; +import { useDebouncedValue } from "@/utilities"; import styles from "./Search.module.scss"; type SearchResultItem = { diff --git a/frontend/src/components/StateIcon.tsx b/frontend/src/components/StateIcon.tsx index 73700a679..31e0b5243 100644 --- a/frontend/src/components/StateIcon.tsx +++ b/frontend/src/components/StateIcon.tsx @@ -1,4 +1,6 @@ -import { BuildKey } from "@/utilities"; +import { FunctionComponent } from "react"; +import { Group, List, Popover, Stack, Text } from "@mantine/core"; +import { useHover } from "@mantine/hooks"; import { faCheck, faCheckCircle, @@ -7,9 +9,7 @@ import { faTimes, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Group, List, Popover, Stack, Text } from "@mantine/core"; -import { useHover } from "@mantine/hooks"; -import { FunctionComponent } from "react"; +import { BuildKey } from "@/utilities"; interface StateIconProps { matches: string[]; diff --git a/frontend/src/components/SubtitleToolsMenu.tsx b/frontend/src/components/SubtitleToolsMenu.tsx index bdadb5cb4..ce7770e16 100644 --- a/frontend/src/components/SubtitleToolsMenu.tsx +++ b/frontend/src/components/SubtitleToolsMenu.tsx @@ -1,11 +1,5 @@ -import { useSubtitleAction } from "@/apis/hooks"; -import { ColorToolModal } from "@/components/forms/ColorToolForm"; -import { FrameRateModal } from "@/components/forms/FrameRateForm"; -import { TimeOffsetModal } from "@/components/forms/TimeOffsetForm"; -import { TranslationModal } from "@/components/forms/TranslationForm"; -import { useModals } from "@/modules/modals"; -import { ModalComponent } from "@/modules/modals/WithModal"; -import { task } from "@/modules/task"; +import { FunctionComponent, ReactElement, useCallback, useMemo } from "react"; +import { Divider, List, Menu, MenuProps, ScrollArea } from "@mantine/core"; import { faClock, faCode, @@ -23,8 +17,14 @@ import { IconDefinition, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Divider, List, Menu, MenuProps, ScrollArea } from "@mantine/core"; -import { FunctionComponent, ReactElement, useCallback, useMemo } from "react"; +import { useSubtitleAction } from "@/apis/hooks"; +import { ColorToolModal } from "@/components/forms/ColorToolForm"; +import { FrameRateModal } from "@/components/forms/FrameRateForm"; +import { TimeOffsetModal } from "@/components/forms/TimeOffsetForm"; +import { TranslationModal } from "@/components/forms/TranslationForm"; +import { useModals } from "@/modules/modals"; +import { ModalComponent } from "@/modules/modals/WithModal"; +import { task } from "@/modules/task"; import { SyncSubtitleModal } from "./forms/SyncSubtitleForm"; export interface ToolOptions { diff --git a/frontend/src/components/TextPopover.tsx b/frontend/src/components/TextPopover.tsx index 8fda5913e..b72654109 100644 --- a/frontend/src/components/TextPopover.tsx +++ b/frontend/src/components/TextPopover.tsx @@ -1,7 +1,7 @@ +import { FunctionComponent, ReactElement } from "react"; import { Tooltip, TooltipProps } from "@mantine/core"; import { useHover } from "@mantine/hooks"; import { isNull, isUndefined } from "lodash"; -import { FunctionComponent, ReactElement } from "react"; interface TextPopoverProps { children: ReactElement; diff --git a/frontend/src/components/async/Lazy.tsx b/frontend/src/components/async/Lazy.tsx index 2a0496223..317c0feb3 100644 --- a/frontend/src/components/async/Lazy.tsx +++ b/frontend/src/components/async/Lazy.tsx @@ -1,5 +1,5 @@ -import { LoadingOverlay } from "@mantine/core"; import { FunctionComponent, PropsWithChildren, Suspense } from "react"; +import { LoadingOverlay } from "@mantine/core"; const Lazy: FunctionComponent = ({ children }) => { return }>{children}; diff --git a/frontend/src/components/async/MutateAction.tsx b/frontend/src/components/async/MutateAction.tsx index 920fe4ff3..9a5837c02 100644 --- a/frontend/src/components/async/MutateAction.tsx +++ b/frontend/src/components/async/MutateAction.tsx @@ -1,7 +1,7 @@ import { useCallback, useState } from "react"; import { UseMutationResult } from "react-query"; -import { Action } from "../inputs"; -import { ActionProps } from "../inputs/Action"; +import { Action } from "@/components/inputs"; +import { ActionProps } from "@/components/inputs/Action"; type MutateActionProps = Omit< ActionProps, diff --git a/frontend/src/components/async/MutateButton.tsx b/frontend/src/components/async/MutateButton.tsx index 8d0f68541..5de836278 100644 --- a/frontend/src/components/async/MutateButton.tsx +++ b/frontend/src/components/async/MutateButton.tsx @@ -1,6 +1,6 @@ -import { Button, ButtonProps } from "@mantine/core"; import { useCallback, useState } from "react"; import { UseMutationResult } from "react-query"; +import { Button, ButtonProps } from "@mantine/core"; type MutateButtonProps = Omit< ButtonProps, diff --git a/frontend/src/components/async/QueryOverlay.tsx b/frontend/src/components/async/QueryOverlay.tsx index 24b95ab18..f6d0d6572 100644 --- a/frontend/src/components/async/QueryOverlay.tsx +++ b/frontend/src/components/async/QueryOverlay.tsx @@ -1,7 +1,7 @@ -import { LoadingProvider } from "@/contexts"; -import { LoadingOverlay } from "@mantine/core"; import { FunctionComponent, ReactNode } from "react"; import { UseQueryResult } from "react-query"; +import { LoadingOverlay } from "@mantine/core"; +import { LoadingProvider } from "@/contexts"; interface QueryOverlayProps { result: UseQueryResult; diff --git a/frontend/src/components/bazarr/AudioList.tsx b/frontend/src/components/bazarr/AudioList.tsx index b73f71331..f1af7ff3c 100644 --- a/frontend/src/components/bazarr/AudioList.tsx +++ b/frontend/src/components/bazarr/AudioList.tsx @@ -1,6 +1,6 @@ -import { BuildKey } from "@/utilities"; -import { Badge, BadgeProps, Group, GroupProps } from "@mantine/core"; import { FunctionComponent } from "react"; +import { Badge, BadgeProps, Group, GroupProps } from "@mantine/core"; +import { BuildKey } from "@/utilities"; export type AudioListProps = GroupProps & { audios: Language.Info[]; diff --git a/frontend/src/components/bazarr/HistoryIcon.tsx b/frontend/src/components/bazarr/HistoryIcon.tsx index e6c0f2411..add0cd1fd 100644 --- a/frontend/src/components/bazarr/HistoryIcon.tsx +++ b/frontend/src/components/bazarr/HistoryIcon.tsx @@ -1,3 +1,5 @@ +import { FunctionComponent } from "react"; +import { Tooltip } from "@mantine/core"; import { faClock, faClosedCaptioning, @@ -9,8 +11,6 @@ import { faUser, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Tooltip } from "@mantine/core"; -import { FunctionComponent } from "react"; enum HistoryAction { Delete = 0, diff --git a/frontend/src/components/bazarr/Language.test.tsx b/frontend/src/components/bazarr/Language.test.tsx index e4e3b42b8..2cad5d4c8 100644 --- a/frontend/src/components/bazarr/Language.test.tsx +++ b/frontend/src/components/bazarr/Language.test.tsx @@ -1,5 +1,5 @@ -import { render, screen } from "@/tests"; import { describe, it } from "vitest"; +import { render, screen } from "@/tests"; import { Language } from "."; describe("Language text", () => { diff --git a/frontend/src/components/bazarr/Language.tsx b/frontend/src/components/bazarr/Language.tsx index ba1a884e6..6315d9102 100644 --- a/frontend/src/components/bazarr/Language.tsx +++ b/frontend/src/components/bazarr/Language.tsx @@ -1,6 +1,6 @@ -import { BuildKey } from "@/utilities"; -import { Badge, Group, Text, TextProps } from "@mantine/core"; import { FunctionComponent, useMemo } from "react"; +import { Badge, Group, Text, TextProps } from "@mantine/core"; +import { BuildKey } from "@/utilities"; type LanguageTextProps = TextProps & { value: Language.Info; diff --git a/frontend/src/components/bazarr/LanguageProfile.tsx b/frontend/src/components/bazarr/LanguageProfile.tsx index 75b7b73ca..a234268c3 100644 --- a/frontend/src/components/bazarr/LanguageProfile.tsx +++ b/frontend/src/components/bazarr/LanguageProfile.tsx @@ -1,5 +1,5 @@ -import { useLanguageProfiles } from "@/apis/hooks"; import { FunctionComponent, useMemo } from "react"; +import { useLanguageProfiles } from "@/apis/hooks"; interface Props { index: number | null; diff --git a/frontend/src/components/bazarr/LanguageSelector.tsx b/frontend/src/components/bazarr/LanguageSelector.tsx index c2219ca7c..8954403bd 100644 --- a/frontend/src/components/bazarr/LanguageSelector.tsx +++ b/frontend/src/components/bazarr/LanguageSelector.tsx @@ -1,7 +1,7 @@ +import { FunctionComponent, useMemo } from "react"; import { useLanguages } from "@/apis/hooks"; import { Selector, SelectorProps } from "@/components/inputs"; import { useSelectorOptions } from "@/utilities"; -import { FunctionComponent, useMemo } from "react"; interface LanguageSelectorProps extends Omit, "options" | "getkey"> { diff --git a/frontend/src/components/forms/ColorToolForm.tsx b/frontend/src/components/forms/ColorToolForm.tsx index a37819bee..9deac9bf4 100644 --- a/frontend/src/components/forms/ColorToolForm.tsx +++ b/frontend/src/components/forms/ColorToolForm.tsx @@ -1,11 +1,11 @@ +import { FunctionComponent } from "react"; +import { Button, Divider, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; import { useSubtitleAction } from "@/apis/hooks"; import { Selector, SelectorOption } from "@/components"; import { useModals, withModal } from "@/modules/modals"; import { task } from "@/modules/task"; import FormUtils from "@/utilities/form"; -import { Button, Divider, Stack } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { FunctionComponent } from "react"; const TaskName = "Changing Color"; diff --git a/frontend/src/components/forms/FrameRateForm.tsx b/frontend/src/components/forms/FrameRateForm.tsx index aa1723183..7c57daf28 100644 --- a/frontend/src/components/forms/FrameRateForm.tsx +++ b/frontend/src/components/forms/FrameRateForm.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent } from "react"; +import { Button, Divider, Group, NumberInput, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; import { useSubtitleAction } from "@/apis/hooks"; import { useModals, withModal } from "@/modules/modals"; import { task } from "@/modules/task"; import FormUtils from "@/utilities/form"; -import { Button, Divider, Group, NumberInput, Stack } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { FunctionComponent } from "react"; const TaskName = "Changing Frame Rate"; diff --git a/frontend/src/components/forms/ItemEditForm.tsx b/frontend/src/components/forms/ItemEditForm.tsx index 64f87fb36..a3d03f4c8 100644 --- a/frontend/src/components/forms/ItemEditForm.tsx +++ b/frontend/src/components/forms/ItemEditForm.tsx @@ -1,11 +1,11 @@ +import { FunctionComponent, useMemo } from "react"; +import { UseMutationResult } from "react-query"; +import { Button, Divider, Group, LoadingOverlay, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; import { useLanguageProfiles } from "@/apis/hooks"; import { MultiSelector, Selector } from "@/components/inputs"; import { useModals, withModal } from "@/modules/modals"; import { GetItemId, useSelectorOptions } from "@/utilities"; -import { Button, Divider, Group, LoadingOverlay, Stack } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { FunctionComponent, useMemo } from "react"; -import { UseMutationResult } from "react-query"; interface Props { mutation: UseMutationResult; diff --git a/frontend/src/components/forms/MovieUploadForm.tsx b/frontend/src/components/forms/MovieUploadForm.tsx index 1d6c64fe7..5a5a47f06 100644 --- a/frontend/src/components/forms/MovieUploadForm.tsx +++ b/frontend/src/components/forms/MovieUploadForm.tsx @@ -1,20 +1,5 @@ -import { useMovieSubtitleModification } from "@/apis/hooks"; -import { useModals, withModal } from "@/modules/modals"; -import { TaskGroup, task } from "@/modules/task"; -import { useArrayAction, useSelectorOptions } from "@/utilities"; -import FormUtils from "@/utilities/form"; -import { - useLanguageProfileBy, - useProfileItemsToLanguages, -} from "@/utilities/languages"; -import { - faCheck, - faCircleNotch, - faInfoCircle, - faTimes, - faTrash, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent, useEffect, useMemo } from "react"; +import { Column } from "react-table"; import { Button, Checkbox, @@ -24,12 +9,27 @@ import { Text, } from "@mantine/core"; import { useForm } from "@mantine/form"; +import { + faCheck, + faCircleNotch, + faInfoCircle, + faTimes, + faTrash, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 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 { useMovieSubtitleModification } from "@/apis/hooks"; +import { Action, Selector } from "@/components/inputs"; +import { SimpleTable } from "@/components/tables"; +import TextPopover from "@/components/TextPopover"; +import { useModals, withModal } from "@/modules/modals"; +import { task, TaskGroup } from "@/modules/task"; +import { useArrayAction, useSelectorOptions } from "@/utilities"; +import FormUtils from "@/utilities/form"; +import { + useLanguageProfileBy, + useProfileItemsToLanguages, +} from "@/utilities/languages"; type SubtitleFile = { file: File; diff --git a/frontend/src/components/forms/ProfileEditForm.tsx b/frontend/src/components/forms/ProfileEditForm.tsx index 93f09d8b8..c1104b223 100644 --- a/frontend/src/components/forms/ProfileEditForm.tsx +++ b/frontend/src/components/forms/ProfileEditForm.tsx @@ -1,9 +1,5 @@ -import { Action, Selector, SelectorOption, SimpleTable } from "@/components"; -import { useModals, withModal } from "@/modules/modals"; -import { useArrayAction, useSelectorOptions } from "@/utilities"; -import { LOG } from "@/utilities/console"; -import FormUtils from "@/utilities/form"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; +import { FunctionComponent, useCallback, useMemo } from "react"; +import { Column } from "react-table"; import { Accordion, Button, @@ -15,9 +11,13 @@ import { TextInput, } from "@mantine/core"; import { useForm } from "@mantine/form"; -import { FunctionComponent, useCallback, useMemo } from "react"; -import { Column } from "react-table"; -import ChipInput from "../inputs/ChipInput"; +import { faTrash } from "@fortawesome/free-solid-svg-icons"; +import { Action, Selector, SelectorOption, SimpleTable } from "@/components"; +import ChipInput from "@/components/inputs/ChipInput"; +import { useModals, withModal } from "@/modules/modals"; +import { useArrayAction, useSelectorOptions } from "@/utilities"; +import { LOG } from "@/utilities/console"; +import FormUtils from "@/utilities/form"; import styles from "./ProfileEditForm.module.scss"; export const anyCutoff = 65535; diff --git a/frontend/src/components/forms/SeriesUploadForm.tsx b/frontend/src/components/forms/SeriesUploadForm.tsx index f0e8e0d31..31b39a8d8 100644 --- a/frontend/src/components/forms/SeriesUploadForm.tsx +++ b/frontend/src/components/forms/SeriesUploadForm.tsx @@ -1,8 +1,31 @@ +import { FunctionComponent, useEffect, useMemo } from "react"; +import { Column } from "react-table"; +import { + Button, + Checkbox, + Divider, + MantineColor, + Stack, + Text, +} from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { + faCheck, + faCircleNotch, + faInfoCircle, + faTimes, + faTrash, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { isString } from "lodash"; import { useEpisodesBySeriesId, useEpisodeSubtitleModification, useSubtitleInfos, } from "@/apis/hooks"; +import { Action, Selector } from "@/components/inputs"; +import { SimpleTable } from "@/components/tables"; +import TextPopover from "@/components/TextPopover"; import { useModals, withModal } from "@/modules/modals"; import { task, TaskGroup } from "@/modules/task"; import { useArrayAction, useSelectorOptions } from "@/utilities"; @@ -11,29 +34,6 @@ import { useLanguageProfileBy, useProfileItemsToLanguages, } from "@/utilities/languages"; -import { - faCheck, - faCircleNotch, - faInfoCircle, - faTimes, - faTrash, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { - Button, - Checkbox, - Divider, - MantineColor, - Stack, - Text, -} from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { isString } from "lodash"; -import { FunctionComponent, useEffect, useMemo } from "react"; -import { Column } from "react-table"; -import { Action, Selector } from "../inputs"; -import { SimpleTable } from "../tables"; -import TextPopover from "../TextPopover"; type SubtitleFile = { file: File; diff --git a/frontend/src/components/forms/SyncSubtitleForm.tsx b/frontend/src/components/forms/SyncSubtitleForm.tsx index c2e4ae9a5..867e49d72 100644 --- a/frontend/src/components/forms/SyncSubtitleForm.tsx +++ b/frontend/src/components/forms/SyncSubtitleForm.tsx @@ -1,20 +1,19 @@ /* eslint-disable camelcase */ - +import { FunctionComponent } from "react"; +import { Alert, Button, Checkbox, Divider, Stack, Text } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { faInfoCircle } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useRefTracksByEpisodeId, useRefTracksByMovieId, useSubtitleAction, } from "@/apis/hooks"; +import { GroupedSelector, Selector } from "@/components/inputs"; import { useModals, withModal } from "@/modules/modals"; import { task } from "@/modules/task"; import { syncMaxOffsetSecondsOptions } from "@/pages/Settings/Subtitles/options"; import { toPython } from "@/utilities"; -import { faInfoCircle } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Alert, Button, Checkbox, Divider, Stack, Text } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { FunctionComponent } from "react"; -import { GroupedSelector, Selector } from "../inputs"; const TaskName = "Syncing Subtitle"; diff --git a/frontend/src/components/forms/TimeOffsetForm.tsx b/frontend/src/components/forms/TimeOffsetForm.tsx index 3802f3a3e..182a26889 100644 --- a/frontend/src/components/forms/TimeOffsetForm.tsx +++ b/frontend/src/components/forms/TimeOffsetForm.tsx @@ -1,12 +1,12 @@ +import { FunctionComponent } from "react"; +import { Button, Divider, Group, NumberInput, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useSubtitleAction } from "@/apis/hooks"; import { useModals, withModal } from "@/modules/modals"; import { task } from "@/modules/task"; import FormUtils from "@/utilities/form"; -import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Button, Divider, Group, NumberInput, Stack } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { FunctionComponent } from "react"; const TaskName = "Changing Time"; diff --git a/frontend/src/components/forms/TranslationForm.tsx b/frontend/src/components/forms/TranslationForm.tsx index 976b2f72f..20aa08478 100644 --- a/frontend/src/components/forms/TranslationForm.tsx +++ b/frontend/src/components/forms/TranslationForm.tsx @@ -1,14 +1,14 @@ +import { FunctionComponent, useMemo } from "react"; +import { Alert, Button, Divider, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { isObject } from "lodash"; import { useSubtitleAction } from "@/apis/hooks"; +import { Selector } from "@/components/inputs"; import { useModals, withModal } from "@/modules/modals"; import { task } from "@/modules/task"; import { useSelectorOptions } from "@/utilities"; import FormUtils from "@/utilities/form"; import { useEnabledLanguages } from "@/utilities/languages"; -import { Alert, Button, Divider, Stack } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { isObject } from "lodash"; -import { FunctionComponent, useMemo } from "react"; -import { Selector } from "../inputs"; const TaskName = "Translating Subtitles"; diff --git a/frontend/src/components/inputs/Action.test.tsx b/frontend/src/components/inputs/Action.test.tsx index 80d24825b..dc8972630 100644 --- a/frontend/src/components/inputs/Action.test.tsx +++ b/frontend/src/components/inputs/Action.test.tsx @@ -1,7 +1,7 @@ -import { render, screen } from "@/tests"; import { faStickyNote } from "@fortawesome/free-regular-svg-icons"; import userEvent from "@testing-library/user-event"; import { describe, it, vitest } from "vitest"; +import { render, screen } from "@/tests"; import Action from "./Action"; const testLabel = "Test Label"; diff --git a/frontend/src/components/inputs/Action.tsx b/frontend/src/components/inputs/Action.tsx index 236baf112..95477f090 100644 --- a/frontend/src/components/inputs/Action.tsx +++ b/frontend/src/components/inputs/Action.tsx @@ -1,15 +1,15 @@ -import { IconDefinition } from "@fortawesome/fontawesome-common-types"; -import { - FontAwesomeIcon, - FontAwesomeIconProps, -} from "@fortawesome/react-fontawesome"; +import { forwardRef } from "react"; import { ActionIcon, ActionIconProps, Tooltip, TooltipProps, } from "@mantine/core"; -import { forwardRef } from "react"; +import { IconDefinition } from "@fortawesome/fontawesome-common-types"; +import { + FontAwesomeIcon, + FontAwesomeIconProps, +} from "@fortawesome/react-fontawesome"; export type ActionProps = MantineComp & { icon: IconDefinition; diff --git a/frontend/src/components/inputs/ChipInput.test.tsx b/frontend/src/components/inputs/ChipInput.test.tsx index 4aa29e8b7..4035966fc 100644 --- a/frontend/src/components/inputs/ChipInput.test.tsx +++ b/frontend/src/components/inputs/ChipInput.test.tsx @@ -1,6 +1,6 @@ -import { render, screen } from "@/tests"; import userEvent from "@testing-library/user-event"; import { describe, it, vitest } from "vitest"; +import { render, screen } from "@/tests"; import ChipInput from "./ChipInput"; describe("ChipInput", () => { diff --git a/frontend/src/components/inputs/DropContent.tsx b/frontend/src/components/inputs/DropContent.tsx index 015794ead..c4bcf2877 100644 --- a/frontend/src/components/inputs/DropContent.tsx +++ b/frontend/src/components/inputs/DropContent.tsx @@ -1,12 +1,12 @@ +import { FunctionComponent } from "react"; +import { Group, Stack, Text } from "@mantine/core"; +import { Dropzone } from "@mantine/dropzone"; import { faArrowUp, faFileCirclePlus, faXmark, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Group, Stack, Text } from "@mantine/core"; -import { Dropzone } from "@mantine/dropzone"; -import { FunctionComponent } from "react"; import styles from "./DropContent.module.scss"; export const DropContent: FunctionComponent = () => { diff --git a/frontend/src/components/inputs/FileBrowser.tsx b/frontend/src/components/inputs/FileBrowser.tsx index e1a4b5c18..bba66a66e 100644 --- a/frontend/src/components/inputs/FileBrowser.tsx +++ b/frontend/src/components/inputs/FileBrowser.tsx @@ -1,13 +1,13 @@ -import { useFileSystem } from "@/apis/hooks"; -import { faFolder } from "@fortawesome/free-regular-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent, useEffect, useMemo, useRef, useState } from "react"; import { Autocomplete, AutocompleteProps, ComboboxItem, OptionsFilter, } from "@mantine/core"; -import { FunctionComponent, useEffect, useMemo, useRef, useState } from "react"; +import { faFolder } from "@fortawesome/free-regular-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useFileSystem } from "@/apis/hooks"; // TODO: use fortawesome icons const backKey = "⏎ Back"; diff --git a/frontend/src/components/inputs/Selector.test.tsx b/frontend/src/components/inputs/Selector.test.tsx index 0da13e5bf..a28772a2d 100644 --- a/frontend/src/components/inputs/Selector.test.tsx +++ b/frontend/src/components/inputs/Selector.test.tsx @@ -1,6 +1,6 @@ -import { render, screen } from "@/tests"; import userEvent from "@testing-library/user-event"; import { describe, it, vitest } from "vitest"; +import { render, screen } from "@/tests"; import { Selector, SelectorOption } from "./Selector"; const selectorName = "Test Selections"; diff --git a/frontend/src/components/inputs/Selector.tsx b/frontend/src/components/inputs/Selector.tsx index 6a25144f5..ff06b3855 100644 --- a/frontend/src/components/inputs/Selector.tsx +++ b/frontend/src/components/inputs/Selector.tsx @@ -1,4 +1,4 @@ -import { LOG } from "@/utilities/console"; +import { useCallback, useMemo, useRef } from "react"; import { ComboboxItem, ComboboxParsedItemGroup, @@ -8,7 +8,7 @@ import { SelectProps, } from "@mantine/core"; import { isNull, isUndefined } from "lodash"; -import { useCallback, useMemo, useRef } from "react"; +import { LOG } from "@/utilities/console"; export type SelectorOption = Override< { diff --git a/frontend/src/components/modals/HistoryModal.tsx b/frontend/src/components/modals/HistoryModal.tsx index cc4197c44..b2d28a622 100644 --- a/frontend/src/components/modals/HistoryModal.tsx +++ b/frontend/src/components/modals/HistoryModal.tsx @@ -1,23 +1,23 @@ /* eslint-disable camelcase */ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { Badge, Center, Text } from "@mantine/core"; +import { faFileExcel, faInfoCircle } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useEpisodeAddBlacklist, useEpisodeHistory, useMovieAddBlacklist, useMovieHistory, } from "@/apis/hooks"; +import { PageTable } from "@/components"; +import MutateAction from "@/components/async/MutateAction"; +import QueryOverlay from "@/components/async/QueryOverlay"; +import { HistoryIcon } from "@/components/bazarr"; +import Language from "@/components/bazarr/Language"; import StateIcon from "@/components/StateIcon"; +import TextPopover from "@/components/TextPopover"; import { withModal } from "@/modules/modals"; -import { faFileExcel, faInfoCircle } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -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"; interface MovieHistoryViewProps { movie: Item.Movie; diff --git a/frontend/src/components/modals/ManualSearchModal.tsx b/frontend/src/components/modals/ManualSearchModal.tsx index 9a9de605d..dbacaf989 100644 --- a/frontend/src/components/modals/ManualSearchModal.tsx +++ b/frontend/src/components/modals/ManualSearchModal.tsx @@ -1,12 +1,6 @@ -import { withModal } from "@/modules/modals"; -import { task, TaskGroup } from "@/modules/task"; -import { GetItemId } from "@/utilities"; -import { - faCaretDown, - faDownload, - faInfoCircle, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useCallback, useMemo, useState } from "react"; +import { UseQueryResult } from "react-query"; +import { Column } from "react-table"; import { Alert, Anchor, @@ -18,13 +12,19 @@ import { Stack, Text, } from "@mantine/core"; +import { + faCaretDown, + faDownload, + faInfoCircle, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { isString } from "lodash"; -import { useCallback, useMemo, useState } from "react"; -import { UseQueryResult } from "react-query"; -import { Column } from "react-table"; -import { Action, PageTable } from ".."; -import Language from "../bazarr/Language"; -import StateIcon from "../StateIcon"; +import { Action, PageTable } from "@/components"; +import Language from "@/components/bazarr/Language"; +import StateIcon from "@/components/StateIcon"; +import { withModal } from "@/modules/modals"; +import { task, TaskGroup } from "@/modules/task"; +import { GetItemId } from "@/utilities"; type SupportType = Item.Movie | Item.Episode; diff --git a/frontend/src/components/modals/SubtitleToolsModal.tsx b/frontend/src/components/modals/SubtitleToolsModal.tsx index 2ba99ec73..150788b48 100644 --- a/frontend/src/components/modals/SubtitleToolsModal.tsx +++ b/frontend/src/components/modals/SubtitleToolsModal.tsx @@ -1,12 +1,12 @@ +import { FunctionComponent, useMemo, useState } from "react"; +import { Column, useRowSelect } from "react-table"; +import { Badge, Button, Divider, Group, Stack, Text } from "@mantine/core"; import Language from "@/components/bazarr/Language"; import SubtitleToolsMenu from "@/components/SubtitleToolsMenu"; 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, Text } from "@mantine/core"; -import { FunctionComponent, useMemo, useState } from "react"; -import { Column, useRowSelect } from "react-table"; type SupportType = Item.Episode | Item.Movie; diff --git a/frontend/src/components/tables/BaseTable.tsx b/frontend/src/components/tables/BaseTable.tsx index f31e9fff0..53058032d 100644 --- a/frontend/src/components/tables/BaseTable.tsx +++ b/frontend/src/components/tables/BaseTable.tsx @@ -1,8 +1,8 @@ -import { useIsLoading } from "@/contexts"; -import { usePageSize } from "@/utilities/storage"; -import { Box, Skeleton, Table, Text } from "@mantine/core"; import { ReactNode, useMemo } from "react"; import { HeaderGroup, Row, TableInstance } from "react-table"; +import { Box, Skeleton, Table, Text } from "@mantine/core"; +import { useIsLoading } from "@/contexts"; +import { usePageSize } from "@/utilities/storage"; import styles from "./BaseTable.module.scss"; export type BaseTableProps = TableInstance & { diff --git a/frontend/src/components/tables/GroupTable.tsx b/frontend/src/components/tables/GroupTable.tsx index f58c868a5..c05182aa6 100644 --- a/frontend/src/components/tables/GroupTable.tsx +++ b/frontend/src/components/tables/GroupTable.tsx @@ -1,6 +1,3 @@ -import { faChevronCircleRight } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Box, Text, Table } from "@mantine/core"; import { Cell, HeaderGroup, @@ -9,6 +6,9 @@ import { useGroupBy, useSortBy, } from "react-table"; +import { Box, Table, Text } from "@mantine/core"; +import { faChevronCircleRight } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import SimpleTable, { SimpleTableProps } from "./SimpleTable"; function renderCell(cell: Cell, row: Row) { diff --git a/frontend/src/components/tables/PageControl.tsx b/frontend/src/components/tables/PageControl.tsx index 8cf528e31..8b7fd938f 100644 --- a/frontend/src/components/tables/PageControl.tsx +++ b/frontend/src/components/tables/PageControl.tsx @@ -1,6 +1,6 @@ -import { useIsLoading } from "@/contexts"; -import { Group, Pagination, Text } from "@mantine/core"; import { FunctionComponent, useEffect } from "react"; +import { Group, Pagination, Text } from "@mantine/core"; +import { useIsLoading } from "@/contexts"; interface Props { count: number; index: number; diff --git a/frontend/src/components/tables/PageTable.tsx b/frontend/src/components/tables/PageTable.tsx index 4f64fe7b8..ee4824db6 100644 --- a/frontend/src/components/tables/PageTable.tsx +++ b/frontend/src/components/tables/PageTable.tsx @@ -1,11 +1,11 @@ -import { ScrollToTop } from "@/utilities"; -import { usePageSize } from "@/utilities/storage"; import { useEffect } from "react"; import { usePagination, useTable } from "react-table"; +import { ScrollToTop } from "@/utilities"; +import { usePageSize } from "@/utilities/storage"; import BaseTable from "./BaseTable"; import PageControl from "./PageControl"; -import { SimpleTableProps } from "./SimpleTable"; import { useDefaultSettings } from "./plugins"; +import { SimpleTableProps } from "./SimpleTable"; type Props = SimpleTableProps & { autoScroll?: boolean; diff --git a/frontend/src/components/tables/QueryPageTable.tsx b/frontend/src/components/tables/QueryPageTable.tsx index 81eccee13..c144b3b54 100644 --- a/frontend/src/components/tables/QueryPageTable.tsx +++ b/frontend/src/components/tables/QueryPageTable.tsx @@ -1,7 +1,7 @@ +import { useEffect } from "react"; import { UsePaginationQueryResult } from "@/apis/queries/hooks"; import { LoadingProvider } from "@/contexts"; import { ScrollToTop } from "@/utilities"; -import { useEffect } from "react"; import PageControl from "./PageControl"; import SimpleTable, { SimpleTableProps } from "./SimpleTable"; diff --git a/frontend/src/components/tables/plugins/useCustomSelection.tsx b/frontend/src/components/tables/plugins/useCustomSelection.tsx index d6ea82de4..572926093 100644 --- a/frontend/src/components/tables/plugins/useCustomSelection.tsx +++ b/frontend/src/components/tables/plugins/useCustomSelection.tsx @@ -1,16 +1,16 @@ -import { Checkbox as MantineCheckbox } from "@mantine/core"; import { forwardRef, useEffect, useRef } from "react"; import { CellProps, Column, ColumnInstance, + ensurePluginOrder, HeaderProps, Hooks, MetaBase, TableInstance, TableToggleCommonProps, - ensurePluginOrder, } from "react-table"; +import { Checkbox as MantineCheckbox } from "@mantine/core"; const pluginName = "useCustomSelection"; diff --git a/frontend/src/components/tables/plugins/useDefaultSettings.tsx b/frontend/src/components/tables/plugins/useDefaultSettings.tsx index c833c9f79..ac34334b4 100644 --- a/frontend/src/components/tables/plugins/useDefaultSettings.tsx +++ b/frontend/src/components/tables/plugins/useDefaultSettings.tsx @@ -1,5 +1,5 @@ -import { usePageSize } from "@/utilities/storage"; import { Hooks, TableOptions } from "react-table"; +import { usePageSize } from "@/utilities/storage"; const pluginName = "useLocalSettings"; diff --git a/frontend/src/components/toolbox/Button.tsx b/frontend/src/components/toolbox/Button.tsx index 022cf9081..0a1d311e1 100644 --- a/frontend/src/components/toolbox/Button.tsx +++ b/frontend/src/components/toolbox/Button.tsx @@ -1,6 +1,3 @@ -import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Button, ButtonProps, Text } from "@mantine/core"; import { ComponentProps, FunctionComponent, @@ -8,6 +5,9 @@ import { useCallback, useState, } from "react"; +import { Button, ButtonProps, Text } from "@mantine/core"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; type ToolboxButtonProps = Omit & Omit, "ref"> & { diff --git a/frontend/src/components/toolbox/Toolbox.tsx b/frontend/src/components/toolbox/Toolbox.tsx index fbeadbc5f..8e600acda 100644 --- a/frontend/src/components/toolbox/Toolbox.tsx +++ b/frontend/src/components/toolbox/Toolbox.tsx @@ -1,5 +1,5 @@ -import { Group } from "@mantine/core"; import { FunctionComponent, PropsWithChildren } from "react"; +import { Group } from "@mantine/core"; import ToolboxButton, { ToolboxMutateButton } from "./Button"; import styles from "./Toolbox.module.scss"; diff --git a/frontend/src/dom.tsx b/frontend/src/dom.tsx index 07b2078a8..f3b7ec03e 100644 --- a/frontend/src/dom.tsx +++ b/frontend/src/dom.tsx @@ -1,7 +1,7 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import { Router } from "./Router"; import { AllProviders } from "./providers"; +import { Router } from "./Router"; const container = document.getElementById("root"); diff --git a/frontend/src/modules/modals/ModalsProvider.tsx b/frontend/src/modules/modals/ModalsProvider.tsx index c704a7ae5..65c987848 100644 --- a/frontend/src/modules/modals/ModalsProvider.tsx +++ b/frontend/src/modules/modals/ModalsProvider.tsx @@ -1,8 +1,8 @@ +import { FunctionComponent, PropsWithChildren, useMemo } from "react"; import { ModalsProvider as MantineModalsProvider, ModalsProviderProps as MantineModalsProviderProps, } from "@mantine/modals"; -import { FunctionComponent, PropsWithChildren, useMemo } from "react"; import { ModalComponent, StaticModals } from "./WithModal"; const DefaultModalProps: MantineModalsProviderProps["modalProps"] = { diff --git a/frontend/src/modules/modals/WithModal.tsx b/frontend/src/modules/modals/WithModal.tsx index eadd6b932..de7b79155 100644 --- a/frontend/src/modules/modals/WithModal.tsx +++ b/frontend/src/modules/modals/WithModal.tsx @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/ban-types */ +import { createContext, FunctionComponent } from "react"; import { ContextModalProps } from "@mantine/modals"; import { ModalSettings } from "@mantine/modals/lib/context"; -import { createContext, FunctionComponent } from "react"; export type ModalComponent

= {}> = FunctionComponent> & { diff --git a/frontend/src/modules/modals/hooks.ts b/frontend/src/modules/modals/hooks.ts index 40e891b8e..09855ac51 100644 --- a/frontend/src/modules/modals/hooks.ts +++ b/frontend/src/modules/modals/hooks.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/ban-types */ +import { useCallback, useContext, useMemo } from "react"; import { useModals as useMantineModals } from "@mantine/modals"; import { ModalSettings } from "@mantine/modals/lib/context"; -import { useCallback, useContext, useMemo } from "react"; import { ModalComponent, ModalIdContext } from "./WithModal"; export function useModals() { diff --git a/frontend/src/modules/socketio/hooks.ts b/frontend/src/modules/socketio/hooks.ts index 741fa5f4a..8d02cce6a 100644 --- a/frontend/src/modules/socketio/hooks.ts +++ b/frontend/src/modules/socketio/hooks.ts @@ -1,6 +1,6 @@ import { useEffect } from "react"; +import { LOG } from "@/utilities/console"; import Socketio from "."; -import { LOG } from "../../utilities/console"; export function useSocketIOReducer(reducer: SocketIO.Reducer) { useEffect(() => { diff --git a/frontend/src/modules/socketio/index.ts b/frontend/src/modules/socketio/index.ts index 64a8d6511..6c0a2810f 100644 --- a/frontend/src/modules/socketio/index.ts +++ b/frontend/src/modules/socketio/index.ts @@ -1,8 +1,8 @@ -import { debounce, forIn, remove, uniq } from "lodash"; import { onlineManager } from "react-query"; -import { Socket, io } from "socket.io-client"; -import { Environment, isDevEnv, isTestEnv } from "../../utilities"; -import { ENSURE, GROUP, LOG } from "../../utilities/console"; +import { debounce, forIn, remove, uniq } from "lodash"; +import { io, Socket } from "socket.io-client"; +import { Environment, isDevEnv, isTestEnv } from "@/utilities"; +import { ENSURE, GROUP, LOG } from "@/utilities/console"; import { createDefaultReducer } from "./reducer"; class SocketIOClient { diff --git a/frontend/src/modules/socketio/reducer.ts b/frontend/src/modules/socketio/reducer.ts index 35a553de9..81157fdc1 100644 --- a/frontend/src/modules/socketio/reducer.ts +++ b/frontend/src/modules/socketio/reducer.ts @@ -1,9 +1,9 @@ +import { cleanNotifications, showNotification } from "@mantine/notifications"; import queryClient from "@/apis/queries"; import { QueryKeys } from "@/apis/queries/keys"; +import { notification, task } from "@/modules/task"; import { LOG } from "@/utilities/console"; import { setCriticalError, setOnlineStatus } from "@/utilities/event"; -import { cleanNotifications, showNotification } from "@mantine/notifications"; -import { notification, task } from "../task"; export function createDefaultReducer(): SocketIO.Reducer[] { return [ diff --git a/frontend/src/modules/task/index.ts b/frontend/src/modules/task/index.ts index 5a33a39a3..59efcaf56 100644 --- a/frontend/src/modules/task/index.ts +++ b/frontend/src/modules/task/index.ts @@ -1,10 +1,10 @@ -import { LOG } from "@/utilities/console"; import { hideNotification, showNotification, updateNotification, } from "@mantine/notifications"; import { uniqueId } from "lodash"; +import { LOG } from "@/utilities/console"; import { notification } from "./notification"; class TaskDispatcher { diff --git a/frontend/src/pages/Authentication.test.tsx b/frontend/src/pages/Authentication.test.tsx index 95bfe3f47..e5dee6e44 100644 --- a/frontend/src/pages/Authentication.test.tsx +++ b/frontend/src/pages/Authentication.test.tsx @@ -1,5 +1,5 @@ -import { render, screen } from "@/tests"; import { describe, it } from "vitest"; +import { render, screen } from "@/tests"; import Authentication from "./Authentication"; describe("Authentication", () => { diff --git a/frontend/src/pages/Authentication.tsx b/frontend/src/pages/Authentication.tsx index 33fda6f01..7a164c6c4 100644 --- a/frontend/src/pages/Authentication.tsx +++ b/frontend/src/pages/Authentication.tsx @@ -1,5 +1,4 @@ -import { useSystem } from "@/apis/hooks"; -import { Environment } from "@/utilities"; +import { FunctionComponent } from "react"; import { Avatar, Button, @@ -11,7 +10,8 @@ import { TextInput, } from "@mantine/core"; import { useForm } from "@mantine/form"; -import { FunctionComponent } from "react"; +import { useSystem } from "@/apis/hooks"; +import { Environment } from "@/utilities"; const Authentication: FunctionComponent = () => { const { login } = useSystem(); diff --git a/frontend/src/pages/Blacklist/Movies/index.tsx b/frontend/src/pages/Blacklist/Movies/index.tsx index 67c6a2a7d..9e552fa7d 100644 --- a/frontend/src/pages/Blacklist/Movies/index.tsx +++ b/frontend/src/pages/Blacklist/Movies/index.tsx @@ -1,13 +1,13 @@ +import { FunctionComponent } from "react"; +import { Container, Stack } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faTrash } from "@fortawesome/free-solid-svg-icons"; import { useMovieBlacklist, useMovieDeleteBlacklist, } from "@/apis/hooks/movies"; import { Toolbox } from "@/components"; import { QueryOverlay } from "@/components/async"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Container, Stack } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; import Table from "./table"; const BlacklistMoviesView: FunctionComponent = () => { diff --git a/frontend/src/pages/Blacklist/Movies/table.tsx b/frontend/src/pages/Blacklist/Movies/table.tsx index 6609d186d..0ac3bf3a8 100644 --- a/frontend/src/pages/Blacklist/Movies/table.tsx +++ b/frontend/src/pages/Blacklist/Movies/table.tsx @@ -1,13 +1,13 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Text } from "@mantine/core"; +import { faTrash } from "@fortawesome/free-solid-svg-icons"; import { useMovieDeleteBlacklist } from "@/apis/hooks"; import { PageTable } from "@/components"; import MutateAction from "@/components/async/MutateAction"; import Language from "@/components/bazarr/Language"; import TextPopover from "@/components/TextPopover"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Anchor, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; interface Props { blacklist: readonly Blacklist.Movie[]; diff --git a/frontend/src/pages/Blacklist/Series/index.tsx b/frontend/src/pages/Blacklist/Series/index.tsx index a4a6d3638..3bdec2b19 100644 --- a/frontend/src/pages/Blacklist/Series/index.tsx +++ b/frontend/src/pages/Blacklist/Series/index.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent } from "react"; +import { Container, Stack } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faTrash } from "@fortawesome/free-solid-svg-icons"; import { useEpisodeBlacklist, useEpisodeDeleteBlacklist } from "@/apis/hooks"; import { Toolbox } from "@/components"; import { QueryOverlay } from "@/components/async"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Container, Stack } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; import Table from "./table"; const BlacklistSeriesView: FunctionComponent = () => { diff --git a/frontend/src/pages/Blacklist/Series/table.tsx b/frontend/src/pages/Blacklist/Series/table.tsx index 96ea1a8a7..655b8d67a 100644 --- a/frontend/src/pages/Blacklist/Series/table.tsx +++ b/frontend/src/pages/Blacklist/Series/table.tsx @@ -1,13 +1,13 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Text } from "@mantine/core"; +import { faTrash } from "@fortawesome/free-solid-svg-icons"; import { useEpisodeDeleteBlacklist } from "@/apis/hooks"; import { PageTable } from "@/components"; import MutateAction from "@/components/async/MutateAction"; import Language from "@/components/bazarr/Language"; import TextPopover from "@/components/TextPopover"; -import { faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Anchor, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; interface Props { blacklist: readonly Blacklist.Episode[]; diff --git a/frontend/src/pages/Episodes/components.tsx b/frontend/src/pages/Episodes/components.tsx index 698785d5e..29ce2e0fa 100644 --- a/frontend/src/pages/Episodes/components.tsx +++ b/frontend/src/pages/Episodes/components.tsx @@ -1,9 +1,9 @@ +import { FunctionComponent, useMemo, useState } from "react"; +import { Badge, MantineColor, Tooltip } from "@mantine/core"; import { useEpisodeSubtitleModification } from "@/apis/hooks"; import Language from "@/components/bazarr/Language"; import SubtitleToolsMenu from "@/components/SubtitleToolsMenu"; import { task, TaskGroup } from "@/modules/task"; -import { Badge, MantineColor, Tooltip } from "@mantine/core"; -import { FunctionComponent, useMemo, useState } from "react"; interface Props { seriesId: number; diff --git a/frontend/src/pages/Episodes/index.tsx b/frontend/src/pages/Episodes/index.tsx index b016490ff..13c112050 100644 --- a/frontend/src/pages/Episodes/index.tsx +++ b/frontend/src/pages/Episodes/index.tsx @@ -1,4 +1,26 @@ -import { RouterNames } from "@/Router/RouterNames"; +import { + FunctionComponent, + useCallback, + useMemo, + useRef, + useState, +} from "react"; +import { Navigate, useParams } from "react-router-dom"; +import { Container, Group, Stack } from "@mantine/core"; +import { Dropzone } from "@mantine/dropzone"; +import { useDocumentTitle } from "@mantine/hooks"; +import { showNotification } from "@mantine/notifications"; +import { + faAdjust, + faBriefcase, + faCircleChevronDown, + faCircleChevronRight, + faCloudUploadAlt, + faHdd, + faSearch, + faSync, + faWrench, +} from "@fortawesome/free-solid-svg-icons"; import { useEpisodesBySeriesId, useIsAnyActionRunning, @@ -12,32 +34,10 @@ import { ItemEditModal } from "@/components/forms/ItemEditForm"; import { SeriesUploadModal } from "@/components/forms/SeriesUploadForm"; import { SubtitleToolsModal } from "@/components/modals"; import { useModals } from "@/modules/modals"; -import { TaskGroup, notification, task } from "@/modules/task"; +import { notification, task, TaskGroup } from "@/modules/task"; import ItemOverview from "@/pages/views/ItemOverview"; +import { RouterNames } from "@/Router/RouterNames"; import { useLanguageProfileBy } from "@/utilities/languages"; -import { - faAdjust, - faBriefcase, - faCircleChevronDown, - faCircleChevronRight, - faCloudUploadAlt, - faHdd, - faSearch, - faSync, - faWrench, -} from "@fortawesome/free-solid-svg-icons"; -import { Container, Group, Stack } from "@mantine/core"; -import { Dropzone } from "@mantine/dropzone"; -import { useDocumentTitle } from "@mantine/hooks"; -import { showNotification } from "@mantine/notifications"; -import { - FunctionComponent, - useCallback, - useMemo, - useRef, - useState, -} from "react"; -import { Navigate, useParams } from "react-router-dom"; import Table from "./table"; const SeriesEpisodesView: FunctionComponent = () => { diff --git a/frontend/src/pages/Episodes/table.tsx b/frontend/src/pages/Episodes/table.tsx index f1aa6a52e..d7eb0a0e1 100644 --- a/frontend/src/pages/Episodes/table.tsx +++ b/frontend/src/pages/Episodes/table.tsx @@ -1,29 +1,29 @@ +import { + FunctionComponent, + useCallback, + useEffect, + useMemo, + useRef, +} from "react"; +import { Column, TableInstance } from "react-table"; +import { Group, Text } from "@mantine/core"; +import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; +import { + faBookmark, + faHistory, + faUser, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 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 { BuildKey, filterSubtitleBy } from "@/utilities"; import { useProfileItemsToLanguages } from "@/utilities/languages"; -import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; -import { - faBookmark, - faHistory, - faUser, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Group, Text } from "@mantine/core"; -import { - FunctionComponent, - useCallback, - useEffect, - useMemo, - useRef, -} from "react"; -import { Column, TableInstance } from "react-table"; import { Subtitle } from "./components"; interface Props { diff --git a/frontend/src/pages/History/Movies/index.tsx b/frontend/src/pages/History/Movies/index.tsx index bdbe5966a..39365e348 100644 --- a/frontend/src/pages/History/Movies/index.tsx +++ b/frontend/src/pages/History/Movies/index.tsx @@ -1,4 +1,14 @@ /* eslint-disable camelcase */ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Badge, Text } from "@mantine/core"; +import { + faFileExcel, + faInfoCircle, + faRecycle, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useMovieAddBlacklist, useMovieHistoryPagination } from "@/apis/hooks"; import { MutateAction } from "@/components/async"; import { HistoryIcon } from "@/components/bazarr"; @@ -6,16 +16,6 @@ import Language from "@/components/bazarr/Language"; import StateIcon from "@/components/StateIcon"; import TextPopover from "@/components/TextPopover"; import HistoryView from "@/pages/views/HistoryView"; -import { - faFileExcel, - faInfoCircle, - faRecycle, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Badge, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const MoviesHistoryView: FunctionComponent = () => { const columns: Column[] = useMemo[]>( diff --git a/frontend/src/pages/History/Series/index.tsx b/frontend/src/pages/History/Series/index.tsx index e2d2f9662..67f18b9d9 100644 --- a/frontend/src/pages/History/Series/index.tsx +++ b/frontend/src/pages/History/Series/index.tsx @@ -1,4 +1,14 @@ /* eslint-disable camelcase */ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Badge, Text } from "@mantine/core"; +import { + faFileExcel, + faInfoCircle, + faRecycle, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useEpisodeAddBlacklist, useEpisodeHistoryPagination, @@ -9,16 +19,6 @@ import Language from "@/components/bazarr/Language"; import StateIcon from "@/components/StateIcon"; import TextPopover from "@/components/TextPopover"; import HistoryView from "@/pages/views/HistoryView"; -import { - faFileExcel, - faInfoCircle, - faRecycle, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Badge, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const SeriesHistoryView: FunctionComponent = () => { const columns: Column[] = useMemo[]>( diff --git a/frontend/src/pages/History/Statistics/HistoryStats.tsx b/frontend/src/pages/History/Statistics/HistoryStats.tsx index 9358cac30..0e2d34400 100644 --- a/frontend/src/pages/History/Statistics/HistoryStats.tsx +++ b/frontend/src/pages/History/Statistics/HistoryStats.tsx @@ -1,15 +1,7 @@ -import { - useHistoryStats, - useLanguages, - useSystemProviders, -} from "@/apis/hooks"; -import { Selector, Toolbox } from "@/components"; -import { QueryOverlay } from "@/components/async"; -import { useSelectorOptions } from "@/utilities"; +import { FunctionComponent, useMemo, useState } from "react"; import { Box, Container, SimpleGrid, useMantineTheme } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; import { merge } from "lodash"; -import { FunctionComponent, useMemo, useState } from "react"; import { Bar, BarChart, @@ -20,6 +12,14 @@ import { XAxis, YAxis, } from "recharts"; +import { + useHistoryStats, + useLanguages, + useSystemProviders, +} from "@/apis/hooks"; +import { Selector, Toolbox } from "@/components"; +import { QueryOverlay } from "@/components/async"; +import { useSelectorOptions } from "@/utilities"; import { actionOptions, timeFrameOptions } from "./options"; import styles from "./HistoryStats.module.scss"; diff --git a/frontend/src/pages/History/history.test.tsx b/frontend/src/pages/History/history.test.tsx index a348a5b91..277a268fb 100644 --- a/frontend/src/pages/History/history.test.tsx +++ b/frontend/src/pages/History/history.test.tsx @@ -1,7 +1,7 @@ import { renderTest, RenderTestCase } from "@/tests/render"; +import HistoryStats from "./Statistics/HistoryStats"; import MoviesHistoryView from "./Movies"; import SeriesHistoryView from "./Series"; -import HistoryStats from "./Statistics/HistoryStats"; const cases: RenderTestCase[] = [ { diff --git a/frontend/src/pages/Movies/Details/index.tsx b/frontend/src/pages/Movies/Details/index.tsx index 4168754f1..1c971d641 100644 --- a/frontend/src/pages/Movies/Details/index.tsx +++ b/frontend/src/pages/Movies/Details/index.tsx @@ -1,4 +1,21 @@ -import { RouterNames } from "@/Router/RouterNames"; +import { FunctionComponent, useCallback, useRef } from "react"; +import { Navigate, useParams } from "react-router-dom"; +import { Container, Group, Menu, Stack } from "@mantine/core"; +import { Dropzone } from "@mantine/dropzone"; +import { useDocumentTitle } from "@mantine/hooks"; +import { showNotification } from "@mantine/notifications"; +import { + faCloudUploadAlt, + faEllipsis, + faHistory, + faSearch, + faSync, + faToolbox, + faUser, + faWrench, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { isNumber } from "lodash"; import { useDownloadMovieSubtitles, useIsMovieActionRunning, @@ -16,27 +33,10 @@ import { MovieUploadModal } from "@/components/forms/MovieUploadForm"; import { MovieHistoryModal, SubtitleToolsModal } from "@/components/modals"; import { MovieSearchModal } from "@/components/modals/ManualSearchModal"; import { useModals } from "@/modules/modals"; -import { TaskGroup, notification, task } from "@/modules/task"; +import { notification, task, TaskGroup } from "@/modules/task"; import ItemOverview from "@/pages/views/ItemOverview"; +import { RouterNames } from "@/Router/RouterNames"; import { useLanguageProfileBy } from "@/utilities/languages"; -import { - faCloudUploadAlt, - faEllipsis, - faHistory, - faSearch, - faSync, - faToolbox, - faUser, - faWrench, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Container, Group, Menu, Stack } from "@mantine/core"; -import { Dropzone } from "@mantine/dropzone"; -import { useDocumentTitle } from "@mantine/hooks"; -import { showNotification } from "@mantine/notifications"; -import { isNumber } from "lodash"; -import { FunctionComponent, useCallback, useRef } from "react"; -import { Navigate, useParams } from "react-router-dom"; import Table from "./table"; const MovieDetailView: FunctionComponent = () => { diff --git a/frontend/src/pages/Movies/Details/table.tsx b/frontend/src/pages/Movies/Details/table.tsx index aa7e164cc..61a5c14c9 100644 --- a/frontend/src/pages/Movies/Details/table.tsx +++ b/frontend/src/pages/Movies/Details/table.tsx @@ -1,3 +1,8 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { Badge, Text, TextProps } from "@mantine/core"; +import { faEllipsis, faSearch } from "@fortawesome/free-solid-svg-icons"; +import { isString } from "lodash"; import { useMovieSubtitleModification } from "@/apis/hooks"; import { useShowOnlyDesired } from "@/apis/hooks/site"; import { Action, SimpleTable } from "@/components"; @@ -6,11 +11,6 @@ import SubtitleToolsMenu from "@/components/SubtitleToolsMenu"; import { task, TaskGroup } from "@/modules/task"; import { filterSubtitleBy } from "@/utilities"; import { useProfileItemsToLanguages } from "@/utilities/languages"; -import { faEllipsis, faSearch } from "@fortawesome/free-solid-svg-icons"; -import { Badge, Text, TextProps } from "@mantine/core"; -import { isString } from "lodash"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; const missingText = "Missing Subtitles"; diff --git a/frontend/src/pages/Movies/Editor.tsx b/frontend/src/pages/Movies/Editor.tsx index a196f9deb..0c568a5b1 100644 --- a/frontend/src/pages/Movies/Editor.tsx +++ b/frontend/src/pages/Movies/Editor.tsx @@ -1,11 +1,11 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { useDocumentTitle } from "@mantine/hooks"; import { useMovieModification, useMovies } from "@/apis/hooks"; import { QueryOverlay } from "@/components/async"; import { AudioList } from "@/components/bazarr"; import LanguageProfileName from "@/components/bazarr/LanguageProfile"; import MassEditor from "@/pages/views/MassEditor"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; const MovieMassEditor: FunctionComponent = () => { const query = useMovies(); diff --git a/frontend/src/pages/Movies/index.tsx b/frontend/src/pages/Movies/index.tsx index 262d56195..94c98a007 100644 --- a/frontend/src/pages/Movies/index.tsx +++ b/frontend/src/pages/Movies/index.tsx @@ -1,3 +1,11 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Badge, Container } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; +import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useMovieModification, useMoviesPagination } from "@/apis/hooks"; import { Action } from "@/components"; import { AudioList } from "@/components/bazarr"; @@ -7,14 +15,6 @@ import { ItemEditModal } from "@/components/forms/ItemEditForm"; import { useModals } from "@/modules/modals"; import ItemView from "@/pages/views/ItemView"; import { BuildKey } from "@/utilities"; -import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; -import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Badge, Container } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const MovieView: FunctionComponent = () => { const query = useMoviesPagination(); diff --git a/frontend/src/pages/Movies/movies.test.tsx b/frontend/src/pages/Movies/movies.test.tsx index fe5691a15..c4ac8133a 100644 --- a/frontend/src/pages/Movies/movies.test.tsx +++ b/frontend/src/pages/Movies/movies.test.tsx @@ -1,7 +1,7 @@ -import { render } from "@/tests"; import { describe } from "vitest"; -import MovieView from "."; +import { render } from "@/tests"; import MovieMassEditor from "./Editor"; +import MovieView from "."; describe("Movies page", () => { it("should render", () => { diff --git a/frontend/src/pages/Series/Editor.tsx b/frontend/src/pages/Series/Editor.tsx index 4db9a4c1d..239481069 100644 --- a/frontend/src/pages/Series/Editor.tsx +++ b/frontend/src/pages/Series/Editor.tsx @@ -1,11 +1,11 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { useDocumentTitle } from "@mantine/hooks"; import { useSeries, useSeriesModification } from "@/apis/hooks"; import { QueryOverlay } from "@/components/async"; import { AudioList } from "@/components/bazarr"; import LanguageProfileName from "@/components/bazarr/LanguageProfile"; import MassEditor from "@/pages/views/MassEditor"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; const SeriesMassEditor: FunctionComponent = () => { const query = useSeries(); diff --git a/frontend/src/pages/Series/index.tsx b/frontend/src/pages/Series/index.tsx index 60206d34a..e36a89be6 100644 --- a/frontend/src/pages/Series/index.tsx +++ b/frontend/src/pages/Series/index.tsx @@ -1,17 +1,17 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Container, Progress } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; +import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useSeriesModification, useSeriesPagination } from "@/apis/hooks"; import { Action } from "@/components"; import LanguageProfileName from "@/components/bazarr/LanguageProfile"; import { ItemEditModal } from "@/components/forms/ItemEditForm"; import { useModals } from "@/modules/modals"; import ItemView from "@/pages/views/ItemView"; -import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; -import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Container, Progress } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const SeriesView: FunctionComponent = () => { const mutation = useSeriesModification(); diff --git a/frontend/src/pages/Series/series.test.tsx b/frontend/src/pages/Series/series.test.tsx index 6813c6e19..b8fd9fad5 100644 --- a/frontend/src/pages/Series/series.test.tsx +++ b/frontend/src/pages/Series/series.test.tsx @@ -1,7 +1,7 @@ -import { render } from "@/tests"; import { describe } from "vitest"; -import SeriesView from "."; +import { render } from "@/tests"; import SeriesMassEditor from "./Editor"; +import SeriesView from "."; describe("Series page", () => { it("should render", () => { diff --git a/frontend/src/pages/Settings/General/index.tsx b/frontend/src/pages/Settings/General/index.tsx index bec3f946f..13f8ed409 100644 --- a/frontend/src/pages/Settings/General/index.tsx +++ b/frontend/src/pages/Settings/General/index.tsx @@ -1,12 +1,11 @@ -import { Environment, toggleState } from "@/utilities"; +import { FunctionComponent, useState } from "react"; +import { Box, Group as MantineGroup, Text as MantineText } from "@mantine/core"; +import { useClipboard } from "@mantine/hooks"; import { faCheck, faClipboard, faSync, } from "@fortawesome/free-solid-svg-icons"; -import { Box, Group as MantineGroup, Text as MantineText } from "@mantine/core"; -import { useClipboard } from "@mantine/hooks"; -import { FunctionComponent, useState } from "react"; import { Action, Check, @@ -20,7 +19,8 @@ import { Section, Selector, Text, -} from "../components"; +} from "@/pages/Settings/components"; +import { Environment, toggleState } from "@/utilities"; import { branchOptions, proxyOptions, securityOptions } from "./options"; const characters = "abcdef0123456789"; diff --git a/frontend/src/pages/Settings/Languages/components.tsx b/frontend/src/pages/Settings/Languages/components.tsx index de3e89c3e..9c3cf8e94 100644 --- a/frontend/src/pages/Settings/Languages/components.tsx +++ b/frontend/src/pages/Settings/Languages/components.tsx @@ -1,16 +1,15 @@ +import { FunctionComponent, useMemo } from "react"; +import { Input } from "@mantine/core"; import { MultiSelector, MultiSelectorProps, SelectorOption, } from "@/components"; -import { Language } from "@/components/bazarr"; +import { Selector, SelectorProps } from "@/pages/Settings/components"; +import { useFormActions } from "@/pages/Settings/utilities/FormValues"; +import { BaseInput } from "@/pages/Settings/utilities/hooks"; import { useSelectorOptions } from "@/utilities"; -import { Input } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; import { useLatestEnabledLanguages, useLatestProfiles } from "."; -import { Selector, SelectorProps } from "../components"; -import { useFormActions } from "../utilities/FormValues"; -import { BaseInput } from "../utilities/hooks"; type LanguageSelectorProps = Omit< MultiSelectorProps, diff --git a/frontend/src/pages/Settings/Languages/equals.test.ts b/frontend/src/pages/Settings/Languages/equals.test.ts index ead613946..5a74db797 100644 --- a/frontend/src/pages/Settings/Languages/equals.test.ts +++ b/frontend/src/pages/Settings/Languages/equals.test.ts @@ -1,10 +1,10 @@ +import { describe, expect, it } from "vitest"; import { decodeEqualData, encodeEqualData, LanguageEqualData, LanguageEqualImmediateData, } from "@/pages/Settings/Languages/equals"; -import { describe, expect, it } from "vitest"; describe("Equals Parser", () => { it("should parse from string correctly", () => { diff --git a/frontend/src/pages/Settings/Languages/equals.tsx b/frontend/src/pages/Settings/Languages/equals.tsx index a417059ab..968550cf2 100644 --- a/frontend/src/pages/Settings/Languages/equals.tsx +++ b/frontend/src/pages/Settings/Languages/equals.tsx @@ -1,3 +1,8 @@ +import { FunctionComponent, useCallback, useMemo } from "react"; +import { Column } from "react-table"; +import { Button, Checkbox } from "@mantine/core"; +import { faEquals, faTrash } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useLanguages } from "@/apis/hooks"; import { Action, SimpleTable } from "@/components"; import LanguageSelector from "@/components/bazarr/LanguageSelector"; @@ -5,11 +10,6 @@ import { languageEqualsKey } from "@/pages/Settings/keys"; import { useFormActions } from "@/pages/Settings/utilities/FormValues"; import { useSettingValue } from "@/pages/Settings/utilities/hooks"; import { LOG } from "@/utilities/console"; -import { faEquals, faTrash } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Button, Checkbox } from "@mantine/core"; -import { FunctionComponent, useCallback, useMemo } from "react"; -import { Column } from "react-table"; interface GenericEqualTarget { content: T; diff --git a/frontend/src/pages/Settings/Languages/index.tsx b/frontend/src/pages/Settings/Languages/index.tsx index 61733c992..9fe562920 100644 --- a/frontend/src/pages/Settings/Languages/index.tsx +++ b/frontend/src/pages/Settings/Languages/index.tsx @@ -1,6 +1,5 @@ -import { useLanguageProfiles, useLanguages } from "@/apis/hooks"; -import { useEnabledLanguages } from "@/utilities/languages"; import { FunctionComponent } from "react"; +import { useLanguageProfiles, useLanguages } from "@/apis/hooks"; import { Check, CollapseBox, @@ -8,14 +7,15 @@ import { Message, Section, Selector, -} from "../components"; +} from "@/pages/Settings/components"; import { defaultUndAudioLang, defaultUndEmbeddedSubtitlesLang, enabledLanguageKey, languageProfileKey, -} from "../keys"; -import { useSettingValue } from "../utilities/hooks"; +} from "@/pages/Settings/keys"; +import { useSettingValue } from "@/pages/Settings/utilities/hooks"; +import { useEnabledLanguages } from "@/utilities/languages"; import { LanguageSelector, ProfileSelector } from "./components"; import EqualsTable from "./equals"; import Table from "./table"; diff --git a/frontend/src/pages/Settings/Languages/table.tsx b/frontend/src/pages/Settings/Languages/table.tsx index 86a227207..324acfb91 100644 --- a/frontend/src/pages/Settings/Languages/table.tsx +++ b/frontend/src/pages/Settings/Languages/table.tsx @@ -1,18 +1,18 @@ +import { FunctionComponent, useCallback, useMemo } from "react"; +import { Column } from "react-table"; +import { Badge, Button, Group } from "@mantine/core"; +import { faTrash, faWrench } from "@fortawesome/free-solid-svg-icons"; +import { cloneDeep } from "lodash"; import { Action, SimpleTable } from "@/components"; import { - ProfileEditModal, anyCutoff, + ProfileEditModal, } from "@/components/forms/ProfileEditForm"; import { useModals } from "@/modules/modals"; +import { languageProfileKey } from "@/pages/Settings/keys"; +import { useFormActions } from "@/pages/Settings/utilities/FormValues"; import { BuildKey, useArrayAction } from "@/utilities"; -import { faTrash, faWrench } from "@fortawesome/free-solid-svg-icons"; -import { Badge, Button, Group } from "@mantine/core"; -import { cloneDeep } from "lodash"; -import { FunctionComponent, useCallback, useMemo } from "react"; -import { Column } from "react-table"; import { useLatestEnabledLanguages, useLatestProfiles } from "."; -import { languageProfileKey } from "../keys"; -import { useFormActions } from "../utilities/FormValues"; const Table: FunctionComponent = () => { const profiles = useLatestProfiles(); diff --git a/frontend/src/pages/Settings/Notifications/components.tsx b/frontend/src/pages/Settings/Notifications/components.tsx index cde3f3268..7ee5f5a26 100644 --- a/frontend/src/pages/Settings/Notifications/components.tsx +++ b/frontend/src/pages/Settings/Notifications/components.tsx @@ -1,9 +1,5 @@ -import api from "@/apis/raw"; -import { Selector } from "@/components"; -import MutateButton from "@/components/async/MutateButton"; -import { useModals, withModal } from "@/modules/modals"; -import { BuildKey, useSelectorOptions } from "@/utilities"; -import FormUtils from "@/utilities/form"; +import { FunctionComponent, useCallback, useMemo } from "react"; +import { useMutation } from "react-query"; import { Button, Divider, @@ -14,11 +10,18 @@ import { } from "@mantine/core"; import { useForm } from "@mantine/form"; import { isObject } from "lodash"; -import { FunctionComponent, useCallback, useMemo } from "react"; -import { useMutation } from "react-query"; -import { Card } from "../components"; -import { notificationsKey } from "../keys"; -import { useSettingValue, useUpdateArray } from "../utilities/hooks"; +import api from "@/apis/raw"; +import { Selector } from "@/components"; +import MutateButton from "@/components/async/MutateButton"; +import { useModals, withModal } from "@/modules/modals"; +import { Card } from "@/pages/Settings/components"; +import { notificationsKey } from "@/pages/Settings/keys"; +import { + useSettingValue, + useUpdateArray, +} from "@/pages/Settings/utilities/hooks"; +import { BuildKey, useSelectorOptions } from "@/utilities"; +import FormUtils from "@/utilities/form"; const notificationHook = (notifications: Settings.NotificationInfo[]) => { return notifications.map((info) => JSON.stringify(info)); diff --git a/frontend/src/pages/Settings/Notifications/index.tsx b/frontend/src/pages/Settings/Notifications/index.tsx index f764bbd61..bb116ada4 100644 --- a/frontend/src/pages/Settings/Notifications/index.tsx +++ b/frontend/src/pages/Settings/Notifications/index.tsx @@ -1,6 +1,6 @@ -import { Anchor, Blockquote, Text } from "@mantine/core"; import { FunctionComponent } from "react"; -import { Check, Layout, Message, Section } from "../components"; +import { Anchor, Blockquote, Text } from "@mantine/core"; +import { Check, Layout, Message, Section } from "@/pages/Settings/components"; import { NotificationView } from "./components"; const SettingsNotificationsView: FunctionComponent = () => { diff --git a/frontend/src/pages/Settings/Providers/components.tsx b/frontend/src/pages/Settings/Providers/components.tsx index 803550ce5..72e2c3b1f 100644 --- a/frontend/src/pages/Settings/Providers/components.tsx +++ b/frontend/src/pages/Settings/Providers/components.tsx @@ -1,44 +1,47 @@ -import { Selector } from "@/components"; -import { useModals, withModal } from "@/modules/modals"; -import { BuildKey, useSelectorOptions } from "@/utilities"; -import { ASSERT } from "@/utilities/console"; import { + FunctionComponent, + useCallback, + useMemo, + useRef, + useState, +} from "react"; +import { + AutocompleteProps, Button, Divider, Group, - Text as MantineText, SimpleGrid, Stack, - AutocompleteProps, + Text as MantineText, } from "@mantine/core"; import { useForm } from "@mantine/form"; import { capitalize } from "lodash"; -import { - FunctionComponent, - useCallback, - useMemo, - useRef, - useState, -} from "react"; +import { Selector } from "@/components"; +import { useModals, withModal } from "@/modules/modals"; import { Card, Check, Chips, - Selector as GlobalSelector, Message, Password, ProviderTestButton, + Selector as GlobalSelector, Text, -} from "../components"; +} from "@/pages/Settings/components"; import { FormContext, FormValues, runHooks, useFormActions, useStagedValues, -} from "../utilities/FormValues"; -import { SettingsProvider, useSettings } from "../utilities/SettingsProvider"; -import { useSettingValue } from "../utilities/hooks"; +} from "@/pages/Settings/utilities/FormValues"; +import { useSettingValue } from "@/pages/Settings/utilities/hooks"; +import { + SettingsProvider, + useSettings, +} from "@/pages/Settings/utilities/SettingsProvider"; +import { BuildKey, useSelectorOptions } from "@/utilities"; +import { ASSERT } from "@/utilities/console"; import { ProviderInfo } from "./list"; type SettingsKey = diff --git a/frontend/src/pages/Settings/Providers/index.tsx b/frontend/src/pages/Settings/Providers/index.tsx index ce855c4ee..a179ecda3 100644 --- a/frontend/src/pages/Settings/Providers/index.tsx +++ b/frontend/src/pages/Settings/Providers/index.tsx @@ -1,6 +1,5 @@ -import { antiCaptchaOption } from "@/pages/Settings/Providers/options"; -import { Anchor } from "@mantine/core"; import { FunctionComponent } from "react"; +import { Anchor } from "@mantine/core"; import { CollapseBox, Layout, @@ -9,7 +8,8 @@ import { Section, Selector, Text, -} from "../components"; +} from "@/pages/Settings/components"; +import { antiCaptchaOption } from "@/pages/Settings/Providers/options"; import { ProviderView } from "./components"; import { IntegrationList, ProviderList } from "./list"; diff --git a/frontend/src/pages/Settings/Providers/list.ts b/frontend/src/pages/Settings/Providers/list.ts index bb3f4e5a5..454831bae 100644 --- a/frontend/src/pages/Settings/Providers/list.ts +++ b/frontend/src/pages/Settings/Providers/list.ts @@ -1,5 +1,5 @@ -import { SelectorOption } from "@/components"; import { ReactText } from "react"; +import { SelectorOption } from "@/components"; type Input = { type: N; diff --git a/frontend/src/pages/Settings/Radarr/index.tsx b/frontend/src/pages/Settings/Radarr/index.tsx index 8805aeed8..b2e858178 100644 --- a/frontend/src/pages/Settings/Radarr/index.tsx +++ b/frontend/src/pages/Settings/Radarr/index.tsx @@ -1,5 +1,5 @@ -import { Code } from "@mantine/core"; import { FunctionComponent } from "react"; +import { Code } from "@mantine/core"; import { Check, Chips, @@ -13,8 +13,8 @@ import { Slider, Text, URLTestButton, -} from "../components"; -import { moviesEnabledKey } from "../keys"; +} from "@/pages/Settings/components"; +import { moviesEnabledKey } from "@/pages/Settings/keys"; import { timeoutOptions } from "./options"; const SettingsRadarrView: FunctionComponent = () => { diff --git a/frontend/src/pages/Settings/Scheduler/index.tsx b/frontend/src/pages/Settings/Scheduler/index.tsx index a6cd2ca74..df88725b2 100644 --- a/frontend/src/pages/Settings/Scheduler/index.tsx +++ b/frontend/src/pages/Settings/Scheduler/index.tsx @@ -1,5 +1,5 @@ -import { SelectorOption } from "@/components"; import { FunctionComponent, useMemo } from "react"; +import { SelectorOption } from "@/components"; import { Check, CollapseBox, @@ -7,7 +7,7 @@ import { Message, Section, Selector, -} from "../components"; +} from "@/pages/Settings/components"; import { backupOptions, dayOptions, diff --git a/frontend/src/pages/Settings/Sonarr/index.tsx b/frontend/src/pages/Settings/Sonarr/index.tsx index 0f60d70a8..ed66ef679 100644 --- a/frontend/src/pages/Settings/Sonarr/index.tsx +++ b/frontend/src/pages/Settings/Sonarr/index.tsx @@ -1,5 +1,5 @@ -import { Code } from "@mantine/core"; import { FunctionComponent } from "react"; +import { Code } from "@mantine/core"; import { Check, Chips, @@ -14,9 +14,9 @@ import { Slider, Text, URLTestButton, -} from "../components"; -import { seriesEnabledKey } from "../keys"; -import { seriesTypeOptions } from "../options"; +} from "@/pages/Settings/components"; +import { seriesEnabledKey } from "@/pages/Settings/keys"; +import { seriesTypeOptions } from "@/pages/Settings/options"; import { timeoutOptions } from "./options"; const SettingsSonarrView: FunctionComponent = () => { diff --git a/frontend/src/pages/Settings/Subtitles/index.tsx b/frontend/src/pages/Settings/Subtitles/index.tsx index c4dffd227..a2250e5a9 100644 --- a/frontend/src/pages/Settings/Subtitles/index.tsx +++ b/frontend/src/pages/Settings/Subtitles/index.tsx @@ -1,5 +1,5 @@ -import { Code, Space, Table } from "@mantine/core"; import { FunctionComponent } from "react"; +import { Code, Space, Table } from "@mantine/core"; import { Check, CollapseBox, @@ -10,11 +10,11 @@ import { Selector, Slider, Text, -} from "../components"; +} from "@/pages/Settings/components"; import { SubzeroColorModification, SubzeroModification, -} from "../utilities/modifications"; +} from "@/pages/Settings/utilities/modifications"; import { adaptiveSearchingDelayOption, adaptiveSearchingDeltaOption, diff --git a/frontend/src/pages/Settings/Subtitles/options.ts b/frontend/src/pages/Settings/Subtitles/options.ts index 75fc4b027..b14d88f44 100644 --- a/frontend/src/pages/Settings/Subtitles/options.ts +++ b/frontend/src/pages/Settings/Subtitles/options.ts @@ -1,5 +1,5 @@ import { SelectorOption } from "@/components"; -import { ProviderList } from "../Providers/list"; +import { ProviderList } from "@/pages/Settings/Providers/list"; export const hiExtensionOptions: SelectorOption[] = [ { diff --git a/frontend/src/pages/Settings/UI/index.tsx b/frontend/src/pages/Settings/UI/index.tsx index c7b6ada1b..a4410f0ba 100644 --- a/frontend/src/pages/Settings/UI/index.tsx +++ b/frontend/src/pages/Settings/UI/index.tsx @@ -1,6 +1,6 @@ -import { uiPageSizeKey } from "@/utilities/storage"; import { FunctionComponent } from "react"; -import { Layout, Section, Selector } from "../components"; +import { Layout, Section, Selector } from "@/pages/Settings/components"; +import { uiPageSizeKey } from "@/utilities/storage"; import { colorSchemeOptions, pageSizeOptions } from "./options"; const SettingsUIView: FunctionComponent = () => { diff --git a/frontend/src/pages/Settings/components/Card.tsx b/frontend/src/pages/Settings/components/Card.tsx index 6e4b58f47..69df15636 100644 --- a/frontend/src/pages/Settings/components/Card.tsx +++ b/frontend/src/pages/Settings/components/Card.tsx @@ -1,7 +1,7 @@ +import { FunctionComponent } from "react"; +import { Center, Stack, Text, UnstyledButton } from "@mantine/core"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Center, Stack, Text, UnstyledButton } from "@mantine/core"; -import { FunctionComponent } from "react"; import styles from "./Card.module.scss"; interface CardProps { diff --git a/frontend/src/pages/Settings/components/Layout.test.tsx b/frontend/src/pages/Settings/components/Layout.test.tsx index 512d0310c..a890bc277 100644 --- a/frontend/src/pages/Settings/components/Layout.test.tsx +++ b/frontend/src/pages/Settings/components/Layout.test.tsx @@ -1,6 +1,6 @@ -import { render, screen } from "@/tests"; import { Text } from "@mantine/core"; import { describe, it } from "vitest"; +import { render, screen } from "@/tests"; import Layout from "./Layout"; describe("Settings layout", () => { diff --git a/frontend/src/pages/Settings/components/Layout.tsx b/frontend/src/pages/Settings/components/Layout.tsx index 5fb6dbbed..c2f8c3c35 100644 --- a/frontend/src/pages/Settings/components/Layout.tsx +++ b/frontend/src/pages/Settings/components/Layout.tsx @@ -1,16 +1,20 @@ +import { FunctionComponent, ReactNode, useCallback, useMemo } from "react"; +import { Badge, Container, Group, LoadingOverlay } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faSave } from "@fortawesome/free-solid-svg-icons"; import { useSettingsMutation, useSystemSettings } from "@/apis/hooks"; import { Toolbox } from "@/components"; import { LoadingProvider } from "@/contexts"; +import { + FormContext, + FormValues, + runHooks, +} from "@/pages/Settings/utilities/FormValues"; +import { SettingsProvider } from "@/pages/Settings/utilities/SettingsProvider"; import { useOnValueChange } from "@/utilities"; import { LOG } from "@/utilities/console"; import { usePrompt } from "@/utilities/routers"; -import { faSave } from "@fortawesome/free-solid-svg-icons"; -import { Badge, Container, Group, LoadingOverlay } from "@mantine/core"; -import { useForm } from "@mantine/form"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, ReactNode, useCallback, useMemo } from "react"; -import { FormContext, FormValues, runHooks } from "../utilities/FormValues"; -import { SettingsProvider } from "../utilities/SettingsProvider"; interface Props { name: string; diff --git a/frontend/src/pages/Settings/components/LayoutModal.tsx b/frontend/src/pages/Settings/components/LayoutModal.tsx index 6150295e4..532f6b6ba 100644 --- a/frontend/src/pages/Settings/components/LayoutModal.tsx +++ b/frontend/src/pages/Settings/components/LayoutModal.tsx @@ -1,7 +1,4 @@ -import { useSettingsMutation, useSystemSettings } from "@/apis/hooks"; -import { LoadingProvider } from "@/contexts"; -import { useOnValueChange } from "@/utilities"; -import { LOG } from "@/utilities/console"; +import { FunctionComponent, ReactNode, useCallback, useMemo } from "react"; import { Button, Container, @@ -11,9 +8,16 @@ import { Space, } from "@mantine/core"; import { useForm } from "@mantine/form"; -import { FunctionComponent, ReactNode, useCallback, useMemo } from "react"; -import { FormContext, FormValues, runHooks } from "../utilities/FormValues"; -import { SettingsProvider } from "../utilities/SettingsProvider"; +import { useSettingsMutation, useSystemSettings } from "@/apis/hooks"; +import { LoadingProvider } from "@/contexts"; +import { + FormContext, + FormValues, + runHooks, +} from "@/pages/Settings/utilities/FormValues"; +import { SettingsProvider } from "@/pages/Settings/utilities/SettingsProvider"; +import { useOnValueChange } from "@/utilities"; +import { LOG } from "@/utilities/console"; interface Props { children: ReactNode; diff --git a/frontend/src/pages/Settings/components/Message.tsx b/frontend/src/pages/Settings/components/Message.tsx index eac84131b..67f519485 100644 --- a/frontend/src/pages/Settings/components/Message.tsx +++ b/frontend/src/pages/Settings/components/Message.tsx @@ -1,5 +1,5 @@ -import { Text } from "@mantine/core"; import { FunctionComponent, PropsWithChildren } from "react"; +import { Text } from "@mantine/core"; interface MessageProps { type?: "warning" | "info"; diff --git a/frontend/src/pages/Settings/components/Section.test.tsx b/frontend/src/pages/Settings/components/Section.test.tsx index 850a47671..535bd8be2 100644 --- a/frontend/src/pages/Settings/components/Section.test.tsx +++ b/frontend/src/pages/Settings/components/Section.test.tsx @@ -1,6 +1,6 @@ -import { render, screen } from "@/tests"; import { Text } from "@mantine/core"; import { describe, it } from "vitest"; +import { render, screen } from "@/tests"; import { Section } from "./Section"; describe("Settings section", () => { diff --git a/frontend/src/pages/Settings/components/Section.tsx b/frontend/src/pages/Settings/components/Section.tsx index 7c5727bf0..1e6a2e0b8 100644 --- a/frontend/src/pages/Settings/components/Section.tsx +++ b/frontend/src/pages/Settings/components/Section.tsx @@ -1,5 +1,5 @@ -import { Divider, Stack, Title } from "@mantine/core"; import { FunctionComponent, PropsWithChildren } from "react"; +import { Divider, Stack, Title } from "@mantine/core"; interface SectionProps { header: string; diff --git a/frontend/src/pages/Settings/components/collapse.tsx b/frontend/src/pages/Settings/components/collapse.tsx index c598105bd..d502ecc69 100644 --- a/frontend/src/pages/Settings/components/collapse.tsx +++ b/frontend/src/pages/Settings/components/collapse.tsx @@ -1,6 +1,6 @@ -import { Collapse, Stack } from "@mantine/core"; import { FunctionComponent, PropsWithChildren, useMemo, useRef } from "react"; -import { useSettingValue } from "../utilities/hooks"; +import { Collapse, Stack } from "@mantine/core"; +import { useSettingValue } from "@/pages/Settings/utilities/hooks"; interface ContentProps { settingKey: string; diff --git a/frontend/src/pages/Settings/components/forms.test.tsx b/frontend/src/pages/Settings/components/forms.test.tsx index 26974bad9..a88d2bec7 100644 --- a/frontend/src/pages/Settings/components/forms.test.tsx +++ b/frontend/src/pages/Settings/components/forms.test.tsx @@ -1,8 +1,8 @@ -import { render, RenderOptions, screen } from "@/tests"; -import { useForm } from "@mantine/form"; import { FunctionComponent, PropsWithChildren, ReactElement } from "react"; +import { useForm } from "@mantine/form"; import { describe, it } from "vitest"; -import { FormContext, FormValues } from "../utilities/FormValues"; +import { FormContext, FormValues } from "@/pages/Settings/utilities/FormValues"; +import { render, RenderOptions, screen } from "@/tests"; import { Number, Text } from "./forms"; const FormSupport: FunctionComponent = ({ children }) => { diff --git a/frontend/src/pages/Settings/components/forms.tsx b/frontend/src/pages/Settings/components/forms.tsx index 1d65b0375..95134db92 100644 --- a/frontend/src/pages/Settings/components/forms.tsx +++ b/frontend/src/pages/Settings/components/forms.tsx @@ -1,7 +1,20 @@ +import { FunctionComponent, ReactNode, ReactText } from "react"; +import { + Input, + NumberInput, + NumberInputProps, + PasswordInput, + PasswordInputProps, + Slider as MantineSlider, + SliderProps as MantineSliderProps, + Switch, + TextInput, + TextInputProps, +} from "@mantine/core"; import { + Action as GlobalAction, FileBrowser, FileBrowserProps, - Action as GlobalAction, MultiSelector as GlobalMultiSelector, MultiSelectorProps as GlobalMultiSelectorProps, Selector as GlobalSelector, @@ -9,21 +22,8 @@ import { } from "@/components"; import { ActionProps as GlobalActionProps } from "@/components/inputs/Action"; import ChipInput, { ChipInputProps } from "@/components/inputs/ChipInput"; +import { BaseInput, useBaseInput } from "@/pages/Settings/utilities/hooks"; import { useSliderMarks } from "@/utilities"; -import { - Input, - Slider as MantineSlider, - SliderProps as MantineSliderProps, - NumberInput, - NumberInputProps, - PasswordInput, - PasswordInputProps, - Switch, - TextInput, - TextInputProps, -} from "@mantine/core"; -import { FunctionComponent, ReactNode, ReactText } from "react"; -import { BaseInput, useBaseInput } from "../utilities/hooks"; export type NumberProps = BaseInput & NumberInputProps; diff --git a/frontend/src/pages/Settings/components/index.tsx b/frontend/src/pages/Settings/components/index.tsx index 6ac9cb86c..5e7882bbc 100644 --- a/frontend/src/pages/Settings/components/index.tsx +++ b/frontend/src/pages/Settings/components/index.tsx @@ -1,7 +1,7 @@ -import api from "@/apis/raw"; -import { Button } from "@mantine/core"; import { FunctionComponent, useCallback, useEffect, useState } from "react"; -import { useSettingValue } from "../utilities/hooks"; +import { Button } from "@mantine/core"; +import api from "@/apis/raw"; +import { useSettingValue } from "@/pages/Settings/utilities/hooks"; export const URLTestButton: FunctionComponent<{ category: "sonarr" | "radarr"; diff --git a/frontend/src/pages/Settings/components/pathMapper.tsx b/frontend/src/pages/Settings/components/pathMapper.tsx index 38fbb27e9..cc525402a 100644 --- a/frontend/src/pages/Settings/components/pathMapper.tsx +++ b/frontend/src/pages/Settings/components/pathMapper.tsx @@ -1,19 +1,19 @@ -import { Action, FileBrowser, SimpleTable } from "@/components"; -import { useArrayAction } from "@/utilities"; +import { FunctionComponent, useCallback, useMemo } from "react"; +import { Column } from "react-table"; +import { Button } from "@mantine/core"; import { faArrowCircleRight, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Button } from "@mantine/core"; import { capitalize } from "lodash"; -import { FunctionComponent, useCallback, useMemo } from "react"; -import { Column } from "react-table"; +import { Action, FileBrowser, SimpleTable } from "@/components"; import { moviesEnabledKey, pathMappingsKey, pathMappingsMovieKey, seriesEnabledKey, -} from "../keys"; -import { useFormActions } from "../utilities/FormValues"; -import { useSettingValue } from "../utilities/hooks"; +} from "@/pages/Settings/keys"; +import { useFormActions } from "@/pages/Settings/utilities/FormValues"; +import { useSettingValue } from "@/pages/Settings/utilities/hooks"; +import { useArrayAction } from "@/utilities"; import { Message } from "./Message"; type SupportType = "sonarr" | "radarr"; diff --git a/frontend/src/pages/Settings/utilities/FormValues.ts b/frontend/src/pages/Settings/utilities/FormValues.ts index d5d1774f5..32e6af226 100644 --- a/frontend/src/pages/Settings/utilities/FormValues.ts +++ b/frontend/src/pages/Settings/utilities/FormValues.ts @@ -1,6 +1,6 @@ -import { LOG } from "@/utilities/console"; -import type { UseFormReturnType } from "@mantine/form"; import { createContext, useCallback, useContext, useRef } from "react"; +import type { UseFormReturnType } from "@mantine/form"; +import { LOG } from "@/utilities/console"; export const FormContext = createContext | null>( null, diff --git a/frontend/src/pages/Settings/utilities/hooks.ts b/frontend/src/pages/Settings/utilities/hooks.ts index da874314e..00c8b9bef 100644 --- a/frontend/src/pages/Settings/utilities/hooks.ts +++ b/frontend/src/pages/Settings/utilities/hooks.ts @@ -1,12 +1,12 @@ -import { LOG } from "@/utilities/console"; -import { get, isNull, isUndefined, uniqBy } from "lodash"; import { useCallback, useMemo, useRef } from "react"; +import { get, isNull, isUndefined, uniqBy } from "lodash"; import { HookType, useFormActions, useStagedValues, -} from "../utilities/FormValues"; -import { useSettings } from "../utilities/SettingsProvider"; +} from "@/pages/Settings/utilities/FormValues"; +import { useSettings } from "@/pages/Settings/utilities/SettingsProvider"; +import { LOG } from "@/utilities/console"; export interface BaseInput { disabled?: boolean; diff --git a/frontend/src/pages/System/Announcements/index.tsx b/frontend/src/pages/System/Announcements/index.tsx index 4e204431e..de9cdea3b 100644 --- a/frontend/src/pages/System/Announcements/index.tsx +++ b/frontend/src/pages/System/Announcements/index.tsx @@ -1,8 +1,8 @@ -import { useSystemAnnouncements } from "@/apis/hooks"; -import { QueryOverlay } from "@/components/async"; +import { FunctionComponent } from "react"; import { Container } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; +import { useSystemAnnouncements } from "@/apis/hooks"; +import { QueryOverlay } from "@/components/async"; import Table from "./table"; const SystemAnnouncementsView: FunctionComponent = () => { diff --git a/frontend/src/pages/System/Announcements/table.tsx b/frontend/src/pages/System/Announcements/table.tsx index eb9b6e43c..7c2ddf127 100644 --- a/frontend/src/pages/System/Announcements/table.tsx +++ b/frontend/src/pages/System/Announcements/table.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { Anchor, Text } from "@mantine/core"; +import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; import { useSystemAnnouncementsAddDismiss } from "@/apis/hooks"; import { SimpleTable } from "@/components"; import { MutateAction } from "@/components/async"; -import { faWindowClose } from "@fortawesome/free-solid-svg-icons"; -import { Anchor, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; interface Props { announcements: readonly System.Announcements[]; diff --git a/frontend/src/pages/System/Backups/index.tsx b/frontend/src/pages/System/Backups/index.tsx index 0a19f2a9a..e4e43b425 100644 --- a/frontend/src/pages/System/Backups/index.tsx +++ b/frontend/src/pages/System/Backups/index.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent } from "react"; +import { Container } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faFileArchive } from "@fortawesome/free-solid-svg-icons"; import { useCreateBackups, useSystemBackups } from "@/apis/hooks"; import { Toolbox } from "@/components"; import { QueryOverlay } from "@/components/async"; -import { faFileArchive } from "@fortawesome/free-solid-svg-icons"; -import { Container } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; import Table from "./table"; const SystemBackupsView: FunctionComponent = () => { diff --git a/frontend/src/pages/System/Backups/table.tsx b/frontend/src/pages/System/Backups/table.tsx index 42236cee5..7076e44b6 100644 --- a/frontend/src/pages/System/Backups/table.tsx +++ b/frontend/src/pages/System/Backups/table.tsx @@ -1,11 +1,11 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; +import { Anchor, Text } from "@mantine/core"; +import { faHistory, faTrash } from "@fortawesome/free-solid-svg-icons"; import { useDeleteBackups, useRestoreBackups } from "@/apis/hooks"; import { Action, PageTable } from "@/components"; import { useModals } from "@/modules/modals"; import { Environment } from "@/utilities"; -import { faHistory, faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Anchor, Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; interface Props { backups: readonly System.Backups[]; diff --git a/frontend/src/pages/System/Logs/index.tsx b/frontend/src/pages/System/Logs/index.tsx index a232b8069..b70389459 100644 --- a/frontend/src/pages/System/Logs/index.tsx +++ b/frontend/src/pages/System/Logs/index.tsx @@ -1,18 +1,18 @@ -import { useDeleteLogs, useSystemLogs, useSystemSettings } from "@/apis/hooks"; -import { Toolbox } from "@/components"; -import { QueryOverlay } from "@/components/async"; -import { Check, LayoutModal, Message, Text } from "@/pages/Settings/components"; -import { Environment } from "@/utilities"; +import { FunctionComponent, useCallback } from "react"; +import { Badge, Container, Group, Stack } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { useModals } from "@mantine/modals"; import { faDownload, faFilter, faSync, faTrash, } from "@fortawesome/free-solid-svg-icons"; -import { Badge, Container, Group, Stack } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { useModals } from "@mantine/modals"; -import { FunctionComponent, useCallback } from "react"; +import { useDeleteLogs, useSystemLogs, useSystemSettings } from "@/apis/hooks"; +import { Toolbox } from "@/components"; +import { QueryOverlay } from "@/components/async"; +import { Check, LayoutModal, Message, Text } from "@/pages/Settings/components"; +import { Environment } from "@/utilities"; import Table from "./table"; const SystemLogsView: FunctionComponent = () => { diff --git a/frontend/src/pages/System/Logs/modal.tsx b/frontend/src/pages/System/Logs/modal.tsx index 297909757..efd687ac0 100644 --- a/frontend/src/pages/System/Logs/modal.tsx +++ b/frontend/src/pages/System/Logs/modal.tsx @@ -1,6 +1,6 @@ -import { withModal } from "@/modules/modals"; -import { Code, Text } from "@mantine/core"; import { FunctionComponent, useMemo } from "react"; +import { Code, Text } from "@mantine/core"; +import { withModal } from "@/modules/modals"; interface Props { stack: string; diff --git a/frontend/src/pages/System/Logs/table.tsx b/frontend/src/pages/System/Logs/table.tsx index 5a36f0f2b..541a8e285 100644 --- a/frontend/src/pages/System/Logs/table.tsx +++ b/frontend/src/pages/System/Logs/table.tsx @@ -1,5 +1,5 @@ -import { Action, PageTable } from "@/components"; -import { useModals } from "@/modules/modals"; +import { FunctionComponent, useMemo } from "react"; +import { Column } from "react-table"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { faBug, @@ -10,8 +10,8 @@ import { faQuestion, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; +import { Action, PageTable } from "@/components"; +import { useModals } from "@/modules/modals"; import SystemLogModal from "./modal"; interface Props { diff --git a/frontend/src/pages/System/Providers/index.tsx b/frontend/src/pages/System/Providers/index.tsx index cd7086221..cd4a52cfd 100644 --- a/frontend/src/pages/System/Providers/index.tsx +++ b/frontend/src/pages/System/Providers/index.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent } from "react"; +import { Container, Group } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faSync, faTrash } from "@fortawesome/free-solid-svg-icons"; import { useResetProvider, useSystemProviders } from "@/apis/hooks"; import { Toolbox } from "@/components"; import { QueryOverlay } from "@/components/async"; -import { faSync, faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Container, Group } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; import Table from "./table"; const SystemProvidersView: FunctionComponent = () => { diff --git a/frontend/src/pages/System/Providers/table.tsx b/frontend/src/pages/System/Providers/table.tsx index 961da65fb..0f9856d99 100644 --- a/frontend/src/pages/System/Providers/table.tsx +++ b/frontend/src/pages/System/Providers/table.tsx @@ -1,6 +1,6 @@ -import { SimpleTable } from "@/components"; import { FunctionComponent, useMemo } from "react"; import { Column } from "react-table"; +import { SimpleTable } from "@/components"; interface Props { providers: readonly System.Provider[]; diff --git a/frontend/src/pages/System/Releases/index.tsx b/frontend/src/pages/System/Releases/index.tsx index 66b5a1c8a..291607a6a 100644 --- a/frontend/src/pages/System/Releases/index.tsx +++ b/frontend/src/pages/System/Releases/index.tsx @@ -1,6 +1,4 @@ -import { useSystemReleases } from "@/apis/hooks"; -import { QueryOverlay } from "@/components/async"; -import { BuildKey } from "@/utilities"; +import { FunctionComponent, useMemo } from "react"; import { Badge, Card, @@ -12,7 +10,9 @@ import { Text, } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent, useMemo } from "react"; +import { useSystemReleases } from "@/apis/hooks"; +import { QueryOverlay } from "@/components/async"; +import { BuildKey } from "@/utilities"; const SystemReleasesView: FunctionComponent = () => { const releases = useSystemReleases(); diff --git a/frontend/src/pages/System/Status/index.tsx b/frontend/src/pages/System/Status/index.tsx index 05996f7ad..bcd0e175d 100644 --- a/frontend/src/pages/System/Status/index.tsx +++ b/frontend/src/pages/System/Status/index.tsx @@ -1,15 +1,10 @@ -import { useSystemHealth, useSystemStatus } from "@/apis/hooks"; -import { QueryOverlay } from "@/components/async"; -import { GithubRepoRoot } from "@/constants"; -import { Environment, useInterval } from "@/utilities"; -import { IconDefinition } from "@fortawesome/fontawesome-common-types"; import { - faDiscord, - faGithub, - faWikipediaW, -} from "@fortawesome/free-brands-svg-icons"; -import { faCode, faPaperPlane } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + FunctionComponent, + PropsWithChildren, + ReactNode, + useCallback, + useState, +} from "react"; import { Anchor, Container, @@ -20,13 +15,18 @@ import { Text, } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; +import { IconDefinition } from "@fortawesome/fontawesome-common-types"; import { - FunctionComponent, - PropsWithChildren, - ReactNode, - useCallback, - useState, -} from "react"; + faDiscord, + faGithub, + faWikipediaW, +} from "@fortawesome/free-brands-svg-icons"; +import { faCode, faPaperPlane } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useSystemHealth, useSystemStatus } from "@/apis/hooks"; +import { QueryOverlay } from "@/components/async"; +import { GithubRepoRoot } from "@/constants"; +import { Environment, useInterval } from "@/utilities"; import { divisorDay, divisorHour, diff --git a/frontend/src/pages/System/Status/table.tsx b/frontend/src/pages/System/Status/table.tsx index c139f9d93..a22f4e435 100644 --- a/frontend/src/pages/System/Status/table.tsx +++ b/frontend/src/pages/System/Status/table.tsx @@ -1,7 +1,7 @@ -import { SimpleTable } from "@/components"; -import { Text } from "@mantine/core"; import { FunctionComponent, useMemo } from "react"; import { Column } from "react-table"; +import { Text } from "@mantine/core"; +import { SimpleTable } from "@/components"; interface Props { health: readonly System.Health[]; diff --git a/frontend/src/pages/System/Tasks/index.tsx b/frontend/src/pages/System/Tasks/index.tsx index 17e429152..b384ea460 100644 --- a/frontend/src/pages/System/Tasks/index.tsx +++ b/frontend/src/pages/System/Tasks/index.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent } from "react"; +import { Container } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faSync } from "@fortawesome/free-solid-svg-icons"; import { useSystemTasks } from "@/apis/hooks"; import { Toolbox } from "@/components"; import { QueryOverlay } from "@/components/async"; -import { faSync } from "@fortawesome/free-solid-svg-icons"; -import { Container } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { FunctionComponent } from "react"; import Table from "./table"; const SystemTasksView: FunctionComponent = () => { diff --git a/frontend/src/pages/System/Tasks/table.tsx b/frontend/src/pages/System/Tasks/table.tsx index 064438668..548cc7b70 100644 --- a/frontend/src/pages/System/Tasks/table.tsx +++ b/frontend/src/pages/System/Tasks/table.tsx @@ -1,10 +1,10 @@ +import { FunctionComponent, useMemo } from "react"; +import { Column, useSortBy } from "react-table"; +import { Text } from "@mantine/core"; +import { faPlay } from "@fortawesome/free-solid-svg-icons"; import { useRunTask } from "@/apis/hooks"; import { SimpleTable } from "@/components"; import MutateAction from "@/components/async/MutateAction"; -import { faPlay } from "@fortawesome/free-solid-svg-icons"; -import { Text } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Column, useSortBy } from "react-table"; interface Props { tasks: readonly System.Task[]; diff --git a/frontend/src/pages/Wanted/Movies/index.tsx b/frontend/src/pages/Wanted/Movies/index.tsx index d62871416..e42b6a6dc 100644 --- a/frontend/src/pages/Wanted/Movies/index.tsx +++ b/frontend/src/pages/Wanted/Movies/index.tsx @@ -1,18 +1,18 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Badge, Group } from "@mantine/core"; +import { faSearch } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useMovieAction, useMovieSubtitleModification, useMovieWantedPagination, } from "@/apis/hooks"; import Language from "@/components/bazarr/Language"; -import { TaskGroup, task } from "@/modules/task"; +import { task, TaskGroup } from "@/modules/task"; import WantedView from "@/pages/views/WantedView"; import { BuildKey } from "@/utilities"; -import { faSearch } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Badge, Group } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const WantedMoviesView: FunctionComponent = () => { const columns: Column[] = useMemo[]>( diff --git a/frontend/src/pages/Wanted/Series/index.tsx b/frontend/src/pages/Wanted/Series/index.tsx index d5f4d8993..cc9a22f6e 100644 --- a/frontend/src/pages/Wanted/Series/index.tsx +++ b/frontend/src/pages/Wanted/Series/index.tsx @@ -1,18 +1,18 @@ +import { FunctionComponent, useMemo } from "react"; +import { Link } from "react-router-dom"; +import { Column } from "react-table"; +import { Anchor, Badge, Group } from "@mantine/core"; +import { faSearch } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useEpisodeSubtitleModification, useEpisodeWantedPagination, useSeriesAction, } from "@/apis/hooks"; import Language from "@/components/bazarr/Language"; -import { TaskGroup, task } from "@/modules/task"; +import { task, TaskGroup } from "@/modules/task"; import WantedView from "@/pages/views/WantedView"; import { BuildKey } from "@/utilities"; -import { faSearch } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Anchor, Badge, Group } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; -import { Link } from "react-router-dom"; -import { Column } from "react-table"; const WantedSeriesView: FunctionComponent = () => { const columns: Column[] = useMemo[]>( diff --git a/frontend/src/pages/errors/CriticalError.tsx b/frontend/src/pages/errors/CriticalError.tsx index 2c8d0202b..22070c2a7 100644 --- a/frontend/src/pages/errors/CriticalError.tsx +++ b/frontend/src/pages/errors/CriticalError.tsx @@ -1,8 +1,8 @@ -import { Reload } from "@/utilities"; +import { FunctionComponent } from "react"; +import { Alert, Container, Text } from "@mantine/core"; import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Alert, Container, Text } from "@mantine/core"; -import { FunctionComponent } from "react"; +import { Reload } from "@/utilities"; interface Props { message: string; diff --git a/frontend/src/pages/errors/NotFound.tsx b/frontend/src/pages/errors/NotFound.tsx index d81c31d7f..da4ba8229 100644 --- a/frontend/src/pages/errors/NotFound.tsx +++ b/frontend/src/pages/errors/NotFound.tsx @@ -1,7 +1,7 @@ +import { FunctionComponent } from "react"; +import { Box, Center, Container, Text, Title } from "@mantine/core"; import { faEyeSlash as fasEyeSlash } from "@fortawesome/free-regular-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Box, Center, Container, Text, Title } from "@mantine/core"; -import { FunctionComponent } from "react"; const NotFound: FunctionComponent = () => { return ( diff --git a/frontend/src/pages/errors/UIError.tsx b/frontend/src/pages/errors/UIError.tsx index 55e0d5414..030f6ba11 100644 --- a/frontend/src/pages/errors/UIError.tsx +++ b/frontend/src/pages/errors/UIError.tsx @@ -1,7 +1,4 @@ -import { GithubRepoRoot } from "@/constants"; -import { Reload } from "@/utilities"; -import { faDizzy } from "@fortawesome/free-regular-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent, useMemo } from "react"; import { Anchor, Box, @@ -13,7 +10,10 @@ import { Text, Title, } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; +import { faDizzy } from "@fortawesome/free-regular-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { GithubRepoRoot } from "@/constants"; +import { Reload } from "@/utilities"; const Placeholder = "********"; diff --git a/frontend/src/pages/views/HistoryView.tsx b/frontend/src/pages/views/HistoryView.tsx index 2ecc74afb..3553f58c6 100644 --- a/frontend/src/pages/views/HistoryView.tsx +++ b/frontend/src/pages/views/HistoryView.tsx @@ -1,8 +1,8 @@ -import { UsePaginationQueryResult } from "@/apis/queries/hooks"; -import { QueryPageTable } from "@/components"; +import { Column } from "react-table"; import { Container } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; -import { Column } from "react-table"; +import { UsePaginationQueryResult } from "@/apis/queries/hooks"; +import { QueryPageTable } from "@/components"; interface Props { name: string; diff --git a/frontend/src/pages/views/ItemOverview.tsx b/frontend/src/pages/views/ItemOverview.tsx index a5224b586..e89100f2e 100644 --- a/frontend/src/pages/views/ItemOverview.tsx +++ b/frontend/src/pages/views/ItemOverview.tsx @@ -1,23 +1,4 @@ -import { Language } from "@/components/bazarr"; -import { BuildKey } from "@/utilities"; -import { - useLanguageProfileBy, - useProfileItemsToLanguages, -} from "@/utilities/languages"; -import { - faFolder, - faBookmark as farBookmark, -} from "@fortawesome/free-regular-svg-icons"; -import { - IconDefinition, - faBookmark, - faClone, - faLanguage, - faMusic, - faStream, - faTags, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { FunctionComponent, useMemo } from "react"; import { BackgroundImage, Badge, @@ -32,7 +13,26 @@ import { Text, Title, } from "@mantine/core"; -import { FunctionComponent, useMemo } from "react"; +import { + faBookmark as farBookmark, + faFolder, +} from "@fortawesome/free-regular-svg-icons"; +import { + faBookmark, + faClone, + faLanguage, + faMusic, + faStream, + faTags, + IconDefinition, +} from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Language } from "@/components/bazarr"; +import { BuildKey } from "@/utilities"; +import { + useLanguageProfileBy, + useProfileItemsToLanguages, +} from "@/utilities/languages"; interface Props { item: Item.Base | null; diff --git a/frontend/src/pages/views/ItemView.tsx b/frontend/src/pages/views/ItemView.tsx index 8fdaf83c8..e00d330ee 100644 --- a/frontend/src/pages/views/ItemView.tsx +++ b/frontend/src/pages/views/ItemView.tsx @@ -1,8 +1,8 @@ -import { UsePaginationQueryResult } from "@/apis/queries/hooks"; -import { QueryPageTable, Toolbox } from "@/components"; -import { faList } from "@fortawesome/free-solid-svg-icons"; import { useNavigate } from "react-router-dom"; import { Column } from "react-table"; +import { faList } from "@fortawesome/free-solid-svg-icons"; +import { UsePaginationQueryResult } from "@/apis/queries/hooks"; +import { QueryPageTable, Toolbox } from "@/components"; interface Props { query: UsePaginationQueryResult; diff --git a/frontend/src/pages/views/MassEditor.tsx b/frontend/src/pages/views/MassEditor.tsx index ddab269bd..e2485b39d 100644 --- a/frontend/src/pages/views/MassEditor.tsx +++ b/frontend/src/pages/views/MassEditor.tsx @@ -1,15 +1,15 @@ +import { useCallback, useMemo, useState } from "react"; +import { UseMutationResult } from "react-query"; +import { useNavigate } from "react-router-dom"; +import { Column, useRowSelect } from "react-table"; +import { Box, Container } from "@mantine/core"; +import { faCheck, faUndo } from "@fortawesome/free-solid-svg-icons"; +import { uniqBy } from "lodash"; import { useIsAnyMutationRunning, useLanguageProfiles } from "@/apis/hooks"; import { SimpleTable, Toolbox } from "@/components"; import { Selector, SelectorOption } from "@/components/inputs"; import { useCustomSelection } from "@/components/tables/plugins"; import { GetItemId, useSelectorOptions } from "@/utilities"; -import { faCheck, faUndo } from "@fortawesome/free-solid-svg-icons"; -import { Box, Container } from "@mantine/core"; -import { uniqBy } from "lodash"; -import { useCallback, useMemo, useState } from "react"; -import { UseMutationResult } from "react-query"; -import { useNavigate } from "react-router-dom"; -import { Column, useRowSelect } from "react-table"; interface MassEditorProps { columns: Column[]; diff --git a/frontend/src/pages/views/WantedView.tsx b/frontend/src/pages/views/WantedView.tsx index 5605bf337..aa71775ac 100644 --- a/frontend/src/pages/views/WantedView.tsx +++ b/frontend/src/pages/views/WantedView.tsx @@ -1,10 +1,10 @@ +import { Column } from "react-table"; +import { Container } from "@mantine/core"; +import { useDocumentTitle } from "@mantine/hooks"; +import { faSearch } from "@fortawesome/free-solid-svg-icons"; import { useIsAnyActionRunning } from "@/apis/hooks"; import { UsePaginationQueryResult } from "@/apis/queries/hooks"; import { QueryPageTable, Toolbox } from "@/components"; -import { faSearch } from "@fortawesome/free-solid-svg-icons"; -import { Container } from "@mantine/core"; -import { useDocumentTitle } from "@mantine/hooks"; -import { Column } from "react-table"; interface Props { name: string; diff --git a/frontend/src/providers.tsx b/frontend/src/providers.tsx index aa526c25b..796117529 100644 --- a/frontend/src/providers.tsx +++ b/frontend/src/providers.tsx @@ -1,12 +1,12 @@ -import queryClient from "@/apis/queries"; -import { ModalsProvider } from "@/modules/modals"; -import "@fontsource/roboto/300.css"; -import { Notifications } from "@mantine/notifications"; import { FunctionComponent, PropsWithChildren } from "react"; import { QueryClientProvider } from "react-query"; import { ReactQueryDevtools } from "react-query/devtools"; -import { Environment } from "./utilities"; +import { Notifications } from "@mantine/notifications"; +import queryClient from "@/apis/queries"; import ThemeProvider from "@/App/ThemeProvider"; +import { ModalsProvider } from "@/modules/modals"; +import { Environment } from "./utilities"; +import "@fontsource/roboto/300.css"; export const AllProviders: FunctionComponent = ({ children, diff --git a/frontend/src/tests/index.tsx b/frontend/src/tests/index.tsx index d18df7227..8b4d64c64 100644 --- a/frontend/src/tests/index.tsx +++ b/frontend/src/tests/index.tsx @@ -1,5 +1,3 @@ -import { AllProviders } from "@/providers"; -import { render, RenderOptions } from "@testing-library/react"; import { FunctionComponent, PropsWithChildren, @@ -11,6 +9,8 @@ import { RouteObject, RouterProvider, } from "react-router-dom"; +import { render, RenderOptions } from "@testing-library/react"; +import { AllProviders } from "@/providers"; const AllProvidersWithStrictMode: FunctionComponent = ({ children, diff --git a/frontend/src/tests/setup.ts b/frontend/src/tests/setup.ts index 2b3bf3672..0f6df68ba 100644 --- a/frontend/src/tests/setup.ts +++ b/frontend/src/tests/setup.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-function */ -import "@testing-library/jest-dom"; import { vitest } from "vitest"; +import "@testing-library/jest-dom"; // From https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function Object.defineProperty(window, "matchMedia", { diff --git a/frontend/src/types/react-table.d.ts b/frontend/src/types/react-table.d.ts index 6795b50a3..c05bcd9fd 100644 --- a/frontend/src/types/react-table.d.ts +++ b/frontend/src/types/react-table.d.ts @@ -31,7 +31,7 @@ import { UseSortByOptions, UseSortByState, } from "react-table"; -import {} from "../components/tables/plugins"; +import {} from "@/components/tables/plugins"; declare module "react-table" { // take this file as-is, or comment out the sections that don't apply to your plugin configuration diff --git a/frontend/src/utilities/hooks.ts b/frontend/src/utilities/hooks.ts index 4f703877c..6ae8a2366 100644 --- a/frontend/src/utilities/hooks.ts +++ b/frontend/src/utilities/hooks.ts @@ -1,5 +1,3 @@ -import { SelectorOption, SelectorProps } from "@/components"; -import { SliderProps } from "@mantine/core"; import { Dispatch, useCallback, @@ -9,6 +7,8 @@ import { useState, } from "react"; import { useNavigate } from "react-router-dom"; +import { SliderProps } from "@mantine/core"; +import { SelectorOption, SelectorProps } from "@/components"; export function useGotoHomepage() { const navigate = useNavigate(); diff --git a/frontend/src/utilities/index.ts b/frontend/src/utilities/index.ts index b0555ad31..f8b9d1961 100644 --- a/frontend/src/utilities/index.ts +++ b/frontend/src/utilities/index.ts @@ -1,5 +1,5 @@ -import { difference, differenceWith } from "lodash"; import { Dispatch } from "react"; +import { difference, differenceWith } from "lodash"; import { isEpisode, isMovie, isSeries } from "./validate"; export function toggleState( diff --git a/frontend/src/utilities/languages.ts b/frontend/src/utilities/languages.ts index ca0c5c51a..1b59aa4e7 100644 --- a/frontend/src/utilities/languages.ts +++ b/frontend/src/utilities/languages.ts @@ -1,5 +1,5 @@ -import { useLanguageProfiles, useLanguages } from "@/apis/hooks"; import { useMemo } from "react"; +import { useLanguageProfiles, useLanguages } from "@/apis/hooks"; export function useLanguageProfileBy(id: number | null | undefined) { const { data } = useLanguageProfiles(); diff --git a/frontend/src/utilities/storage.ts b/frontend/src/utilities/storage.ts index c4d50a829..a7c256cab 100644 --- a/frontend/src/utilities/storage.ts +++ b/frontend/src/utilities/storage.ts @@ -1,5 +1,5 @@ -import { useSystemSettings } from "@/apis/hooks"; import { useCallback } from "react"; +import { useSystemSettings } from "@/apis/hooks"; export const uiPageSizeKey = "settings-general-page_size"; diff --git a/frontend/src/utilities/validate.ts b/frontend/src/utilities/validate.ts index 665e5aa61..2b3f028f6 100644 --- a/frontend/src/utilities/validate.ts +++ b/frontend/src/utilities/validate.ts @@ -1,5 +1,5 @@ -import { isNumber, isString } from "lodash"; import { ReactText } from "react"; +import { isNumber, isString } from "lodash"; export function isReactText(v: unknown): v is ReactText { return isString(v) || isNumber(v); -- cgit v1.2.3 From 8beebce2e4db3411e23e7aff59788fcfdbf1753f Mon Sep 17 00:00:00 2001 From: Anderson Shindy Oki Date: Fri, 5 Jul 2024 09:56:13 +0900 Subject: Updated tanstack table to v8.x (#2564) --- frontend/package-lock.json | 62 +-- frontend/package.json | 3 +- frontend/src/components/forms/MovieUploadForm.tsx | 127 ++++--- frontend/src/components/forms/ProfileEditForm.tsx | 140 +++---- frontend/src/components/forms/SeriesUploadForm.tsx | 137 ++++--- frontend/src/components/modals/HistoryModal.tsx | 184 +++++---- .../src/components/modals/ManualSearchModal.tsx | 147 +++++--- .../src/components/modals/SubtitleToolsModal.tsx | 73 +++- frontend/src/components/tables/BaseTable.tsx | 84 ++--- frontend/src/components/tables/GroupTable.tsx | 88 +++-- frontend/src/components/tables/PageTable.tsx | 63 ++-- frontend/src/components/tables/QueryPageTable.tsx | 2 +- frontend/src/components/tables/SimpleTable.tsx | 60 ++- frontend/src/components/tables/plugins/index.ts | 2 - .../tables/plugins/useCustomSelection.tsx | 113 ------ .../tables/plugins/useDefaultSettings.tsx | 33 -- frontend/src/pages/Blacklist/Movies/table.tsx | 74 ++-- frontend/src/pages/Blacklist/Series/table.tsx | 82 ++-- frontend/src/pages/Episodes/index.tsx | 31 +- frontend/src/pages/Episodes/table.tsx | 420 +++++++++++---------- frontend/src/pages/History/Movies/index.tsx | 107 ++++-- frontend/src/pages/History/Series/index.tsx | 121 +++--- frontend/src/pages/Movies/Details/table.tsx | 213 ++++++----- frontend/src/pages/Movies/Editor.tsx | 60 ++- frontend/src/pages/Movies/index.tsx | 84 +++-- frontend/src/pages/Series/Editor.tsx | 56 ++- frontend/src/pages/Series/index.tsx | 52 +-- frontend/src/pages/Settings/Languages/equals.tsx | 53 ++- frontend/src/pages/Settings/Languages/table.tsx | 60 +-- .../src/pages/Settings/components/pathMapper.tsx | 29 +- frontend/src/pages/System/Announcements/table.tsx | 61 +-- frontend/src/pages/System/Backups/table.tsx | 89 +++-- frontend/src/pages/System/Logs/table.tsx | 40 +- frontend/src/pages/System/Providers/table.tsx | 20 +- frontend/src/pages/System/Status/table.tsx | 32 +- frontend/src/pages/System/Tasks/table.tsx | 52 ++- frontend/src/pages/Wanted/Movies/index.tsx | 35 +- frontend/src/pages/Wanted/Series/index.tsx | 51 ++- frontend/src/pages/views/HistoryView.tsx | 4 +- frontend/src/pages/views/ItemView.tsx | 4 +- frontend/src/pages/views/MassEditor.tsx | 25 +- frontend/src/pages/views/WantedView.tsx | 4 +- 42 files changed, 1761 insertions(+), 1416 deletions(-) delete mode 100644 frontend/src/components/tables/plugins/index.ts delete mode 100644 frontend/src/components/tables/plugins/useCustomSelection.tsx delete mode 100644 frontend/src/components/tables/plugins/useDefaultSettings.tsx (limited to 'frontend/src/pages/System/Status') diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b1064664b..981b8acbd 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,6 +16,7 @@ "@mantine/modals": "^7.11.0", "@mantine/notifications": "^7.11.0", "@tanstack/react-query": "^5.40.1", + "@tanstack/react-table": "^8.19.2", "axios": "^1.6.8", "braces": "^3.0.3", "react": "^18.3.1", @@ -39,7 +40,6 @@ "@types/node": "^20.12.6", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@types/react-table": "^7.7.20", "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^1.4.0", "@vitest/ui": "^1.2.2", @@ -57,7 +57,6 @@ "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "pretty-quick": "^4.0.0", - "react-table": "^7.8.0", "recharts": "^2.12.6", "sass": "^1.74.1", "typescript": "^5.4.4", @@ -3381,6 +3380,39 @@ "react": "^18 || ^19" } }, + "node_modules/@tanstack/react-table": { + "version": "8.19.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.19.2.tgz", + "integrity": "sha512-itoSIAkA/Vsg+bjY23FSemcTyPhc5/1YjYyaMsr9QSH/cdbZnQxHVWrpWn0Sp2BWN71qkzR7e5ye8WuMmwyOjg==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.19.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.19.2", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.19.2.tgz", + "integrity": "sha512-KpRjhgehIhbfH78ARm/GJDXGnpdw4bCg3qas6yjWSi7czJhI/J6pWln7NHtmBkGE9ZbohiiNtLqwGzKmBfixig==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@testing-library/dom": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.0.0.tgz", @@ -3714,13 +3746,13 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true + "dev": true }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "devOptional": true, + "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3735,15 +3767,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-table": { - "version": "7.7.20", - "resolved": "https://registry.npmjs.org/@types/react-table/-/react-table-7.7.20.tgz", - "integrity": "sha512-ahMp4pmjVlnExxNwxyaDrFgmKxSbPwU23sGQw2gJK4EhCvnvmib2s/O/+y1dfV57dXOwpr2plfyBol+vEHbi2w==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", @@ -8958,19 +8981,6 @@ } } }, - "node_modules/react-table": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz", - "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.3 || ^17.0.0-0 || ^18.0.0" - } - }, "node_modules/react-textarea-autosize": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 53e9c4c47..f964fb9f8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "@mantine/modals": "^7.11.0", "@mantine/notifications": "^7.11.0", "@tanstack/react-query": "^5.40.1", + "@tanstack/react-table": "^8.19.2", "axios": "^1.6.8", "braces": "^3.0.3", "react": "^18.3.1", @@ -43,7 +44,6 @@ "@types/node": "^20.12.6", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@types/react-table": "^7.7.20", "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^1.4.0", "@vitest/ui": "^1.2.2", @@ -61,7 +61,6 @@ "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "pretty-quick": "^4.0.0", - "react-table": "^7.8.0", "recharts": "^2.12.6", "sass": "^1.74.1", "typescript": "^5.4.4", diff --git a/frontend/src/components/forms/MovieUploadForm.tsx b/frontend/src/components/forms/MovieUploadForm.tsx index 7e3df4b33..8e318d7ad 100644 --- a/frontend/src/components/forms/MovieUploadForm.tsx +++ b/frontend/src/components/forms/MovieUploadForm.tsx @@ -1,5 +1,4 @@ import { FunctionComponent, useEffect, useMemo } from "react"; -import { Column } from "react-table"; import { Button, Checkbox, @@ -17,10 +16,11 @@ import { faTrash, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { isString } from "lodash"; import { useMovieSubtitleModification } from "@/apis/hooks"; import { Action, Selector } from "@/components/inputs"; -import { SimpleTable } from "@/components/tables"; +import SimpleTable from "@/components/tables/SimpleTable"; import TextPopover from "@/components/TextPopover"; import { useModals, withModal } from "@/modules/modals"; import { task, TaskGroup } from "@/modules/task"; @@ -143,61 +143,77 @@ const MovieUploadForm: FunctionComponent = ({ }); }); - const columns = useMemo[]>( - () => [ - { - accessor: "validateResult", - Cell: ({ cell: { value } }) => { - const icon = useMemo(() => { - switch (value?.state) { - case "valid": - return faCheck; - case "warning": - return faInfoCircle; - case "error": - return faTimes; - default: - return faCircleNotch; - } - }, [value?.state]); + const ValidateResultCell = ({ + validateResult, + }: { + validateResult: SubtitleValidateResult | undefined; + }) => { + const icon = useMemo(() => { + switch (validateResult?.state) { + case "valid": + return faCheck; + case "warning": + return faInfoCircle; + case "error": + return faTimes; + default: + return faCircleNotch; + } + }, [validateResult?.state]); - const color = useMemo(() => { - switch (value?.state) { - case "valid": - return "green"; - case "warning": - return "yellow"; - case "error": - return "red"; - default: - return undefined; - } - }, [value?.state]); + const color = useMemo(() => { + switch (validateResult?.state) { + case "valid": + return "green"; + case "warning": + return "yellow"; + case "error": + return "red"; + default: + return undefined; + } + }, [validateResult?.state]); - return ( - - - - - - ); + return ( + + + + + + ); + }; + + const columns = useMemo[]>( + () => [ + { + id: "validateResult", + cell: ({ + row: { + original: { validateResult }, + }, + }) => { + return ; }, }, { - Header: "File", + header: "File", id: "filename", - accessor: "file", - Cell: ({ value }) => { - return {value.name}; + accessorKey: "file", + cell: ({ + row: { + original: { file }, + }, + }) => { + return {file.name}; }, }, { - Header: "Forced", - accessor: "forced", - Cell: ({ row: { original, index }, value }) => { + header: "Forced", + accessorKey: "forced", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, forced: checked }); }} @@ -206,12 +222,12 @@ const MovieUploadForm: FunctionComponent = ({ }, }, { - Header: "HI", - accessor: "hi", - Cell: ({ row: { original, index }, value }) => { + header: "HI", + accessorKey: "hi", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, hi: checked }); }} @@ -220,14 +236,14 @@ const MovieUploadForm: FunctionComponent = ({ }, }, { - Header: "Language", - accessor: "language", - Cell: ({ row: { original, index }, value }) => { + header: "Language", + accessorKey: "language", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, language: item }); }} @@ -237,8 +253,7 @@ const MovieUploadForm: FunctionComponent = ({ }, { id: "action", - accessor: "file", - Cell: ({ row: { index } }) => { + cell: ({ row: { index } }) => { return ( = ({ } }, [form, languages]); - const columns = useMemo[]>( + const LanguageCell = React.memo( + ({ item, index }: { item: Language.ProfileItem; index: number }) => { + const code = useMemo( + () => + languageOptions.options.find((l) => l.value.code2 === item.language) + ?.value ?? null, + [item.language], + ); + + return ( + { + if (value) { + item.language = value.code2; + action.mutate(index, { ...item, language: value.code2 }); + } + }} + > + ); + }, + ); + + const SubtitleTypeCell = React.memo( + ({ item, index }: { item: Language.ProfileItem; index: number }) => { + const selectValue = useMemo(() => { + if (item.forced === "True") { + return "forced"; + } else if (item.hi === "True") { + return "hi"; + } else { + return "normal"; + } + }, [item.forced, item.hi]); + + return ( + + ); + }, + ); + + const columns = useMemo[]>( () => [ { - Header: "ID", - accessor: "id", + header: "ID", + accessorKey: "id", }, { - Header: "Language", - accessor: "language", - Cell: ({ value: code, row: { original: item, index } }) => { - const language = useMemo( - () => - languageOptions.options.find((l) => l.value.code2 === code) - ?.value ?? null, - [code], - ); - - return ( - { - if (value) { - item.language = value.code2; - action.mutate(index, { ...item, language: value.code2 }); - } - }} - > - ); + header: "Language", + accessorKey: "language", + cell: ({ row: { original: item, index } }) => { + return ; }, }, { - Header: "Subtitles Type", - accessor: "forced", - Cell: ({ row: { original: item, index }, value }) => { - const selectValue = useMemo(() => { - if (item.forced === "True") { - return "forced"; - } else if (item.hi === "True") { - return "hi"; - } else { - return "normal"; - } - }, [item.forced, item.hi]); - - return ( - - ); + header: "Subtitles Type", + accessorKey: "forced", + cell: ({ row: { original: item, index } }) => { + return ; }, }, { - Header: "Exclude If Matching Audio", - accessor: "audio_exclude", - Cell: ({ row: { original: item, index }, value }) => { + header: "Exclude If Matching Audio", + accessorKey: "audio_exclude", + cell: ({ row: { original: item, index } }) => { return ( { action.mutate(index, { ...item, @@ -228,8 +241,7 @@ const ProfileEditForm: FunctionComponent = ({ }, { id: "action", - accessor: "id", - Cell: ({ row }) => { + cell: ({ row }) => { return ( = ({ }, }, ], - [action, languageOptions], + [action, LanguageCell, SubtitleTypeCell], ); return ( diff --git a/frontend/src/components/forms/SeriesUploadForm.tsx b/frontend/src/components/forms/SeriesUploadForm.tsx index 99a8e8e30..e4482cab4 100644 --- a/frontend/src/components/forms/SeriesUploadForm.tsx +++ b/frontend/src/components/forms/SeriesUploadForm.tsx @@ -1,5 +1,4 @@ import { FunctionComponent, useEffect, useMemo } from "react"; -import { Column } from "react-table"; import { Button, Checkbox, @@ -17,6 +16,7 @@ import { faTrash, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { isString } from "lodash"; import { useEpisodesBySeriesId, @@ -24,7 +24,7 @@ import { useSubtitleInfos, } from "@/apis/hooks"; import { Action, Selector } from "@/components/inputs"; -import { SimpleTable } from "@/components/tables"; +import SimpleTable from "@/components/tables/SimpleTable"; import TextPopover from "@/components/TextPopover"; import { useModals, withModal } from "@/modules/modals"; import { task, TaskGroup } from "@/modules/task"; @@ -169,61 +169,79 @@ const SeriesUploadForm: FunctionComponent = ({ } }, [action, episodes.data, infos.data]); - const columns = useMemo[]>( - () => [ - { - accessor: "validateResult", - Cell: ({ cell: { value } }) => { - const icon = useMemo(() => { - switch (value?.state) { - case "valid": - return faCheck; - case "warning": - return faInfoCircle; - case "error": - return faTimes; - default: - return faCircleNotch; - } - }, [value?.state]); + const ValidateResultCell = ({ + validateResult, + }: { + validateResult: SubtitleValidateResult | undefined; + }) => { + const icon = useMemo(() => { + switch (validateResult?.state) { + case "valid": + return faCheck; + case "warning": + return faInfoCircle; + case "error": + return faTimes; + default: + return faCircleNotch; + } + }, [validateResult?.state]); - const color = useMemo(() => { - switch (value?.state) { - case "valid": - return "green"; - case "warning": - return "yellow"; - case "error": - return "red"; - default: - return undefined; - } - }, [value?.state]); + const color = useMemo(() => { + switch (validateResult?.state) { + case "valid": + return "green"; + case "warning": + return "yellow"; + case "error": + return "red"; + default: + return undefined; + } + }, [validateResult?.state]); - return ( - - - - - - ); + return ( + + + + + + ); + }; + + const columns = useMemo[]>( + () => [ + { + id: "validateResult", + cell: ({ + row: { + original: { validateResult }, + }, + }) => { + return ; }, }, { - Header: "File", + header: "File", id: "filename", - accessor: "file", - Cell: ({ value: { name } }) => { + accessorKey: "file", + cell: ({ + row: { + original: { + file: { name }, + }, + }, + }) => { return {name}; }, }, { - Header: "Forced", - accessor: "forced", - Cell: ({ row: { original, index }, value }) => { + header: "Forced", + accessorKey: "forced", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, @@ -236,12 +254,12 @@ const SeriesUploadForm: FunctionComponent = ({ }, }, { - Header: "HI", - accessor: "hi", - Cell: ({ row: { original, index }, value }) => { + header: "HI", + accessorKey: "hi", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, @@ -254,7 +272,7 @@ const SeriesUploadForm: FunctionComponent = ({ }, }, { - Header: ( + header: () => ( = ({ }} > ), - accessor: "language", - Cell: ({ row: { original, index }, value }) => { + accessorKey: "language", + cell: ({ row: { original, index } }) => { return ( { action.mutate(index, { ...original, language: item }); }} @@ -285,17 +303,17 @@ const SeriesUploadForm: FunctionComponent = ({ }, { id: "episode", - Header: "Episode", - accessor: "episode", - Cell: ({ value, row }) => { + header: "Episode", + accessorKey: "episode", + cell: ({ row: { original, index } }) => { return ( { - action.mutate(row.index, { ...row.original, episode: item }); + action.mutate(index, { ...original, episode: item }); }} > ); @@ -303,8 +321,7 @@ const SeriesUploadForm: FunctionComponent = ({ }, { id: "action", - accessor: "file", - Cell: ({ row: { index } }) => { + cell: ({ row: { index } }) => { return ( = ({ const { data } = history; - const columns = useMemo[]>( + const addMovieToBlacklist = useMovieAddBlacklist(); + + const columns = useMemo[]>( () => [ { - accessor: "action", - Cell: (row) => ( + id: "action", + cell: ({ + row: { + original: { action }, + }, + }) => (

- +
), }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { return ( - + ); } else { @@ -56,17 +66,20 @@ const MovieHistoryView: FunctionComponent = ({ }, }, { - Header: "Provider", - accessor: "provider", + header: "Provider", + accessorKey: "provider", }, { - Header: "Score", - accessor: "score", + header: "Score", + accessorKey: "score", }, { - accessor: "matches", - Cell: (row) => { - const { matches, dont_matches: dont } = row.row.original; + id: "matches", + cell: ({ + row: { + original: { matches, dont_matches: dont }, + }, + }) => { if (matches.length || dont.length) { return ( = ({ }, }, { - Header: "Date", - accessor: "timestamp", - Cell: ({ value, row }) => { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp: parsedTimestamp }, + }, + }) => { return ( - - {value} + + {timestamp} ); }, }, { // Actions - accessor: "blacklisted", - Cell: ({ row, value }) => { - const add = useMovieAddBlacklist(); - const { radarrId, provider, subs_id, language, subtitles_path } = - row.original; - + id: "blacklisted", + cell: ({ + row: { + original: { + blacklisted, + radarrId, + provider, + subs_id, + language, + subtitles_path, + }, + }, + }) => { if (subs_id && provider && language) { return ( ({ id: radarrId, form: { @@ -123,7 +147,7 @@ const MovieHistoryView: FunctionComponent = ({ }, }, ], - [], + [addMovieToBlacklist], ); return ( @@ -153,24 +177,34 @@ const EpisodeHistoryView: FunctionComponent = ({ const { data } = history; - const columns = useMemo[]>( + const addEpisodeToBlacklist = useEpisodeAddBlacklist(); + + const columns = useMemo[]>( () => [ { - accessor: "action", - Cell: (row) => ( + id: "action", + cell: ({ + row: { + original: { action }, + }, + }) => (
- +
), }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { return ( - + ); } else { @@ -179,16 +213,16 @@ const EpisodeHistoryView: FunctionComponent = ({ }, }, { - Header: "Provider", - accessor: "provider", + header: "Provider", + accessorKey: "provider", }, { - Header: "Score", - accessor: "score", + header: "Score", + accessorKey: "score", }, { - accessor: "matches", - Cell: (row) => { + id: "matches", + cell: (row) => { const { matches, dont_matches: dont } = row.row.original; if (matches.length || dont.length) { return ( @@ -204,21 +238,29 @@ const EpisodeHistoryView: FunctionComponent = ({ }, }, { - Header: "Date", - accessor: "timestamp", - Cell: ({ row, value }) => { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp: parsedTimestamp }, + }, + }) => { return ( - - {value} + + {timestamp} ); }, }, { - accessor: "description", - Cell: ({ value }) => { + id: "description", + cell: ({ + row: { + original: { description }, + }, + }) => { return ( - + ); @@ -226,25 +268,27 @@ const EpisodeHistoryView: FunctionComponent = ({ }, { // Actions - accessor: "blacklisted", - Cell: ({ row, value }) => { - const { - sonarrEpisodeId, - sonarrSeriesId, - provider, - subs_id, - language, - subtitles_path, - } = row.original; - const add = useEpisodeAddBlacklist(); - + id: "blacklisted", + cell: ({ + row: { + original: { + blacklisted, + sonarrEpisodeId, + sonarrSeriesId, + provider, + subs_id, + language, + subtitles_path, + }, + }, + }) => { if (subs_id && provider && language) { return ( ({ seriesId: sonarrSeriesId, episodeId: sonarrEpisodeId, @@ -263,7 +307,7 @@ const EpisodeHistoryView: FunctionComponent = ({ }, }, ], - [], + [addEpisodeToBlacklist], ); return ( diff --git a/frontend/src/components/modals/ManualSearchModal.tsx b/frontend/src/components/modals/ManualSearchModal.tsx index d29a2deba..81a49f0f3 100644 --- a/frontend/src/components/modals/ManualSearchModal.tsx +++ b/frontend/src/components/modals/ManualSearchModal.tsx @@ -1,5 +1,4 @@ -import { useCallback, useMemo, useState } from "react"; -import { Column } from "react-table"; +import React, { useCallback, useMemo, useState } from "react"; import { Alert, Anchor, @@ -18,10 +17,12 @@ import { } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { UseQueryResult } from "@tanstack/react-query"; +import { ColumnDef } from "@tanstack/react-table"; import { isString } from "lodash"; -import { Action, PageTable } from "@/components"; +import { Action } from "@/components"; import Language from "@/components/bazarr/Language"; import StateIcon from "@/components/StateIcon"; +import PageTable from "@/components/tables/PageTable"; import { withModal } from "@/modules/modals"; import { task, TaskGroup } from "@/modules/task"; import { GetItemId } from "@/utilities"; @@ -51,23 +52,63 @@ function ManualSearchView(props: Props) { void results.refetch(); }, [results]); - const columns = useMemo[]>( + const ReleaseInfoCell = React.memo( + ({ releaseInfo }: { releaseInfo: string[] }) => { + const [open, setOpen] = useState(false); + + const items = useMemo( + () => releaseInfo.slice(1).map((v, idx) => {v}), + [releaseInfo], + ); + + if (releaseInfo.length === 0) { + return Cannot get release info; + } + + return ( + setOpen((o) => !o)}> + + {releaseInfo[0]} + {releaseInfo.length > 1 && ( + + )} + + + <>{items} + + + ); + }, + ); + + const columns = useMemo[]>( () => [ { - Header: "Score", - accessor: "score", - Cell: ({ value }) => { - return {value}%; + header: "Score", + accessorKey: "score", + cell: ({ + row: { + original: { score }, + }, + }) => { + return {score}%; }, }, { - Header: "Language", - accessor: "language", - Cell: ({ row: { original }, value }) => { + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language, hearing_impaired: hi, forced }, + }, + }) => { const lang: Language.Info = { - code2: value, - hi: original.hearing_impaired === "True", - forced: original.forced === "True", + code2: language, + hi: hi === "True", + forced: forced === "True", name: "", }; return ( @@ -78,11 +119,15 @@ function ManualSearchView(props: Props) { }, }, { - Header: "Provider", - accessor: "provider", - Cell: (row) => { - const value = row.value; - const { url } = row.row.original; + header: "Provider", + accessorKey: "provider", + cell: ({ + row: { + original: { provider, url }, + }, + }) => { + const value = provider; + if (url) { return ( (props: Props) { }, }, { - Header: "Release", - accessor: "release_info", - Cell: ({ value }) => { - const [open, setOpen] = useState(false); - - const items = useMemo( - () => value.slice(1).map((v, idx) => {v}), - [value], - ); - - if (value.length === 0) { - return Cannot get release info; - } - - return ( - setOpen((o) => !o)}> - - {value[0]} - {value.length > 1 && ( - - )} - - - <>{items} - - - ); + header: "Release", + accessorKey: "release_info", + cell: ({ + row: { + original: { release_info: releaseInfo }, + }, + }) => { + return ; }, }, { - Header: "Uploader", - accessor: "uploader", - Cell: ({ value }) => { - return {value ?? "-"}; + header: "Uploader", + accessorKey: "uploader", + cell: ({ + row: { + original: { uploader }, + }, + }) => { + return {uploader ?? "-"}; }, }, { - Header: "Match", - accessor: "matches", - Cell: (row) => { + header: "Match", + accessorKey: "matches", + cell: (row) => { const { matches, dont_matches: dont } = row.row.original; return ( (props: Props) { }, }, { - Header: "Get", - accessor: "subtitle", - Cell: ({ row }) => { + header: "Get", + accessorKey: "subtitle", + cell: ({ row }) => { const result = row.original; return ( (props: Props) { }, }, ], - [download, item], + [download, item, ReleaseInfoCell], ); const bSceneNameAvailable = diff --git a/frontend/src/components/modals/SubtitleToolsModal.tsx b/frontend/src/components/modals/SubtitleToolsModal.tsx index 150788b48..dca20d159 100644 --- a/frontend/src/components/modals/SubtitleToolsModal.tsx +++ b/frontend/src/components/modals/SubtitleToolsModal.tsx @@ -1,10 +1,17 @@ import { FunctionComponent, useMemo, useState } from "react"; -import { Column, useRowSelect } from "react-table"; -import { Badge, Button, Divider, Group, Stack, Text } from "@mantine/core"; +import { + Badge, + Button, + Checkbox, + Divider, + Group, + Stack, + Text, +} from "@mantine/core"; +import { ColumnDef } from "@tanstack/react-table"; import Language from "@/components/bazarr/Language"; import SubtitleToolsMenu from "@/components/SubtitleToolsMenu"; -import { SimpleTable } from "@/components/tables"; -import { useCustomSelection } from "@/components/tables/plugins"; +import SimpleTable from "@/components/tables/SimpleTable"; import { withModal } from "@/modules/modals"; import { isMovie } from "@/utilities"; @@ -35,24 +42,53 @@ const SubtitleToolView: FunctionComponent = ({ }) => { const [selections, setSelections] = useState([]); - const columns: Column[] = useMemo[]>( + const columns = useMemo[]>( () => [ { - Header: "Language", - accessor: "raw_language", - Cell: ({ value }) => ( + id: "selection", + header: ({ table }) => { + return ( + + ); + }, + cell: ({ row: { index, getIsSelected, getToggleSelectedHandler } }) => { + return ( + + ); + }, + }, + { + header: "Language", + accessorKey: "raw_language", + cell: ({ + row: { + original: { raw_language: rawLanguage }, + }, + }) => ( - + ), }, { id: "file", - Header: "File", - accessor: "path", - Cell: ({ value }) => { - const path = value; - + header: "File", + accessorKey: "path", + cell: ({ + row: { + original: { path }, + }, + }) => { let idx = path.lastIndexOf("/"); if (idx === -1) { @@ -94,16 +130,15 @@ const SubtitleToolView: FunctionComponent = ({ [payload], ); - const plugins = [useRowSelect, useCustomSelection]; - return ( CanSelectSubtitle(row.original)} + onRowSelectionChanged={(rows) => + setSelections(rows.map((r) => r.original)) + } columns={columns} - onSelect={setSelections} - canSelect={CanSelectSubtitle} data={data} > diff --git a/frontend/src/components/tables/BaseTable.tsx b/frontend/src/components/tables/BaseTable.tsx index 53058032d..b5a867b14 100644 --- a/frontend/src/components/tables/BaseTable.tsx +++ b/frontend/src/components/tables/BaseTable.tsx @@ -1,11 +1,17 @@ -import { ReactNode, useMemo } from "react"; -import { HeaderGroup, Row, TableInstance } from "react-table"; +import React, { ReactNode, useMemo } from "react"; import { Box, Skeleton, Table, Text } from "@mantine/core"; +import { + flexRender, + Header, + Row, + Table as TableInstance, +} from "@tanstack/react-table"; import { useIsLoading } from "@/contexts"; import { usePageSize } from "@/utilities/storage"; -import styles from "./BaseTable.module.scss"; +import styles from "@/components/tables/BaseTable.module.scss"; -export type BaseTableProps = TableInstance & { +export type BaseTableProps = { + instance: TableInstance; tableStyles?: TableStyleProps; }; @@ -15,60 +21,57 @@ export interface TableStyleProps { placeholder?: number; hideHeader?: boolean; fixHeader?: boolean; - headersRenderer?: (headers: HeaderGroup[]) => JSX.Element[]; - rowRenderer?: (row: Row) => Nullable; + headersRenderer?: (headers: Header[]) => React.JSX.Element[]; + rowRenderer?: (row: Row) => Nullable; } function DefaultHeaderRenderer( - headers: HeaderGroup[], -): JSX.Element[] { - return headers.map((col) => ( - - {col.render("Header")} + headers: Header[], +): React.JSX.Element[] { + return headers.map((header) => ( + + {flexRender(header.column.columnDef.header, header.getContext())} )); } -function DefaultRowRenderer(row: Row): JSX.Element | null { +function DefaultRowRenderer( + row: Row, +): React.JSX.Element | null { return ( - - {row.cells.map((cell) => ( - {cell.render("Cell")} + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + ))} ); } export default function BaseTable(props: BaseTableProps) { - const { - headerGroups, - rows: tableRows, - page: tablePages, - prepareRow, - getTableProps, - getTableBodyProps, - tableStyles, - } = props; + const { instance, tableStyles } = props; const headersRenderer = tableStyles?.headersRenderer ?? DefaultHeaderRenderer; const rowRenderer = tableStyles?.rowRenderer ?? DefaultRowRenderer; const colCount = useMemo(() => { - return headerGroups.reduce( - (prev, curr) => (curr.headers.length > prev ? curr.headers.length : prev), - 0, - ); - }, [headerGroups]); + return instance + .getHeaderGroups() + .reduce( + (prev, curr) => + curr.headers.length > prev ? curr.headers.length : prev, + 0, + ); + }, [instance]); - // Switch to usePagination plugin if enabled - const rows = tablePages ?? tableRows; - - const empty = rows.length === 0; + const empty = instance.getRowCount() === 0; const pageSize = usePageSize(); const isLoading = useIsLoading(); let body: ReactNode; + if (isLoading) { body = Array(tableStyles?.placeholder ?? pageSize) .fill(0) @@ -88,27 +91,22 @@ export default function BaseTable(props: BaseTableProps) { ); } else { - body = rows.map((row) => { - prepareRow(row); + body = instance.getRowModel().rows.map((row) => { return rowRenderer(row); }); } return ( - +
- {body} + {body}
); diff --git a/frontend/src/components/tables/GroupTable.tsx b/frontend/src/components/tables/GroupTable.tsx index c05182aa6..b14edf3e6 100644 --- a/frontend/src/components/tables/GroupTable.tsx +++ b/frontend/src/components/tables/GroupTable.tsx @@ -1,38 +1,44 @@ -import { - Cell, - HeaderGroup, - Row, - useExpanded, - useGroupBy, - useSortBy, -} from "react-table"; +import React, { Fragment } from "react"; import { Box, Table, Text } from "@mantine/core"; import { faChevronCircleRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import SimpleTable, { SimpleTableProps } from "./SimpleTable"; +import { + Cell, + flexRender, + getExpandedRowModel, + getGroupedRowModel, + Header, + Row, +} from "@tanstack/react-table"; +import SimpleTable, { SimpleTableProps } from "@/components/tables/SimpleTable"; -function renderCell(cell: Cell, row: Row) { - if (cell.isGrouped) { +function renderCell( + cell: Cell, + row: Row, +) { + if (cell.getIsGrouped()) { return ( -
{cell.render("Cell")}
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
); - } else if (row.canExpand || cell.isAggregated) { + } else if (row.getCanExpand() || cell.getIsAggregated()) { return null; } else { - return cell.render("Cell"); + return flexRender(cell.column.columnDef.cell, cell.getContext()); } } function renderRow(row: Row) { - if (row.canExpand) { - const cell = row.cells.find((cell) => cell.isGrouped); + if (row.getCanExpand()) { + const cell = row.getVisibleCells().find((cell) => cell.getIsGrouped()); + if (cell) { - const rotation = row.isExpanded ? 90 : undefined; + const rotation = row.getIsExpanded() ? 90 : undefined; + return ( - - - - {cell.render("Cell")} + + + row.toggleExpanded()}> + {flexRender(cell.column.columnDef.cell, cell.getContext())} (row: Row) { } } else { return ( - - {row.cells - .filter((cell) => !cell.isPlaceholder) + + {row + .getVisibleCells() + .filter((cell) => !cell.getIsPlaceholder()) .map((cell) => ( - - {renderCell(cell, row)} - + {renderCell(cell, row)} ))} ); @@ -62,27 +67,34 @@ function renderRow(row: Row) { } function renderHeaders( - headers: HeaderGroup[], -): JSX.Element[] { - return headers - .filter((col) => !col.isGrouped) - .map((col) => ( - {col.render("Header")} - )); + headers: Header[], +): React.JSX.Element[] { + return headers.map((header) => { + if (header.column.getIsGrouped()) { + return ; + } + + return ( + + {flexRender(header.column.columnDef.header, header.getContext())} + + ); + }); } type Props = Omit< SimpleTableProps, - "plugins" | "headersRenderer" | "rowRenderer" + "headersRenderer" | "rowRenderer" >; -const plugins = [useGroupBy, useSortBy, useExpanded]; - function GroupTable(props: Props) { return ( ); diff --git a/frontend/src/components/tables/PageTable.tsx b/frontend/src/components/tables/PageTable.tsx index ee4824db6..476ff2c2b 100644 --- a/frontend/src/components/tables/PageTable.tsx +++ b/frontend/src/components/tables/PageTable.tsx @@ -1,55 +1,62 @@ -import { useEffect } from "react"; -import { usePagination, useTable } from "react-table"; +import { MutableRefObject, useEffect } from "react"; +import { + getCoreRowModel, + getPaginationRowModel, + Table, + TableOptions, + useReactTable, +} from "@tanstack/react-table"; +import BaseTable, { TableStyleProps } from "@/components/tables/BaseTable"; import { ScrollToTop } from "@/utilities"; import { usePageSize } from "@/utilities/storage"; -import BaseTable from "./BaseTable"; import PageControl from "./PageControl"; -import { useDefaultSettings } from "./plugins"; -import { SimpleTableProps } from "./SimpleTable"; -type Props = SimpleTableProps & { +type Props = Omit, "getCoreRowModel"> & { + instanceRef?: MutableRefObject | null>; + tableStyles?: TableStyleProps; autoScroll?: boolean; }; -const tablePlugins = [useDefaultSettings, usePagination]; - export default function PageTable(props: Props) { - const { autoScroll = true, plugins, instanceRef, ...options } = props; + const { instanceRef, autoScroll, ...options } = props; - const instance = useTable( - options, - useDefaultSettings, - ...tablePlugins, - ...(plugins ?? []), - ); + const pageSize = usePageSize(); - // use page size as specified in UI settings - instance.state.pageSize = usePageSize(); + const instance = useReactTable({ + ...options, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + initialState: { + pagination: { + pageSize: pageSize, + }, + }, + }); if (instanceRef) { instanceRef.current = instance; } + const pageIndex = instance.getState().pagination.pageIndex; + // Scroll to top when page is changed useEffect(() => { if (autoScroll) { ScrollToTop(); } - }, [instance.state.pageIndex, autoScroll]); + }, [pageIndex, autoScroll]); + + const state = instance.getState(); return ( <> - + ); diff --git a/frontend/src/components/tables/QueryPageTable.tsx b/frontend/src/components/tables/QueryPageTable.tsx index c144b3b54..797d7a08e 100644 --- a/frontend/src/components/tables/QueryPageTable.tsx +++ b/frontend/src/components/tables/QueryPageTable.tsx @@ -1,9 +1,9 @@ import { useEffect } from "react"; import { UsePaginationQueryResult } from "@/apis/queries/hooks"; +import SimpleTable, { SimpleTableProps } from "@/components/tables/SimpleTable"; import { LoadingProvider } from "@/contexts"; import { ScrollToTop } from "@/utilities"; import PageControl from "./PageControl"; -import SimpleTable, { SimpleTableProps } from "./SimpleTable"; type Props = Omit, "data"> & { query: UsePaginationQueryResult; diff --git a/frontend/src/components/tables/SimpleTable.tsx b/frontend/src/components/tables/SimpleTable.tsx index 90f76c7f2..e3e0b7ff3 100644 --- a/frontend/src/components/tables/SimpleTable.tsx +++ b/frontend/src/components/tables/SimpleTable.tsx @@ -1,23 +1,65 @@ -import { PluginHook, TableInstance, TableOptions, useTable } from "react-table"; -import BaseTable, { TableStyleProps } from "./BaseTable"; -import { useDefaultSettings } from "./plugins"; +import { MutableRefObject, useEffect, useMemo } from "react"; +import { + getCoreRowModel, + Row, + Table, + TableOptions, + useReactTable, +} from "@tanstack/react-table"; +import BaseTable, { TableStyleProps } from "@/components/tables/BaseTable"; +import { usePageSize } from "@/utilities/storage"; -export type SimpleTableProps = TableOptions & { - plugins?: PluginHook[]; - instanceRef?: React.MutableRefObject | null>; +export type SimpleTableProps = Omit< + TableOptions, + "getCoreRowModel" +> & { + instanceRef?: MutableRefObject | null>; tableStyles?: TableStyleProps; + onRowSelectionChanged?: (selectedRows: Row[]) => void; + onAllRowsExpandedChanged?: (isAllRowsExpanded: boolean) => void; }; export default function SimpleTable( props: SimpleTableProps, ) { - const { plugins, instanceRef, tableStyles, ...options } = props; + const { + instanceRef, + tableStyles, + onRowSelectionChanged, + onAllRowsExpandedChanged, + ...options + } = props; - const instance = useTable(options, useDefaultSettings, ...(plugins ?? [])); + const pageSize = usePageSize(); + + const instance = useReactTable({ + ...options, + getCoreRowModel: getCoreRowModel(), + autoResetPageIndex: false, + autoResetExpanded: false, + pageCount: pageSize, + }); if (instanceRef) { instanceRef.current = instance; } - return ; + const selectedRows = instance.getSelectedRowModel().rows; + + const memoizedRows = useMemo(() => selectedRows, [selectedRows]); + + // eslint-disable-next-line react-hooks/exhaustive-deps + const memoizedRowSelectionChanged = useMemo(() => onRowSelectionChanged, []); + + const isAllRowsExpanded = instance.getIsAllRowsExpanded(); + + useEffect(() => { + memoizedRowSelectionChanged?.(memoizedRows); + }, [memoizedRowSelectionChanged, memoizedRows]); + + useEffect(() => { + onAllRowsExpandedChanged?.(isAllRowsExpanded); + }, [onAllRowsExpandedChanged, isAllRowsExpanded]); + + return ; } diff --git a/frontend/src/components/tables/plugins/index.ts b/frontend/src/components/tables/plugins/index.ts deleted file mode 100644 index 39490a113..000000000 --- a/frontend/src/components/tables/plugins/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as useCustomSelection } from "./useCustomSelection"; -export { default as useDefaultSettings } from "./useDefaultSettings"; diff --git a/frontend/src/components/tables/plugins/useCustomSelection.tsx b/frontend/src/components/tables/plugins/useCustomSelection.tsx deleted file mode 100644 index 572926093..000000000 --- a/frontend/src/components/tables/plugins/useCustomSelection.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { forwardRef, useEffect, useRef } from "react"; -import { - CellProps, - Column, - ColumnInstance, - ensurePluginOrder, - HeaderProps, - Hooks, - MetaBase, - TableInstance, - TableToggleCommonProps, -} from "react-table"; -import { Checkbox as MantineCheckbox } from "@mantine/core"; - -const pluginName = "useCustomSelection"; - -const checkboxId = "---selection---"; - -interface CheckboxProps { - idIn: string; - disabled?: boolean; -} - -const Checkbox = forwardRef< - HTMLInputElement, - TableToggleCommonProps & CheckboxProps ->(({ indeterminate, checked, disabled, idIn, ...rest }, ref) => { - const defaultRef = useRef(null); - const resolvedRef = ref || defaultRef; - - useEffect(() => { - if (typeof resolvedRef === "object" && resolvedRef.current) { - resolvedRef.current.indeterminate = indeterminate ?? false; - - if (disabled) { - resolvedRef.current.checked = false; - } else { - resolvedRef.current.checked = checked ?? false; - } - } - }, [resolvedRef, indeterminate, checked, disabled]); - - return ( - - ); -}); - -function useCustomSelection(hooks: Hooks) { - hooks.visibleColumns.push(visibleColumns); - hooks.useInstance.push(useInstance); -} - -useCustomSelection.pluginName = pluginName; - -function useInstance(instance: TableInstance) { - const { - plugins, - rows, - onSelect, - canSelect, - state: { selectedRowIds }, - } = instance; - - ensurePluginOrder(plugins, ["useRowSelect"], pluginName); - - useEffect(() => { - // Performance - let items = Object.keys(selectedRowIds).flatMap( - (v) => rows.find((n) => n.id === v)?.original ?? [], - ); - - if (canSelect) { - items = items.filter((v) => canSelect(v)); - } - - onSelect && onSelect(items); - }, [selectedRowIds, onSelect, rows, canSelect]); -} - -function visibleColumns( - columns: ColumnInstance[], - meta: MetaBase, -): Column[] { - const { instance } = meta; - const checkbox: Column = { - id: checkboxId, - Header: ({ getToggleAllRowsSelectedProps }: HeaderProps) => ( - - ), - Cell: ({ row }: CellProps) => { - const canSelect = instance.canSelect; - const disabled = (canSelect && !canSelect(row.original)) ?? false; - return ( - - ); - }, - }; - return [checkbox, ...columns]; -} - -export default useCustomSelection; diff --git a/frontend/src/components/tables/plugins/useDefaultSettings.tsx b/frontend/src/components/tables/plugins/useDefaultSettings.tsx deleted file mode 100644 index ac34334b4..000000000 --- a/frontend/src/components/tables/plugins/useDefaultSettings.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Hooks, TableOptions } from "react-table"; -import { usePageSize } from "@/utilities/storage"; - -const pluginName = "useLocalSettings"; - -function useDefaultSettings(hooks: Hooks) { - hooks.useOptions.push(useOptions); -} -useDefaultSettings.pluginName = pluginName; - -function useOptions(options: TableOptions) { - const pageSize = usePageSize(); - - if (options.autoResetPage === undefined) { - options.autoResetPage = false; - } - - if (options.autoResetExpanded === undefined) { - options.autoResetExpanded = false; - } - - if (options.initialState === undefined) { - options.initialState = {}; - } - - if (options.initialState.pageSize === undefined) { - options.initialState.pageSize = pageSize; - } - - return options; -} - -export default useDefaultSettings; diff --git a/frontend/src/pages/Blacklist/Movies/table.tsx b/frontend/src/pages/Blacklist/Movies/table.tsx index 0ac3bf3a8..00730a850 100644 --- a/frontend/src/pages/Blacklist/Movies/table.tsx +++ b/frontend/src/pages/Blacklist/Movies/table.tsx @@ -1,56 +1,70 @@ import { FunctionComponent, useMemo } from "react"; import { Link } from "react-router-dom"; -import { Column } from "react-table"; import { Anchor, Text } from "@mantine/core"; import { faTrash } from "@fortawesome/free-solid-svg-icons"; +import { ColumnDef } from "@tanstack/react-table"; import { useMovieDeleteBlacklist } from "@/apis/hooks"; -import { PageTable } from "@/components"; import MutateAction from "@/components/async/MutateAction"; import Language from "@/components/bazarr/Language"; +import PageTable from "@/components/tables/PageTable"; import TextPopover from "@/components/TextPopover"; interface Props { - blacklist: readonly Blacklist.Movie[]; + blacklist: Blacklist.Movie[]; } const Table: FunctionComponent = ({ blacklist }) => { - const columns = useMemo[]>( + const remove = useMovieDeleteBlacklist(); + + const columns = useMemo[]>( () => [ { - Header: "Name", - accessor: "title", - Cell: (row) => { - const target = `/movies/${row.row.original.radarrId}`; + header: "Name", + accessorKey: "title", + cell: ({ + row: { + original: { radarrId }, + }, + }) => { + const target = `/movies/${radarrId}`; return ( - {row.value} + {radarrId} ); }, }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { - return ; + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { + return ; } else { return null; } }, }, { - Header: "Provider", - accessor: "provider", + header: "Provider", + accessorKey: "provider", }, { - Header: "Date", - accessor: "timestamp", - Cell: (row) => { - if (row.value) { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp: parsedTimestamp }, + }, + }) => { + if (timestamp) { return ( - - {row.value} + + {timestamp} ); } else { @@ -59,10 +73,12 @@ const Table: FunctionComponent = ({ blacklist }) => { }, }, { - accessor: "subs_id", - Cell: ({ row, value }) => { - const remove = useMovieDeleteBlacklist(); - + id: "subs_id", + cell: ({ + row: { + original: { subs_id: subsId, provider }, + }, + }) => { return ( = ({ blacklist }) => { args={() => ({ all: false, form: { - provider: row.original.provider, + provider: provider, // eslint-disable-next-line camelcase - subs_id: value, + subs_id: subsId, }, })} > @@ -82,7 +98,7 @@ const Table: FunctionComponent = ({ blacklist }) => { }, }, ], - [], + [remove], ); return ( = ({ blacklist }) => { - const columns = useMemo[]>( + const removeFromBlacklist = useEpisodeDeleteBlacklist(); + + const columns = useMemo[]>( () => [ { - Header: "Series", - accessor: "seriesTitle", - Cell: (row) => { - const target = `/series/${row.row.original.sonarrSeriesId}`; + header: "Series", + accessorKey: "seriesTitle", + cell: ({ + row: { + original: { sonarrSeriesId, seriesTitle }, + }, + }) => { + const target = `/series/${sonarrSeriesId}`; return ( - {row.value} + {seriesTitle} ); }, }, { - Header: "Episode", - accessor: "episode_number", + header: "Episode", + accessorKey: "episode_number", }, { - accessor: "episodeTitle", + id: "episodeTitle", }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { - return ; + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { + return ; } else { return null; } }, }, { - Header: "Provider", - accessor: "provider", + header: "Provider", + accessorKey: "provider", }, { - Header: "Date", - accessor: "timestamp", - Cell: (row) => { - if (row.value) { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp: parsedTimestamp }, + }, + }) => { + if (timestamp) { return ( - - {row.value} + + {timestamp} ); } else { @@ -66,22 +80,24 @@ const Table: FunctionComponent = ({ blacklist }) => { }, }, { - accessor: "subs_id", - Cell: ({ row, value }) => { - const remove = useEpisodeDeleteBlacklist(); - + id: "subs_id", + cell: ({ + row: { + original: { subs_id: subsId, provider }, + }, + }) => { return ( ({ all: false, form: { - provider: row.original.provider, + provider: provider, // eslint-disable-next-line camelcase - subs_id: value, + subs_id: subsId, }, })} > @@ -89,7 +105,7 @@ const Table: FunctionComponent = ({ blacklist }) => { }, }, ], - [], + [removeFromBlacklist], ); return ( { - const [state, setState] = useState({ - expand: false, - buttonText: "Expand All", - initial: true, - }); - const params = useParams(); const id = Number.parseInt(params.id as string); @@ -102,18 +97,18 @@ const SeriesEpisodesView: FunctionComponent = () => { useDocumentTitle(`${series?.title ?? "Unknown Series"} - Bazarr (Series)`); + const tableRef = useRef | null>(null); + + const [isAllRowExpanded, setIsAllRowExpanded] = useState( + tableRef?.current?.getIsAllRowsExpanded(), + ); + const openDropzone = useRef(null); if (isNaN(id) || (isFetched && !series)) { return ; } - const toggleState = () => { - state.expand - ? setState({ expand: false, buttonText: "Expand All", initial: false }) - : setState({ expand: true, buttonText: "Collapse All", initial: false }); - }; - return ( @@ -210,12 +205,14 @@ const SeriesEpisodesView: FunctionComponent = () => { Edit Series { - toggleState(); + tableRef.current?.toggleAllRowsExpanded(); }} > - {state.buttonText} + {isAllRowExpanded ? "Collapse All" : "Expand All"} @@ -223,11 +220,11 @@ const SeriesEpisodesView: FunctionComponent = () => {
diff --git a/frontend/src/pages/Episodes/table.tsx b/frontend/src/pages/Episodes/table.tsx index b28e0d7e8..7b8d4494f 100644 --- a/frontend/src/pages/Episodes/table.tsx +++ b/frontend/src/pages/Episodes/table.tsx @@ -1,11 +1,4 @@ -import { - FunctionComponent, - useCallback, - useEffect, - useMemo, - useRef, -} from "react"; -import { Column, TableInstance } from "react-table"; +import React, { forwardRef, useCallback, useEffect, useMemo } from "react"; import { Group, Text } from "@mantine/core"; import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; import { @@ -14,6 +7,7 @@ import { faUser, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef, Table as TableInstance } from "@tanstack/react-table"; import { useDownloadEpisodeSubtitles, useEpisodesProvider } from "@/apis/hooks"; import { useShowOnlyDesired } from "@/apis/hooks/site"; import { Action, GroupTable } from "@/components"; @@ -30,219 +24,227 @@ interface Props { episodes: Item.Episode[] | null; disabled?: boolean; profile?: Language.Profile; - expand?: boolean; - initial?: boolean; + onAllRowsExpandedChanged: (isAllRowsExpanded: boolean) => void; } -const Table: FunctionComponent = ({ - episodes, - profile, - disabled, - expand, - initial, -}) => { - const onlyDesired = useShowOnlyDesired(); - - const profileItems = useProfileItemsToLanguages(profile); - const { mutateAsync } = useDownloadEpisodeSubtitles(); - - const download = useCallback( - (item: Item.Episode, result: SearchResultType) => { - const { - language, - hearing_impaired: hi, - forced, - provider, - subtitle, - original_format: originalFormat, - } = result; - const { sonarrSeriesId: seriesId, sonarrEpisodeId: episodeId } = item; - - return mutateAsync({ - seriesId, - episodeId, - form: { +const Table = forwardRef | null, Props>( + ({ episodes, profile, disabled, onAllRowsExpandedChanged }, ref) => { + const onlyDesired = useShowOnlyDesired(); + + const tableRef = + ref as React.MutableRefObject | null>; + + const profileItems = useProfileItemsToLanguages(profile); + + const { mutateAsync } = useDownloadEpisodeSubtitles(); + + const modals = useModals(); + + const download = useCallback( + (item: Item.Episode, result: SearchResultType) => { + const { language, - hi, + hearing_impaired: hi, forced, provider, subtitle, - // eslint-disable-next-line camelcase original_format: originalFormat, + } = result; + const { sonarrSeriesId: seriesId, sonarrEpisodeId: episodeId } = item; + + return mutateAsync({ + seriesId, + episodeId, + form: { + language, + hi, + forced, + provider, + subtitle, + // eslint-disable-next-line camelcase + original_format: originalFormat, + }, + }); + }, + [mutateAsync], + ); + + const SubtitlesCell = React.memo( + ({ episode }: { episode: Item.Episode }) => { + const seriesId = episode.sonarrSeriesId; + + const elements = useMemo(() => { + const episodeId = episode.sonarrEpisodeId; + + const missing = episode.missing_subtitles.map((val, idx) => ( + + )); + + let rawSubtitles = episode.subtitles; + if (onlyDesired) { + rawSubtitles = filterSubtitleBy(rawSubtitles, profileItems); + } + + const subtitles = rawSubtitles.map((val, idx) => ( + + )); + + return [...missing, ...subtitles]; + }, [episode, seriesId]); + + return ( + + {elements} + + ); + }, + ); + + const columns = useMemo[]>( + () => [ + { + id: "monitored", + cell: ({ + row: { + original: { monitored }, + }, + }) => { + return ( + + ); + }, }, - }); - }, - [mutateAsync], - ); - - const columns: Column[] = useMemo[]>( - () => [ - { - accessor: "monitored", - Cell: (row) => { - return ( - - ); + { + header: "", + accessorKey: "season", + cell: ({ + row: { + original: { season }, + }, + }) => { + return Season {season}; + }, }, - }, - { - accessor: "season", - Cell: (row) => { - return Season {row.value}; + { + header: "Episode", + accessorKey: "episode", }, - }, - { - Header: "Episode", - accessor: "episode", - }, - { - Header: "Title", - accessor: "title", - Cell: ({ value, row }) => { - return ( - - {value} - - ); + { + header: "Title", + accessorKey: "title", + cell: ({ + row: { + original: { sceneName, title }, + }, + }) => { + return ( + + {title} + + ); + }, }, - }, - { - Header: "Audio", - accessor: "audio_language", - Cell: ({ value }) => , - }, - { - Header: "Subtitles", - accessor: "missing_subtitles", - Cell: ({ row }) => { - const episode = row.original; - - const seriesId = episode.sonarrSeriesId; - - const elements = useMemo(() => { - const episodeId = episode.sonarrEpisodeId; - - const missing = episode.missing_subtitles.map((val, idx) => ( - - )); - - let rawSubtitles = episode.subtitles; - if (onlyDesired) { - rawSubtitles = filterSubtitleBy(rawSubtitles, profileItems); - } - - const subtitles = rawSubtitles.map((val, idx) => ( - - )); - - return [...missing, ...subtitles]; - }, [episode, seriesId]); - - return ( - - {elements} - - ); + { + header: "Audio", + accessorKey: "audio_language", + cell: ({ + row: { + original: { audio_language: audioLanguage }, + }, + }) => , }, - }, - { - Header: "Actions", - accessor: "sonarrEpisodeId", - Cell: ({ row }) => { - const modals = useModals(); - return ( - - { - modals.openContextModal(EpisodeSearchModal, { - item: row.original, - download, - query: useEpisodesProvider, - }); - }} - icon={faUser} - > - { - modals.openContextModal( - EpisodeHistoryModal, - { - episode: row.original, - }, - { - title: `History - ${row.original.title}`, - }, - ); - }} - icon={faHistory} - > - - ); + { + header: "Subtitles", + accessorKey: "missing_subtitles", + cell: ({ row: { original } }) => { + return ; + }, }, - }, - ], - [onlyDesired, profileItems, disabled, download], - ); - - const maxSeason = useMemo( - () => - episodes?.reduce( - (prev, curr) => Math.max(prev, curr.season), - 0, - ) ?? 0, - [episodes], - ); - - const instance = useRef | null>(null); - - useEffect(() => { - if (instance.current) { - if (initial) { - // start with all rows collapsed - instance.current.toggleAllRowsExpanded(false); - // expand the last/current season on initial display - instance.current.toggleRowExpanded([`season:${maxSeason}`], true); - } else { - if (expand !== undefined) { - instance.current.toggleAllRowsExpanded(expand); - } - } - } - }, [maxSeason, expand, initial]); - - return ( - - ); -}; + { + header: "Actions", + cell: ({ row }) => { + return ( + + { + modals.openContextModal(EpisodeSearchModal, { + item: row.original, + download, + query: useEpisodesProvider, + }); + }} + icon={faUser} + > + { + modals.openContextModal( + EpisodeHistoryModal, + { + episode: row.original, + }, + { + title: `History - ${row.original.title}`, + }, + ); + }} + icon={faHistory} + > + + ); + }, + }, + ], + [disabled, download, modals, SubtitlesCell], + ); + + const maxSeason = useMemo( + () => + episodes?.reduce( + (prev, curr) => Math.max(prev, curr.season), + 0, + ) ?? 0, + [episodes], + ); + + useEffect(() => { + tableRef?.current?.setExpanded(() => ({ [`season:${maxSeason}`]: true })); + }, [tableRef, maxSeason]); + + return ( + + ); + }, +); export default Table; diff --git a/frontend/src/pages/History/Movies/index.tsx b/frontend/src/pages/History/Movies/index.tsx index 39365e348..92d1aa280 100644 --- a/frontend/src/pages/History/Movies/index.tsx +++ b/frontend/src/pages/History/Movies/index.tsx @@ -1,7 +1,6 @@ /* eslint-disable camelcase */ import { FunctionComponent, useMemo } from "react"; import { Link } from "react-router-dom"; -import { Column } from "react-table"; import { Anchor, Badge, Text } from "@mantine/core"; import { faFileExcel, @@ -9,6 +8,7 @@ import { faRecycle, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { useMovieAddBlacklist, useMovieHistoryPagination } from "@/apis/hooks"; import { MutateAction } from "@/components/async"; import { HistoryIcon } from "@/components/bazarr"; @@ -18,32 +18,40 @@ import TextPopover from "@/components/TextPopover"; import HistoryView from "@/pages/views/HistoryView"; const MoviesHistoryView: FunctionComponent = () => { - const columns: Column[] = useMemo[]>( + const addToBlacklist = useMovieAddBlacklist(); + + const columns = useMemo[]>( () => [ { - accessor: "action", - Cell: (row) => , + id: "action", + cell: ({ row }) => ( + + ), }, { - Header: "Name", - accessor: "title", - Cell: ({ row, value }) => { + header: "Name", + accessorKey: "title", + cell: ({ row }) => { const target = `/movies/${row.original.radarrId}`; return ( - {value} + {row.original.title} ); }, }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { return ( - + ); } else { @@ -52,13 +60,13 @@ const MoviesHistoryView: FunctionComponent = () => { }, }, { - Header: "Score", - accessor: "score", + header: "Score", + accessorKey: "score", }, { - Header: "Match", - accessor: "matches", - Cell: (row) => { + header: "Match", + accessorKey: "matches", + cell: (row) => { const { matches, dont_matches: dont } = row.row.original; if (matches.length || dont.length) { return ( @@ -74,13 +82,17 @@ const MoviesHistoryView: FunctionComponent = () => { }, }, { - Header: "Date", - accessor: "timestamp", - Cell: (row) => { - if (row.value) { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp }, + }, + }) => { + if (timestamp) { return ( - - {row.value} + + {timestamp} ); } else { @@ -89,21 +101,29 @@ const MoviesHistoryView: FunctionComponent = () => { }, }, { - Header: "Info", - accessor: "description", - Cell: ({ value }) => { + header: "Info", + accessorKey: "description", + cell: ({ + row: { + original: { description }, + }, + }) => { return ( - + ); }, }, { - Header: "Upgrade", - accessor: "upgradable", - Cell: (row) => { - if (row.value) { + header: "Upgrade", + accessorKey: "upgradable", + cell: ({ + row: { + original: { upgradable }, + }, + }) => { + if (upgradable) { return ( @@ -115,20 +135,25 @@ const MoviesHistoryView: FunctionComponent = () => { }, }, { - Header: "Blacklist", - accessor: "blacklisted", - Cell: ({ row, value }) => { - const add = useMovieAddBlacklist(); - const { radarrId, provider, subs_id, language, subtitles_path } = - row.original; + header: "Blacklist", + accessorKey: "blacklisted", + cell: ({ row }) => { + const { + blacklisted, + radarrId, + provider, + subs_id, + language, + subtitles_path, + } = row.original; if (subs_id && provider && language) { return ( ({ id: radarrId, form: { @@ -146,7 +171,7 @@ const MoviesHistoryView: FunctionComponent = () => { }, }, ], - [], + [addToBlacklist], ); const query = useMovieHistoryPagination(); diff --git a/frontend/src/pages/History/Series/index.tsx b/frontend/src/pages/History/Series/index.tsx index 67f18b9d9..a5d75516a 100644 --- a/frontend/src/pages/History/Series/index.tsx +++ b/frontend/src/pages/History/Series/index.tsx @@ -1,7 +1,6 @@ /* eslint-disable camelcase */ import { FunctionComponent, useMemo } from "react"; import { Link } from "react-router-dom"; -import { Column } from "react-table"; import { Anchor, Badge, Text } from "@mantine/core"; import { faFileExcel, @@ -9,6 +8,7 @@ import { faRecycle, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { useEpisodeAddBlacklist, useEpisodeHistoryPagination, @@ -21,44 +21,60 @@ import TextPopover from "@/components/TextPopover"; import HistoryView from "@/pages/views/HistoryView"; const SeriesHistoryView: FunctionComponent = () => { - const columns: Column[] = useMemo[]>( + const addToBlacklist = useEpisodeAddBlacklist(); + + const columns = useMemo[]>( () => [ { - accessor: "action", - Cell: ({ value }) => , + id: "action", + cell: ({ row: { original } }) => ( + + ), }, { - Header: "Series", - accessor: "seriesTitle", - Cell: (row) => { - const target = `/series/${row.row.original.sonarrSeriesId}`; + header: "Series", + accessorKey: "seriesTitle", + cell: ({ + row: { + original: { seriesTitle, sonarrSeriesId }, + }, + }) => { + const target = `/series/${sonarrSeriesId}`; return ( - {row.value} + {seriesTitle} ); }, }, { - Header: "Episode", - accessor: "episode_number", + header: "Episode", + accessorKey: "episode_number", }, { - Header: "Title", - accessor: "episodeTitle", - Cell: ({ value }) => { - return {value}; + header: "Title", + accessorKey: "episodeTitle", + cell: ({ + row: { + original: { episodeTitle }, + }, + }) => { + return {episodeTitle}; }, }, { - Header: "Language", - accessor: "language", - Cell: ({ value }) => { - if (value) { + header: "Language", + accessorKey: "language", + cell: ({ + row: { + original: { language }, + }, + }) => { + if (language) { return ( - + ); } else { @@ -67,13 +83,13 @@ const SeriesHistoryView: FunctionComponent = () => { }, }, { - Header: "Score", - accessor: "score", + header: "Score", + accessorKey: "score", }, { - Header: "Match", - accessor: "matches", - Cell: (row) => { + header: "Match", + accessorKey: "matches", + cell: (row) => { const { matches, dont_matches: dont } = row.row.original; if (matches.length || dont.length) { return ( @@ -89,13 +105,17 @@ const SeriesHistoryView: FunctionComponent = () => { }, }, { - Header: "Date", - accessor: "timestamp", - Cell: (row) => { - if (row.value) { + header: "Date", + accessorKey: "timestamp", + cell: ({ + row: { + original: { timestamp, parsed_timestamp }, + }, + }) => { + if (timestamp) { return ( - - {row.value} + + {timestamp} ); } else { @@ -104,21 +124,29 @@ const SeriesHistoryView: FunctionComponent = () => { }, }, { - Header: "Info", - accessor: "description", - Cell: ({ row, value }) => { + header: "Info", + accessorKey: "description", + cell: ({ + row: { + original: { description }, + }, + }) => { return ( - + ); }, }, { - Header: "Upgrade", - accessor: "upgradable", - Cell: (row) => { - if (row.value) { + header: "Upgrade", + accessorKey: "upgradable", + cell: ({ + row: { + original: { upgradable }, + }, + }) => { + if (upgradable) { return ( @@ -130,9 +158,9 @@ const SeriesHistoryView: FunctionComponent = () => { }, }, { - Header: "Blacklist", - accessor: "blacklisted", - Cell: ({ row, value }) => { + header: "Blacklist", + accessorKey: "blacklisted", + cell: ({ row }) => { const { sonarrEpisodeId, sonarrSeriesId, @@ -140,16 +168,15 @@ const SeriesHistoryView: FunctionComponent = () => { subs_id, language, subtitles_path, + blacklisted, } = row.original; - const add = useEpisodeAddBlacklist(); - if (subs_id && provider && language) { return ( ({ seriesId: sonarrSeriesId, episodeId: sonarrEpisodeId, @@ -168,7 +195,7 @@ const SeriesHistoryView: FunctionComponent = () => { }, }, ], - [], + [addToBlacklist], ); const query = useEpisodeHistoryPagination(); diff --git a/frontend/src/pages/Movies/Details/table.tsx b/frontend/src/pages/Movies/Details/table.tsx index 03593102c..7d0c20a30 100644 --- a/frontend/src/pages/Movies/Details/table.tsx +++ b/frontend/src/pages/Movies/Details/table.tsx @@ -1,13 +1,14 @@ -import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; +import React, { FunctionComponent, useMemo } from "react"; import { Badge, Text, TextProps } from "@mantine/core"; import { faEllipsis, faSearch } from "@fortawesome/free-solid-svg-icons"; +import { ColumnDef } from "@tanstack/react-table"; import { isString } from "lodash"; import { useMovieSubtitleModification } from "@/apis/hooks"; import { useShowOnlyDesired } from "@/apis/hooks/site"; -import { Action, SimpleTable } from "@/components"; +import { Action } from "@/components"; import Language from "@/components/bazarr/Language"; import SubtitleToolsMenu from "@/components/SubtitleToolsMenu"; +import SimpleTable from "@/components/tables/SimpleTable"; import { task, TaskGroup } from "@/modules/task"; import { filterSubtitleBy, toPython } from "@/utilities"; import { useProfileItemsToLanguages } from "@/utilities/languages"; @@ -33,35 +34,125 @@ const Table: FunctionComponent = ({ movie, profile, disabled }) => { const profileItems = useProfileItemsToLanguages(profile); - const columns: Column[] = useMemo[]>( + const { download, remove } = useMovieSubtitleModification(); + + const CodeCell = React.memo(({ item }: { item: Subtitle }) => { + const { code2, path, hi, forced } = item; + + const selections = useMemo(() => { + const list: FormType.ModifySubtitle[] = []; + + if (path && !isSubtitleMissing(path) && movie !== null) { + list.push({ + type: "movie", + path, + id: movie.radarrId, + language: code2, + forced: toPython(forced), + hi: toPython(hi), + }); + } + + return list; + }, [code2, path, forced, hi]); + + if (movie === null) { + return null; + } + + const { radarrId } = movie; + + if (isSubtitleMissing(path)) { + return ( + { + task.create( + movie.title, + TaskGroup.SearchSubtitle, + download.mutateAsync, + { + radarrId, + form: { + language: code2, + forced, + hi, + }, + }, + ); + }} + > + ); + } + + return ( + { + if (action === "delete" && path) { + task.create( + movie.title, + TaskGroup.DeleteSubtitle, + remove.mutateAsync, + { + radarrId, + form: { + language: code2, + forced, + hi, + path, + }, + }, + ); + } else if (action === "search") { + throw new Error("This shouldn't happen, please report the bug"); + } + }} + > + + + ); + }); + + const columns = useMemo[]>( () => [ { - Header: "Subtitle Path", - accessor: "path", - Cell: ({ value }) => { + header: "Subtitle Path", + accessorKey: "path", + cell: ({ + row: { + original: { path }, + }, + }) => { const props: TextProps = { className: "table-primary", }; - if (isSubtitleTrack(value)) { + if (isSubtitleTrack(path)) { return ( Video File Subtitle Track ); - } else if (isSubtitleMissing(value)) { + } else if (isSubtitleMissing(path)) { return ( - {value} + {path} ); } else { - return {value}; + return {path}; } }, }, { - Header: "Language", - accessor: "name", - Cell: ({ row }) => { + header: "Language", + accessorKey: "name", + cell: ({ row }) => { if (row.original.path === missingText) { return ( @@ -78,99 +169,13 @@ const Table: FunctionComponent = ({ movie, profile, disabled }) => { }, }, { - accessor: "code2", - Cell: ({ row }) => { - const { - original: { code2, path, hi, forced }, - } = row; - - const { download, remove } = useMovieSubtitleModification(); - - const selections = useMemo(() => { - const list: FormType.ModifySubtitle[] = []; - - if (path && !isSubtitleMissing(path) && movie !== null) { - list.push({ - type: "movie", - path, - id: movie.radarrId, - language: code2, - forced: toPython(forced), - hi: toPython(hi), - }); - } - - return list; - }, [code2, path, forced, hi]); - - if (movie === null) { - return null; - } - - const { radarrId } = movie; - - if (isSubtitleMissing(path)) { - return ( - { - task.create( - movie.title, - TaskGroup.SearchSubtitle, - download.mutateAsync, - { - radarrId, - form: { - language: code2, - forced, - hi, - }, - }, - ); - }} - > - ); - } - - return ( - { - if (action === "delete" && path) { - task.create( - movie.title, - TaskGroup.DeleteSubtitle, - remove.mutateAsync, - { - radarrId, - form: { - language: code2, - forced, - hi, - path, - }, - }, - ); - } else if (action === "search") { - throw new Error( - "This shouldn't happen, please report the bug", - ); - } - }} - > - - - ); + id: "code2", + cell: ({ row: { original } }) => { + return ; }, }, ], - [movie, disabled], + [CodeCell], ); const data: Subtitle[] = useMemo(() => { diff --git a/frontend/src/pages/Movies/Editor.tsx b/frontend/src/pages/Movies/Editor.tsx index 0c568a5b1..1ec84a52c 100644 --- a/frontend/src/pages/Movies/Editor.tsx +++ b/frontend/src/pages/Movies/Editor.tsx @@ -1,6 +1,7 @@ import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; +import { Checkbox } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; +import { ColumnDef } from "@tanstack/react-table"; import { useMovieModification, useMovies } from "@/apis/hooks"; import { QueryOverlay } from "@/components/async"; import { AudioList } from "@/components/bazarr"; @@ -11,32 +12,63 @@ const MovieMassEditor: FunctionComponent = () => { const query = useMovies(); const mutation = useMovieModification(); - const columns = useMemo[]>( + useDocumentTitle("Movies - Bazarr (Mass Editor)"); + + const columns = useMemo[]>( () => [ { - Header: "Name", - accessor: "title", + id: "selection", + header: ({ table }) => { + return ( + + ); + }, + cell: ({ row: { index, getIsSelected, getToggleSelectedHandler } }) => { + return ( + + ); + }, + }, + { + header: "Name", + accessorKey: "title", }, { - Header: "Audio", - accessor: "audio_language", - Cell: ({ value }) => { - return ; + header: "Audio", + accessorKey: "audio_language", + cell: ({ + row: { + original: { audio_language: audioLanguage }, + }, + }) => { + return ; }, }, { - Header: "Languages Profile", - accessor: "profileId", - Cell: ({ value }) => { - return ; + header: "Languages Profile", + accessorKey: "profileId", + cell: ({ + row: { + original: { profileId }, + }, + }) => { + return ; }, }, ], [], ); - useDocumentTitle("Movies - Bazarr (Mass Editor)"); - return ( { + const modifyMovie = useMovieModification(); + + const modals = useModals(); + const query = useMoviesPagination(); - const columns: Column[] = useMemo[]>( + const columns = useMemo[]>( () => [ { - accessor: "monitored", - Cell: ({ value }) => ( + id: "monitored", + cell: ({ + row: { + original: { monitored }, + }, + }) => ( ), }, { - Header: "Name", - accessor: "title", - Cell: ({ row, value }) => { - const target = `/movies/${row.original.radarrId}`; + header: "Name", + accessorKey: "title", + cell: ({ + row: { + original: { title, radarrId }, + }, + }) => { + const target = `/movies/${radarrId}`; return ( - {value} + {title} ); }, }, { - Header: "Audio", - accessor: "audio_language", - Cell: ({ value }) => { - return ; + header: "Audio", + accessorKey: "audio_language", + cell: ({ + row: { + original: { audio_language: audioLanguage }, + }, + }) => { + return ; }, }, { - Header: "Languages Profile", - accessor: "profileId", - Cell: ({ value }) => { + header: "Languages Profile", + accessorKey: "profileId", + cell: ({ + row: { + original: { profileId }, + }, + }) => { return ( - + ); }, }, { - Header: "Missing Subtitles", - accessor: "missing_subtitles", - Cell: (row) => { - const missing = row.value; + header: "Missing Subtitles", + accessorKey: "missing_subtitles", + cell: ({ + row: { + original: { missing_subtitles: missingSubtitles }, + }, + }) => { return ( <> - {missing.map((v) => ( + {missingSubtitles.map((v) => ( { }, }, { - accessor: "radarrId", - Cell: ({ row }) => { - const modals = useModals(); - const mutation = useMovieModification(); + id: "radarrId", + cell: ({ row }) => { return ( { modals.openContextModal( ItemEditModal, { - mutation, + mutation: modifyMovie, item: row.original, }, { @@ -105,7 +129,7 @@ const MovieView: FunctionComponent = () => { }, }, ], - [], + [modals, modifyMovie], ); useDocumentTitle("Movies - Bazarr"); diff --git a/frontend/src/pages/Series/Editor.tsx b/frontend/src/pages/Series/Editor.tsx index 239481069..45a277d17 100644 --- a/frontend/src/pages/Series/Editor.tsx +++ b/frontend/src/pages/Series/Editor.tsx @@ -1,6 +1,7 @@ import { FunctionComponent, useMemo } from "react"; -import { Column } from "react-table"; +import { Checkbox } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; +import { ColumnDef } from "@tanstack/react-table"; import { useSeries, useSeriesModification } from "@/apis/hooks"; import { QueryOverlay } from "@/components/async"; import { AudioList } from "@/components/bazarr"; @@ -11,24 +12,55 @@ const SeriesMassEditor: FunctionComponent = () => { const query = useSeries(); const mutation = useSeriesModification(); - const columns = useMemo[]>( + const columns = useMemo[]>( () => [ { - Header: "Name", - accessor: "title", + id: "selection", + header: ({ table }) => { + return ( + + ); + }, + cell: ({ row: { index, getIsSelected, getToggleSelectedHandler } }) => { + return ( + + ); + }, + }, + { + header: "Name", + accessorKey: "title", }, { - Header: "Audio", - accessor: "audio_language", - Cell: ({ value }) => { - return ; + header: "Audio", + accessorKey: "audio_language", + cell: ({ + row: { + original: { audio_language: audioLanguage }, + }, + }) => { + return ; }, }, { - Header: "Languages Profile", - accessor: "profileId", - Cell: ({ value }) => { - return ; + header: "Languages Profile", + accessorKey: "profileId", + cell: ({ + row: { + original: { profileId }, + }, + }) => { + return ; }, }, ], diff --git a/frontend/src/pages/Series/index.tsx b/frontend/src/pages/Series/index.tsx index 92f63c9ab..229082444 100644 --- a/frontend/src/pages/Series/index.tsx +++ b/frontend/src/pages/Series/index.tsx @@ -1,11 +1,11 @@ import { FunctionComponent, useMemo } from "react"; import { Link } from "react-router-dom"; -import { Column } from "react-table"; import { Anchor, Container, Progress } from "@mantine/core"; import { useDocumentTitle } from "@mantine/hooks"; import { faBookmark as farBookmark } from "@fortawesome/free-regular-svg-icons"; import { faBookmark, faWrench } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { useSeriesModification, useSeriesPagination } from "@/apis/hooks"; import { Action } from "@/components"; import LanguageProfileName from "@/components/bazarr/LanguageProfile"; @@ -18,42 +18,51 @@ const SeriesView: FunctionComponent = () => { const query = useSeriesPagination(); - const columns: Column[] = useMemo[]>( + const modals = useModals(); + + const columns = useMemo[]>( () => [ { - accessor: "monitored", - Cell: ({ value }) => ( + id: "monitored", + cell: ({ + row: { + original: { monitored }, + }, + }) => ( ), }, { - Header: "Name", - accessor: "title", - Cell: ({ row, value }) => { - const target = `/series/${row.original.sonarrSeriesId}`; + header: "Name", + accessorKey: "title", + cell: ({ row: { original } }) => { + const target = `/series/${original.sonarrSeriesId}`; return ( - {value} + {original.title} ); }, }, { - Header: "Languages Profile", - accessor: "profileId", - Cell: ({ value }) => { + header: "Languages Profile", + accessorKey: "profileId", + cell: ({ row: { original } }) => { return ( - + ); }, }, { - Header: "Episodes", - accessor: "episodeFileCount", - Cell: (row) => { + header: "Episodes", + accessorKey: "episodeFileCount", + cell: (row) => { const { episodeFileCount, episodeMissingCount, profileId, title } = row.row.original; let progress = 0; @@ -80,9 +89,8 @@ const SeriesView: FunctionComponent = () => { }, }, { - accessor: "sonarrSeriesId", - Cell: ({ row: { original } }) => { - const modals = useModals(); + id: "sonarrSeriesId", + cell: ({ row: { original } }) => { return ( { }, }, ], - [mutation], + [mutation, modals], ); useDocumentTitle("Series - Bazarr"); diff --git a/frontend/src/pages/Settings/Languages/equals.tsx b/frontend/src/pages/Settings/Languages/equals.tsx index dae20a75a..08642f27e 100644 --- a/frontend/src/pages/Settings/Languages/equals.tsx +++ b/frontend/src/pages/Settings/Languages/equals.tsx @@ -1,11 +1,12 @@ import { FunctionComponent, useCallback, useMemo } from "react"; -import { Column } from "react-table"; import { Button, Checkbox } from "@mantine/core"; import { faEquals, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { ColumnDef } from "@tanstack/react-table"; import { useLanguages } from "@/apis/hooks"; -import { Action, SimpleTable } from "@/components"; +import { Action } from "@/components"; import LanguageSelector from "@/components/bazarr/LanguageSelector"; +import SimpleTable from "@/components/tables/SimpleTable"; import { languageEqualsKey } from "@/pages/Settings/keys"; import { useFormActions } from "@/pages/Settings/utilities/FormValues"; import { useSettingValue } from "@/pages/Settings/utilities/hooks"; @@ -196,22 +197,22 @@ const EqualsTable: FunctionComponent = () => { [equals, setEquals], ); - const columns = useMemo[]>( + const columns = useMemo[]>( () => [ { - Header: "Source", + header: "Source", id: "source-lang", - accessor: "source", - Cell: ({ value: { content }, row }) => { + accessorKey: "source", + cell: ({ row: { original, index } }) => { return ( { if (result !== null) { - update(row.index, { - ...row.original, - source: { ...row.original.source, content: result }, + update(index, { + ...original, + source: { ...original.source, content: result }, }); } }} @@ -221,12 +222,11 @@ const EqualsTable: FunctionComponent = () => { }, { id: "source-hi", - accessor: "source", - Cell: ({ value: { hi }, row }) => { + cell: ({ row }) => { return ( { update(row.index, { ...row.original, @@ -243,12 +243,11 @@ const EqualsTable: FunctionComponent = () => { }, { id: "source-forced", - accessor: "source", - Cell: ({ value: { forced }, row }) => { + cell: ({ row }) => { return ( { update(row.index, { ...row.original, @@ -265,19 +264,18 @@ const EqualsTable: FunctionComponent = () => { }, { id: "equal-icon", - Cell: () => { + cell: () => { return ; }, }, { - Header: "Target", + header: "Target", id: "target-lang", - accessor: "target", - Cell: ({ value: { content }, row }) => { + cell: ({ row }) => { return ( { if (result !== null) { update(row.index, { @@ -292,12 +290,11 @@ const EqualsTable: FunctionComponent = () => { }, { id: "target-hi", - accessor: "target", - Cell: ({ value: { hi }, row }) => { + cell: ({ row }) => { return ( { update(row.index, { ...row.original, @@ -314,12 +311,11 @@ const EqualsTable: FunctionComponent = () => { }, { id: "target-forced", - accessor: "target", - Cell: ({ value: { forced }, row }) => { + cell: ({ row }) => { return ( { update(row.index, { ...row.original, @@ -336,8 +332,7 @@ const EqualsTable: FunctionComponent = () => { }, { id: "action", - accessor: "target", - Cell: ({ row }) => { + cell: ({ row }) => { return ( { const updateProfile = useCallback( (profile: Language.Profile) => { const list = [...profiles]; + const idx = list.findIndex((v) => v.profileId === profile.profileId); if (idx !== -1) { @@ -57,18 +59,20 @@ const Table: FunctionComponent = () => { submitProfiles(fn(list)); }); - const columns = useMemo[]>( + const columns = useMemo[]>( () => [ { - Header: "Name", - accessor: "name", + header: "Name", + accessorKey: "name", }, { - Header: "Languages", - accessor: "items", - Cell: (row) => { - const items = row.value; - const cutoff = row.row.original.cutoff; + header: "Languages", + accessorKey: "items", + cell: ({ + row: { + original: { items, cutoff }, + }, + }) => { return ( {items.map((v) => { @@ -82,16 +86,19 @@ const Table: FunctionComponent = () => { }, }, { - Header: "Must contain", - accessor: "mustContain", - Cell: (row) => { - const items = row.value; - if (!items) { + header: "Must contain", + accessorKey: "mustContain", + cell: ({ + row: { + original: { mustContain }, + }, + }) => { + if (!mustContain) { return null; } return ( <> - {items.map((v, idx) => { + {mustContain.map((v, idx) => { return ( {v} @@ -103,16 +110,19 @@ const Table: FunctionComponent = () => { }, }, { - Header: "Must not contain", - accessor: "mustNotContain", - Cell: (row) => { - const items = row.value; - if (!items) { + header: "Must not contain", + accessorKey: "mustNotContain", + cell: ({ + row: { + original: { mustNotContain }, + }, + }) => { + if (!mustNotContain) { return null; } return ( <> - {items.map((v, idx) => { + {mustNotContain.map((v, idx) => { return ( {v} @@ -124,8 +134,8 @@ const Table: FunctionComponent = () => { }, }, { - accessor: "profileId", - Cell: ({ row }) => { + id: "profileId", + cell: ({ row }) => { const profile = row.original; return ( @@ -160,7 +170,7 @@ const Table: FunctionComponent = () => { return ( <> - +