diff options
author | JayZed <[email protected]> | 2024-02-19 21:14:42 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2024-02-19 21:14:42 -0500 |
commit | d5466fff2304e863e62fe2dfc62d9e88bdeb4068 (patch) | |
tree | 9c4bf6e41e5f45e6c09dcc56ecadf6a262ca4a4b /frontend | |
parent | ad8f116c78688ab038e834a8ad3a3b4c7bfee0c6 (diff) | |
download | bazarr-d5466fff2304e863e62fe2dfc62d9e88bdeb4068.tar.gz bazarr-d5466fff2304e863e62fe2dfc62d9e88bdeb4068.zip |
Added log level/filter settings to Logs page
Diffstat (limited to 'frontend')
-rw-r--r-- | frontend/src/components/tables/PageControl.tsx | 7 | ||||
-rw-r--r-- | frontend/src/components/tables/PageTable.tsx | 4 | ||||
-rw-r--r-- | frontend/src/pages/Settings/General/index.tsx | 16 | ||||
-rw-r--r-- | frontend/src/pages/Settings/components/LayoutModal.tsx | 99 | ||||
-rw-r--r-- | frontend/src/pages/Settings/components/index.tsx | 1 | ||||
-rw-r--r-- | frontend/src/pages/System/Logs/index.tsx | 84 | ||||
-rw-r--r-- | frontend/src/types/settings.d.ts | 8 |
7 files changed, 215 insertions, 4 deletions
diff --git a/frontend/src/components/tables/PageControl.tsx b/frontend/src/components/tables/PageControl.tsx index d00edcef6..0767593de 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 } from "react"; +import { FunctionComponent, useEffect } from "react"; interface Props { count: number; index: number; @@ -22,6 +22,11 @@ const PageControl: FunctionComponent<Props> = ({ const isLoading = useIsLoading(); + // Jump to first page if total page count changes + useEffect(() => { + goto(0); + }, [total, goto]); + return ( <Group p={16} position="apart"> <Text size="sm"> diff --git a/frontend/src/components/tables/PageTable.tsx b/frontend/src/components/tables/PageTable.tsx index fa958b28f..d84940857 100644 --- a/frontend/src/components/tables/PageTable.tsx +++ b/frontend/src/components/tables/PageTable.tsx @@ -1,4 +1,5 @@ import { ScrollToTop } from "@/utilities"; +import { usePageSize } from "@/utilities/storage"; import { useEffect } from "react"; import { usePagination, useTable } from "react-table"; import BaseTable from "./BaseTable"; @@ -22,6 +23,9 @@ export default function PageTable<T extends object>(props: Props<T>) { ...(plugins ?? []) ); + // use page size as specified in UI settings + instance.state.pageSize = usePageSize(); + if (instanceRef) { instanceRef.current = instance; } diff --git a/frontend/src/pages/Settings/General/index.tsx b/frontend/src/pages/Settings/General/index.tsx index 96336a250..8cc5ea8c3 100644 --- a/frontend/src/pages/Settings/General/index.tsx +++ b/frontend/src/pages/Settings/General/index.tsx @@ -177,6 +177,22 @@ const SettingsGeneralView: FunctionComponent = () => { <Section header="Logging"> <Check label="Debug" settingKey="settings-general-debug"></Check> <Message>Debug logging should only be enabled temporarily</Message> + <Text + label="Include Filter" + settingKey="settings-log-include_filter" + ></Text> + <Text + label="Exclude Filter" + settingKey="settings-log-exclude_filter" + ></Text> + <Check + label="Use Regular Expressions (Regex)" + settingKey="settings-log-use_regex" + ></Check> + <Check + label="Ignore Case" + settingKey="settings-log-ignore_case" + ></Check> </Section> <Section header="Backups"> <File diff --git a/frontend/src/pages/Settings/components/LayoutModal.tsx b/frontend/src/pages/Settings/components/LayoutModal.tsx new file mode 100644 index 000000000..3ec074e09 --- /dev/null +++ b/frontend/src/pages/Settings/components/LayoutModal.tsx @@ -0,0 +1,99 @@ +import { useSettingsMutation, useSystemSettings } from "@/apis/hooks"; +import { LoadingProvider } from "@/contexts"; +import { useOnValueChange } from "@/utilities"; +import { LOG } from "@/utilities/console"; +import { + Button, + Container, + Divider, + Group, + LoadingOverlay, + 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"; + +interface Props { + children: ReactNode; + callbackModal: (value: boolean) => void; +} + +const LayoutModal: FunctionComponent<Props> = (props) => { + const { children, callbackModal } = props; + + const { data: settings, isLoading, isRefetching } = useSystemSettings(); + const { mutate, isLoading: isMutating } = useSettingsMutation(); + + const form = useForm<FormValues>({ + initialValues: { + settings: {}, + hooks: {}, + }, + }); + + useOnValueChange(isRefetching, (value) => { + if (!value) { + form.reset(); + } + }); + + const submit = useCallback( + (values: FormValues) => { + const { settings, hooks } = values; + if (Object.keys(settings).length > 0) { + const settingsToSubmit = { ...settings }; + runHooks(hooks, settingsToSubmit); + LOG("info", "submitting settings", settingsToSubmit); + mutate(settingsToSubmit); + // wait for settings to be validated before callback + // let the user see the spinning indicator on the Save button before the modal closes + setTimeout(() => { + callbackModal(true); + }, 500); + } + }, + [mutate, callbackModal] + ); + + const totalStagedCount = useMemo(() => { + return Object.keys(form.values.settings).length; + }, [form.values.settings]); + + return ( + <SettingsProvider value={settings ?? null}> + <LoadingProvider value={isLoading || isMutating}> + <form onSubmit={form.onSubmit(submit)} style={{ position: "relative" }}> + <LoadingOverlay visible={settings === undefined}></LoadingOverlay> + <FormContext.Provider value={form}> + <Container size="xl" mx={0}> + {children} + </Container> + </FormContext.Provider> + <Space h="md" /> + <Divider></Divider> + <Space h="md" /> + <Group position="right"> + <Button + type="submit" + disabled={totalStagedCount === 0} + loading={isMutating} + > + Save + </Button> + <Button + onClick={() => { + callbackModal(true); + }} + > + Close + </Button> + </Group> + </form> + </LoadingProvider> + </SettingsProvider> + ); +}; + +export default LayoutModal; diff --git a/frontend/src/pages/Settings/components/index.tsx b/frontend/src/pages/Settings/components/index.tsx index 15b60db29..9502f4366 100644 --- a/frontend/src/pages/Settings/components/index.tsx +++ b/frontend/src/pages/Settings/components/index.tsx @@ -65,6 +65,7 @@ export const URLTestButton: FunctionComponent<{ export * from "./Card"; export * from "./Layout"; export { default as Layout } from "./Layout"; +export { default as LayoutModal } from "./LayoutModal"; export * from "./Message"; export * from "./Section"; export * from "./collapse"; diff --git a/frontend/src/pages/System/Logs/index.tsx b/frontend/src/pages/System/Logs/index.tsx index 8d12847d7..d77e102d8 100644 --- a/frontend/src/pages/System/Logs/index.tsx +++ b/frontend/src/pages/System/Logs/index.tsx @@ -1,10 +1,17 @@ -import { useDeleteLogs, useSystemLogs } from "@/apis/hooks"; +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 { faDownload, faSync, faTrash } from "@fortawesome/free-solid-svg-icons"; -import { Container, Group } from "@mantine/core"; +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 Table from "./table"; @@ -20,6 +27,61 @@ const SystemLogsView: FunctionComponent = () => { useDocumentTitle("Logs - Bazarr (System)"); + const { data: settings } = useSystemSettings(); + const modals = useModals(); + + const suffix = () => { + const include = settings?.log.include_filter; + const exclude = settings?.log.exclude_filter; + const includeIndex = include !== "" && include !== undefined ? 1 : 0; + const excludeIndex = exclude !== "" && exclude !== undefined ? 1 : 0; + const filters = [ + ["", "I"], + ["E", "I/E"], + ]; + const filterStr = filters[excludeIndex][includeIndex]; + const debugStr = settings?.general.debug ? "Debug" : ""; + const spaceStr = debugStr !== "" && filterStr !== "" ? " " : ""; + const suffixStr = debugStr + spaceStr + filterStr; + return suffixStr; + }; + + const openFilterModal = () => { + const callbackModal = (close: boolean) => { + if (close) { + modals.closeModal(id); + } + }; + + const id = modals.openModal({ + title: "Set Log Debug and Filter Options", + children: ( + <LayoutModal callbackModal={callbackModal}> + <Stack> + <Check label="Debug" settingKey="settings-general-debug"></Check> + <Message>Debug logging should only be enabled temporarily</Message> + <Text + label="Include Filter" + settingKey="settings-log-include_filter" + ></Text> + <Text + label="Exclude Filter" + settingKey="settings-log-exclude_filter" + ></Text> + <Check + label="Use Regular Expressions (Regex)" + settingKey="settings-log-use_regex" + ></Check> + <Check + label="Ignore Case" + settingKey="settings-log-ignore_case" + ></Check> + </Stack> + </LayoutModal> + ), + }); + }; + return ( <Container fluid px={0}> <QueryOverlay result={logs}> @@ -42,6 +104,22 @@ const SystemLogsView: FunctionComponent = () => { > Empty </Toolbox.Button> + <Toolbox.Button + loading={isLoading} + icon={faFilter} + onClick={openFilterModal} + rightIcon={ + suffix() !== "" ? ( + <Badge size="xs" radius="sm"> + {suffix()} + </Badge> + ) : ( + <></> + ) + } + > + Filter + </Toolbox.Button> </Group> </Toolbox> <Table logs={data ?? []}></Table> diff --git a/frontend/src/types/settings.d.ts b/frontend/src/types/settings.d.ts index d88489a0e..d46a9734e 100644 --- a/frontend/src/types/settings.d.ts +++ b/frontend/src/types/settings.d.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ interface Settings { general: Settings.General; + log: Settings.Log; proxy: Settings.Proxy; auth: Settings.Auth; subsync: Settings.Subsync; @@ -82,6 +83,13 @@ declare namespace Settings { wanted_search_frequency_movie: number; } + interface Log { + include_filter: string; + exclude_filter: string; + ignore_case: boolean; + use_regex: boolean; + } + interface Proxy { exclude: string[]; type?: string; |