aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend
diff options
context:
space:
mode:
authorLASER-Yi <[email protected]>2022-10-25 08:22:00 +0800
committerLASER-Yi <[email protected]>2022-10-25 08:22:06 +0800
commitc08ba5f7937fcd86533a91ddc1a0675d7fc623fb (patch)
tree95d9fbd0ce9ef8e00b19c0d5cb697c0788fee038 /frontend
parent70fe14562f788c514666a7a87fa736f30aad1139 (diff)
downloadbazarr-c08ba5f7937fcd86533a91ddc1a0675d7fc623fb.tar.gz
bazarr-c08ba5f7937fcd86533a91ddc1a0675d7fc623fb.zip
Try to fix languages profiles editor by introducing a new submit hooks source in the settings page #1924v1.1.3-beta.6
Diffstat (limited to 'frontend')
-rw-r--r--frontend/src/pages/Settings/components/Layout.tsx85
-rw-r--r--frontend/src/pages/Settings/utilities/HooksProvider.tsx95
-rw-r--r--frontend/src/pages/Settings/utilities/hooks.ts10
3 files changed, 139 insertions, 51 deletions
diff --git a/frontend/src/pages/Settings/components/Layout.tsx b/frontend/src/pages/Settings/components/Layout.tsx
index 7aae8a991..623893fff 100644
--- a/frontend/src/pages/Settings/components/Layout.tsx
+++ b/frontend/src/pages/Settings/components/Layout.tsx
@@ -10,30 +10,13 @@ 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 { enabledLanguageKey, languageProfileKey } from "../keys";
import { FormContext, FormValues } from "../utilities/FormValues";
+import {
+ SubmitHooksProvider,
+ useSubmitHooksSource,
+} from "../utilities/HooksProvider";
import { SettingsProvider } from "../utilities/SettingsProvider";
-type SubmitHookType = {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- [key: string]: (value: any) => unknown;
-};
-
-export const submitHooks: SubmitHookType = {
- [languageProfileKey]: (value) => JSON.stringify(value),
- [enabledLanguageKey]: (value: Language.Info[]) => value.map((v) => v.code2),
-};
-
-function invokeHooks(settings: LooseObject) {
- for (const key in settings) {
- if (key in submitHooks) {
- const value = settings[key];
- const fn = submitHooks[key];
- settings[key] = fn(value);
- }
- }
-}
-
interface Props {
name: string;
children: ReactNode;
@@ -45,6 +28,8 @@ const Layout: FunctionComponent<Props> = (props) => {
const { data: settings, isLoading, isRefetching } = useSystemSettings();
const { mutate, isLoading: isMutating } = useSettingsMutation();
+ const submitHooks = useSubmitHooksSource();
+
const form = useForm<FormValues>({
initialValues: {
settings: {},
@@ -66,7 +51,7 @@ const Layout: FunctionComponent<Props> = (props) => {
if (Object.keys(settings).length > 0) {
const settingsToSubmit = { ...settings };
- invokeHooks(settingsToSubmit);
+ submitHooks.invoke(settingsToSubmit);
LOG("info", "submitting settings", settingsToSubmit);
mutate(settingsToSubmit);
}
@@ -77,7 +62,7 @@ const Layout: FunctionComponent<Props> = (props) => {
updateStorage(storagesToSubmit);
}
},
- [mutate, updateStorage]
+ [mutate, submitHooks, updateStorage]
);
const totalStagedCount = useMemo(() => {
@@ -100,30 +85,36 @@ const Layout: FunctionComponent<Props> = (props) => {
return (
<SettingsProvider value={settings}>
<LoadingProvider value={isLoading || isMutating}>
- <form onSubmit={form.onSubmit(submit)}>
- <Toolbox>
- <Group>
- <Toolbox.Button
- type="submit"
- icon={faSave}
- loading={isMutating}
- disabled={totalStagedCount === 0}
- rightIcon={
- <Badge size="xs" radius="sm" hidden={totalStagedCount === 0}>
- {totalStagedCount}
- </Badge>
- }
- >
- Save
- </Toolbox.Button>
- </Group>
- </Toolbox>
- <FormContext.Provider value={form}>
- <Container size="xl" mx={0}>
- {children}
- </Container>
- </FormContext.Provider>
- </form>
+ <SubmitHooksProvider value={submitHooks}>
+ <form onSubmit={form.onSubmit(submit)}>
+ <Toolbox>
+ <Group>
+ <Toolbox.Button
+ type="submit"
+ icon={faSave}
+ loading={isMutating}
+ disabled={totalStagedCount === 0}
+ rightIcon={
+ <Badge
+ size="xs"
+ radius="sm"
+ hidden={totalStagedCount === 0}
+ >
+ {totalStagedCount}
+ </Badge>
+ }
+ >
+ Save
+ </Toolbox.Button>
+ </Group>
+ </Toolbox>
+ <FormContext.Provider value={form}>
+ <Container size="xl" mx={0}>
+ {children}
+ </Container>
+ </FormContext.Provider>
+ </form>
+ </SubmitHooksProvider>
</LoadingProvider>
</SettingsProvider>
);
diff --git a/frontend/src/pages/Settings/utilities/HooksProvider.tsx b/frontend/src/pages/Settings/utilities/HooksProvider.tsx
new file mode 100644
index 000000000..2c49f174a
--- /dev/null
+++ b/frontend/src/pages/Settings/utilities/HooksProvider.tsx
@@ -0,0 +1,95 @@
+import {
+ createContext,
+ FunctionComponent,
+ useCallback,
+ useContext,
+ useMemo,
+ useRef,
+ useState,
+} from "react";
+import { enabledLanguageKey, languageProfileKey } from "../keys";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type HookType = (value: any) => unknown;
+
+export type SubmitHookType = {
+ [key: string]: HookType;
+};
+
+export type SubmitHookModifierType = {
+ add: (key: string, fn: HookType) => void;
+ remove: (key: string) => void;
+ invoke: (settings: LooseObject) => void;
+};
+
+const SubmitHooksContext = createContext<SubmitHookModifierType | null>(null);
+
+type SubmitHooksProviderProps = {
+ value: SubmitHookModifierType;
+};
+
+export const SubmitHooksProvider: FunctionComponent<
+ SubmitHooksProviderProps
+> = ({ value, children }) => {
+ return (
+ <SubmitHooksContext.Provider value={value}>
+ {children}
+ </SubmitHooksContext.Provider>
+ );
+};
+
+export function useSubmitHooks() {
+ const context = useContext(SubmitHooksContext);
+
+ if (context === null) {
+ throw new Error(
+ "useSubmitHooksModifier must be used within a SubmitHooksProvider"
+ );
+ }
+
+ return context;
+}
+
+export function useSubmitHooksSource(): SubmitHookModifierType {
+ const [submitHooks, setSubmitHooks] = useState<SubmitHookType>({
+ [languageProfileKey]: (value) => JSON.stringify(value),
+ [enabledLanguageKey]: (value: Language.Info[]) => value.map((v) => v.code2),
+ });
+ const hooksRef = useRef(submitHooks);
+
+ const invokeHooks = useCallback((settings: LooseObject) => {
+ const hooks = hooksRef.current;
+ for (const key in settings) {
+ if (key in hooks) {
+ const value = settings[key];
+ const fn = hooks[key];
+ settings[key] = fn(value);
+ }
+ }
+ }, []);
+
+ const addHook = useCallback(
+ (key: string, fn: (value: unknown) => unknown) => {
+ setSubmitHooks((hooks) => ({ ...hooks, [key]: fn }));
+ },
+ []
+ );
+
+ const removeHook = useCallback((key: string) => {
+ setSubmitHooks((hooks) => {
+ const newHooks = { ...hooks };
+ delete newHooks[key];
+
+ return newHooks;
+ });
+ }, []);
+
+ return useMemo(
+ () => ({
+ add: addHook,
+ remove: removeHook,
+ invoke: invokeHooks,
+ }),
+ [addHook, invokeHooks, removeHook]
+ );
+}
diff --git a/frontend/src/pages/Settings/utilities/hooks.ts b/frontend/src/pages/Settings/utilities/hooks.ts
index 09f054cc3..5f011e7e9 100644
--- a/frontend/src/pages/Settings/utilities/hooks.ts
+++ b/frontend/src/pages/Settings/utilities/hooks.ts
@@ -1,13 +1,13 @@
import { LOG } from "@/utilities/console";
import { get, isNull, isUndefined, uniqBy } from "lodash";
import { useCallback, useEffect, useMemo, useRef } from "react";
-import { submitHooks } from "../components";
import {
FormKey,
useFormActions,
useStagedValues,
} from "../utilities/FormValues";
import { useSettings } from "../utilities/SettingsProvider";
+import { useSubmitHooks } from "./HooksProvider";
export interface BaseInput<T> {
disabled?: boolean;
@@ -52,20 +52,22 @@ export function useSettingValue<T>(
const optionsRef = useRef(options);
+ const submitHooks = useSubmitHooks();
+
useEffect(() => {
const onSubmit = optionsRef.current?.onSubmit;
if (onSubmit) {
LOG("info", "Adding submit hook for", key);
- submitHooks[key] = onSubmit;
+ submitHooks.add(key, onSubmit);
}
return () => {
if (key in submitHooks) {
LOG("info", "Removing submit hook for", key);
- delete submitHooks[key];
+ submitHooks.remove(key);
}
};
- }, [key]);
+ }, [key, submitHooks]);
const originalValue = useMemo(() => {
const onLoaded = optionsRef.current?.onLoaded;