From 9ede271c0588e206f8b022db81c019a61c25f5bc Mon Sep 17 00:00:00 2001 From: DingDongSoLong4 <99329275+DingDongSoLong4@users.noreply.github.com> Date: Tue, 7 Mar 2023 07:19:56 +0200 Subject: [PATCH] Fix yup schemas (#3509) * Fix yup schemas * Add internationalization --- ui/v2.5/src/App.tsx | 14 +- .../GalleryDetails/GalleryEditPanel.tsx | 86 +++--- .../Images/ImageDetails/ImageEditPanel.tsx | 58 ++-- .../components/Movies/MovieDetails/Movie.tsx | 32 +-- .../Movies/MovieDetails/MovieCreate.tsx | 20 +- .../Movies/MovieDetails/MovieEditPanel.tsx | 223 +++++++-------- .../Performers/EditPerformersDialog.tsx | 2 +- .../Performers/PerformerDetails/Performer.tsx | 22 +- .../PerformerDetails/PerformerCreate.tsx | 18 +- .../PerformerDetails/PerformerEditPanel.tsx | 261 +++++++++--------- .../PerformerScrapeDialog.tsx | 6 +- .../Scenes/SceneDetails/SceneEditPanel.tsx | 125 ++++----- .../Studios/StudioDetails/Studio.tsx | 22 +- .../Studios/StudioDetails/StudioCreate.tsx | 23 +- .../Studios/StudioDetails/StudioEditPanel.tsx | 127 ++++----- .../src/components/Tags/TagDetails/Tag.tsx | 32 +-- .../components/Tags/TagDetails/TagCreate.tsx | 30 +- .../Tags/TagDetails/TagEditPanel.tsx | 101 ++++--- ui/v2.5/src/docs/en/Changelog/v0200.md | 1 + ui/v2.5/src/locales/cs-CZ.json | 4 +- ui/v2.5/src/locales/da-DK.json | 4 +- ui/v2.5/src/locales/de-DE.json | 4 +- ui/v2.5/src/locales/en-GB.json | 6 +- ui/v2.5/src/locales/es-ES.json | 4 +- ui/v2.5/src/locales/et-EE.json | 4 +- ui/v2.5/src/locales/fi-FI.json | 4 +- ui/v2.5/src/locales/fr-FR.json | 4 +- ui/v2.5/src/locales/it-IT.json | 4 +- ui/v2.5/src/locales/ja-JP.json | 4 +- ui/v2.5/src/locales/ko-KR.json | 4 +- ui/v2.5/src/locales/nl-NL.json | 4 +- ui/v2.5/src/locales/pl-PL.json | 4 +- ui/v2.5/src/locales/pt-BR.json | 4 +- ui/v2.5/src/locales/ru-RU.json | 4 +- ui/v2.5/src/locales/sv-SE.json | 4 +- ui/v2.5/src/locales/tr-TR.json | 4 +- ui/v2.5/src/locales/zh-CN.json | 4 +- ui/v2.5/src/locales/zh-TW.json | 4 +- ui/v2.5/src/utils/gender.ts | 2 +- 39 files changed, 632 insertions(+), 651 deletions(-) diff --git a/ui/v2.5/src/App.tsx b/ui/v2.5/src/App.tsx index 0833452ba..4a374065c 100644 --- a/ui/v2.5/src/App.tsx +++ b/ui/v2.5/src/App.tsx @@ -21,6 +21,7 @@ import { useSystemStatus, } from "src/core/StashService"; import flattenMessages from "./utils/flattenMessages"; +import * as yup from "yup"; import Mousetrap from "mousetrap"; import MousetrapPause from "mousetrap-pause"; import { ErrorBoundary } from "./components/ErrorBoundary"; @@ -126,7 +127,18 @@ export const App: React.FC = () => { } ); - setMessages(flattenMessages(mergedMessages)); + const newMessages = flattenMessages(mergedMessages) as Record< + string, + string + >; + + yup.setLocale({ + mixed: { + required: newMessages["validation.required"], + }, + }); + + setMessages(newMessages); }; setLocale(); diff --git a/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryEditPanel.tsx b/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryEditPanel.tsx index 575653a3a..5e7654d03 100644 --- a/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryEditPanel.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryEditPanel.tsx @@ -38,6 +38,7 @@ import { faSyncAlt } from "@fortawesome/free-solid-svg-icons"; import { galleryTitle } from "src/core/galleries"; import { useRatingKeybinds } from "src/hooks/keybinds"; import { ConfigurationContext } from "src/hooks/Config"; +import isEqual from "lodash-es/isEqual"; interface IProps { gallery: Partial; @@ -79,44 +80,50 @@ export const GalleryEditPanel: React.FC = ({ isNew || (gallery?.files?.length === 0 && !gallery?.folder); const schema = yup.object({ - title: titleRequired - ? yup.string().required() - : yup.string().optional().nullable(), - details: yup.string().optional().nullable(), - url: yup.string().optional().nullable(), - date: yup.string().optional().nullable(), - rating100: yup.number().optional().nullable(), - studio_id: yup.string().optional().nullable(), - performer_ids: yup.array(yup.string().required()).optional().nullable(), - tag_ids: yup.array(yup.string().required()).optional().nullable(), - scene_ids: yup.array(yup.string().required()).optional().nullable(), + title: titleRequired ? yup.string().required() : yup.string().ensure(), + url: yup.string().ensure(), + date: yup + .string() + .ensure() + .test({ + name: "date", + test: (value) => { + if (!value) return true; + if (!value.match(/^\d{4}-\d{2}-\d{2}$/)) return false; + if (Number.isNaN(Date.parse(value))) return false; + return true; + }, + message: intl.formatMessage({ id: "validation.date_invalid_form" }), + }), + rating100: yup.number().nullable().defined(), + studio_id: yup.string().required().nullable(), + performer_ids: yup.array(yup.string().required()).defined(), + tag_ids: yup.array(yup.string().required()).defined(), + scene_ids: yup.array(yup.string().required()).defined(), + details: yup.string().ensure(), }); const initialValues = { title: gallery?.title ?? "", - details: gallery?.details ?? "", url: gallery?.url ?? "", date: gallery?.date ?? "", rating100: gallery?.rating100 ?? null, - studio_id: gallery?.studio?.id, + studio_id: gallery?.studio?.id ?? null, performer_ids: (gallery?.performers ?? []).map((p) => p.id), tag_ids: (gallery?.tags ?? []).map((t) => t.id), scene_ids: (gallery?.scenes ?? []).map((s) => s.id), + details: gallery?.details ?? "", }; - type InputValues = typeof initialValues; + type InputValues = yup.InferType; - const formik = useFormik({ + const formik = useFormik({ initialValues, + enableReinitialize: true, validationSchema: schema, - onSubmit: (values) => onSave(getGalleryInput(values)), + onSubmit: (values) => onSave(values), }); - // always dirty if creating a new gallery with a title - if (isNew && gallery?.title) { - formik.dirty = true; - } - function setRating(v: number) { formik.setFieldValue("rating100", v); } @@ -166,24 +173,13 @@ export const GalleryEditPanel: React.FC = ({ setQueryableScrapers(newQueryableScrapers); }, [Scrapers]); - function getGalleryInput( - input: InputValues - ): GQL.GalleryCreateInput | GQL.GalleryUpdateInput { - return { - id: isNew ? undefined : gallery?.id ?? "", - ...input, - }; - } - - async function onSave( - input: GQL.GalleryCreateInput | GQL.GalleryUpdateInput - ) { + async function onSave(input: GQL.GalleryCreateInput) { setIsLoading(true); try { if (isNew) { const result = await createGallery({ variables: { - input: input as GQL.GalleryCreateInput, + input, }, }); if (result.data?.galleryCreate) { @@ -202,7 +198,10 @@ export const GalleryEditPanel: React.FC = ({ } else { const result = await updateGallery({ variables: { - input: input as GQL.GalleryUpdateInput, + input: { + id: gallery.id!, + ...input, + }, }, }); if (result.data?.galleryUpdate) { @@ -216,7 +215,7 @@ export const GalleryEditPanel: React.FC = ({ } ), }); - formik.resetForm({ values: formik.values }); + formik.resetForm(); } } } catch (e) { @@ -271,7 +270,10 @@ export const GalleryEditPanel: React.FC = ({ return; } - const currentGallery = getGalleryInput(formik.values); + const currentGallery = { + id: gallery.id!, + ...formik.values, + }; return ( = ({ function renderTextField(field: string, title: string, placeholder?: string) { return ( - + {FormUtils.renderLabel({ title, })} @@ -419,7 +421,9 @@ export const GalleryEditPanel: React.FC = ({