diff options
author | Anderson Shindy Oki <[email protected]> | 2024-12-03 15:05:19 +0900 |
---|---|---|
committer | GitHub <[email protected]> | 2024-12-03 15:05:19 +0900 |
commit | d79bc09b7c9715dd2eb016ac6782a16a755bb67c (patch) | |
tree | 84da3bb6f7f89b5d9b3facf2f37e7f6818462abd | |
parent | 8dc686e902df6a0b421f5c6fb36f24661e09db8a (diff) | |
download | bazarr-d79bc09b7c9715dd2eb016ac6782a16a755bb67c.tar.gz bazarr-d79bc09b7c9715dd2eb016ac6782a16a755bb67c.zip |
Added opensubtitlescom provider validation (#2770)
-rw-r--r-- | frontend/src/pages/Settings/Providers/components.tsx | 107 | ||||
-rw-r--r-- | 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<ProviderToolProps> = ({ payload, enabledProviders, @@ -172,6 +194,9 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({ settings: staged, hooks: {}, }, + validate: { + settings: validation!, + }, }); const deletePayload = useCallback(() => { @@ -188,6 +213,12 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({ 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<ProviderToolProps> = ({ modals.closeAll(); } }, - [info, enabledProviders, modals, settingsKey], + [info, enabledProviders, modals, settingsKey, form], ); const canSave = info !== null; @@ -249,43 +280,57 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({ const label = value.name ?? capitalize(value.key); const options = value.options ?? []; + const error = form.errors[`settings.settings-${itemKey}-${key}`] ? ( + <MantineText c="red" component="span" size="xs"> + {form.errors[`settings.settings-${itemKey}-${key}`]} + </MantineText> + ) : null; + switch (value.type) { case "text": elements.push( - <Text - key={BuildKey(itemKey, key)} - label={label} - settingKey={`settings-${itemKey}-${key}`} - ></Text>, + <Fragment key={BuildKey(itemKey, key)}> + <Text + label={label} + settingKey={`settings-${itemKey}-${key}`} + ></Text> + {error} + </Fragment>, ); return; case "password": elements.push( - <Password - key={BuildKey(itemKey, key)} - label={label} - settingKey={`settings-${itemKey}-${key}`} - ></Password>, + <Fragment key={BuildKey(itemKey, key)}> + <Password + label={label} + settingKey={`settings-${itemKey}-${key}`} + ></Password> + {error} + </Fragment>, ); return; case "switch": elements.push( - <Check - key={key} - inline - label={label} - settingKey={`settings-${itemKey}-${key}`} - ></Check>, + <Fragment key={BuildKey(itemKey, key)}> + <Check + inline + label={label} + settingKey={`settings-${itemKey}-${key}`} + ></Check> + {error} + </Fragment>, ); return; case "select": elements.push( - <GlobalSelector - key={key} - label={label} - settingKey={`settings-${itemKey}-${key}`} - options={options} - ></GlobalSelector>, + <Fragment key={BuildKey(itemKey, key)}> + <GlobalSelector + label={label} + settingKey={`settings-${itemKey}-${key}`} + options={options} + ></GlobalSelector> + {error} + </Fragment>, ); return; case "testbutton": @@ -295,11 +340,13 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({ return; case "chips": elements.push( - <Chips - key={key} - label={label} - settingKey={`settings-${itemKey}-${key}`} - ></Chips>, + <Fragment key={BuildKey(itemKey, key)}> + <Chips + label={label} + settingKey={`settings-${itemKey}-${key}`} + ></Chips> + {error} + </Fragment>, ); return; default: @@ -308,7 +355,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({ }); return <Stack gap="xs">{elements}</Stack>; - }, [info]); + }, [info, form]); return ( <SettingsProvider value={settings}> 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<T, N> = { type: N; key: string; @@ -8,15 +9,18 @@ type Input<T, N> = { name?: string; description?: string; options?: SelectorOption<string>[]; + validation?: { + rule: (value: string) => string | null; + }; }; type AvailableInput = - | Input<ReactText, "text"> + | Input<Text, "text"> | Input<string, "password"> | Input<boolean, "switch"> | Input<string, "select"> | Input<string, "testbutton"> - | Input<ReactText[], "chips">; + | Input<Text[], "chips">; export interface ProviderInfo { key: string; @@ -391,6 +395,12 @@ export const ProviderList: Readonly<ProviderInfo[]> = [ { type: "text", key: "username", + validation: { + rule: (value: string) => + /^.\S+@\S+$/.test(value) + ? "Invalid Username. Do not use your e-mail." + : null, + }, }, { type: "password", |