From d79bc09b7c9715dd2eb016ac6782a16a755bb67c Mon Sep 17 00:00:00 2001 From: Anderson Shindy Oki Date: Tue, 3 Dec 2024 15:05:19 +0900 Subject: [PATCH] Added opensubtitlescom provider validation (#2770) --- .../pages/Settings/Providers/components.tsx | 107 +++++++++++++----- frontend/src/pages/Settings/Providers/list.ts | 16 ++- 2 files changed, 90 insertions(+), 33 deletions(-) diff --git a/frontend/src/pages/Settings/Providers/components.tsx b/frontend/src/pages/Settings/Providers/components.tsx index 5c37188a2..d50f0c93c 100644 --- a/frontend/src/pages/Settings/Providers/components.tsx +++ b/frontend/src/pages/Settings/Providers/components.tsx @@ -1,4 +1,5 @@ import { + Fragment, FunctionComponent, useCallback, useMemo, @@ -42,7 +43,7 @@ import { } from "@/pages/Settings/utilities/SettingsProvider"; import { BuildKey, useSelectorOptions } from "@/utilities"; import { ASSERT } from "@/utilities/console"; -import { ProviderInfo } from "./list"; +import { ProviderInfo, ProviderList } from "./list"; type SettingsKey = | "settings-general-enabled_providers" @@ -151,6 +152,27 @@ const SelectItem: AutocompleteProps["renderOption"] = ({ option }) => { ); }; +const validation = ProviderList.map((provider) => { + return provider.inputs + ?.map((input) => { + if (input.validation === undefined) { + return null; + } + + return { + [`settings-${provider.key}-${input.key}`]: input.validation?.rule, + }; + }) + .filter((input) => input && Object.keys(input).length > 0) + .reduce((acc, curr) => { + return { ...acc, ...curr }; + }, {}); +}) + .filter((provider) => provider && Object.keys(provider).length > 0) + .reduce((acc, item) => { + return { ...acc, ...item }; + }, {}); + const ProviderTool: FunctionComponent = ({ payload, enabledProviders, @@ -172,6 +194,9 @@ const ProviderTool: FunctionComponent = ({ settings: staged, hooks: {}, }, + validate: { + settings: validation!, + }, }); const deletePayload = useCallback(() => { @@ -188,6 +213,12 @@ const ProviderTool: FunctionComponent = ({ const submit = useCallback( (values: FormValues) => { + const result = form.validate(); + + if (result.hasErrors) { + return; + } + if (info && enabledProviders) { const changes = { ...values.settings }; const hooks = values.hooks; @@ -204,7 +235,7 @@ const ProviderTool: FunctionComponent = ({ modals.closeAll(); } }, - [info, enabledProviders, modals, settingsKey], + [info, enabledProviders, modals, settingsKey, form], ); const canSave = info !== null; @@ -249,43 +280,57 @@ const ProviderTool: FunctionComponent = ({ const label = value.name ?? capitalize(value.key); const options = value.options ?? []; + const error = form.errors[`settings.settings-${itemKey}-${key}`] ? ( + + {form.errors[`settings.settings-${itemKey}-${key}`]} + + ) : null; + switch (value.type) { case "text": elements.push( - , + + + {error} + , ); return; case "password": elements.push( - , + + + {error} + , ); return; case "switch": elements.push( - , + + + {error} + , ); return; case "select": elements.push( - , + + + {error} + , ); return; case "testbutton": @@ -295,11 +340,13 @@ const ProviderTool: FunctionComponent = ({ return; case "chips": elements.push( - , + + + {error} + , ); return; default: @@ -308,7 +355,7 @@ const ProviderTool: FunctionComponent = ({ }); return {elements}; - }, [info]); + }, [info, form]); return ( diff --git a/frontend/src/pages/Settings/Providers/list.ts b/frontend/src/pages/Settings/Providers/list.ts index 9d663a1d5..d2217bb6d 100644 --- a/frontend/src/pages/Settings/Providers/list.ts +++ b/frontend/src/pages/Settings/Providers/list.ts @@ -1,6 +1,7 @@ -import { ReactText } from "react"; import { SelectorOption } from "@/components"; +type Text = string | number; + type Input = { type: N; key: string; @@ -8,15 +9,18 @@ type Input = { name?: string; description?: string; options?: SelectorOption[]; + validation?: { + rule: (value: string) => string | null; + }; }; type AvailableInput = - | Input + | Input | Input | Input | Input | Input - | Input; + | Input; export interface ProviderInfo { key: string; @@ -391,6 +395,12 @@ export const ProviderList: Readonly = [ { type: "text", key: "username", + validation: { + rule: (value: string) => + /^.\S+@\S+$/.test(value) + ? "Invalid Username. Do not use your e-mail." + : null, + }, }, { type: "password",