import * as yup from "yup" import {useFormik} from "formik" import {TbCursorText} from "react-icons/tb" import {useTranslation} from "react-i18next" import {MdCheck, MdClear, MdOutlineChangeCircle, MdTextFormat} from "react-icons/md" import {BsImage} from "react-icons/bs" import {AxiosError} from "axios" import {FaMask} from "react-icons/fa" import AliasesPercentageAmount from "./AliasPercentageAmount" import { Checkbox, Collapse, FormControlLabel, FormGroup, FormHelperText, Grid, InputAdornment, TextField, Typography, } from "@mui/material" import {LoadingButton} from "@mui/lab" import {useMutation} from "@tanstack/react-query" import {AdminSettings} from "~/server-types" import {StringPoolField, createPool} from "~/components" import {UpdateAdminSettingsResponse, updateAdminSettings} from "~/apis" import {useErrorSuccessSnacks} from "~/hooks" import {queryClient} from "~/constants/react-query" import {parseFastAPIError} from "~/utils" import {DEFAULT_ADMIN_SETTINGS} from "~/constants/admin-settings" import RandomAliasGenerator from "~/route-widgets/GlobalSettingsRoute/RandomAliasGenerator" export interface SettingsFormProps { settings: AdminSettings queryKey: readonly string[] } const DEFAULT_POOLS = createPool({ abcdefghijklmnopqrstuvwxyz: "a-z", ABCDEFGHIJKLMNOPQRSTUVWXYZ: "A-Z", "0123456789": "0-9", }) export default function SettingsForm({settings, queryKey}: SettingsFormProps) { const {t} = useTranslation(["admin-global-settings", "common"]) const {showSuccess, showError} = useErrorSuccessSnacks() const validationSchema = yup.object().shape({ randomEmailIdMinLength: yup .number() .min(1) .max(1_023) .label(t("fields.randomEmailIdMinLength.label")), randomEmailIdChars: yup.string().label(t("fields.randomEmailIdChars.label")), randomEmailLengthIncreaseOnPercentage: yup .number() .min(0) .max(1) .label(t("fields.randomEmailLengthIncreaseOnPercentage.label")), imageProxyStorageLifeTimeInHours: yup .number() .label(t("fields.imageProxyStorageLifeTimeInHours.label")), customEmailSuffixLength: yup .number() .min(1) .max(1_023) .label(t("fields.customEmailSuffixLength.label")), customEmailSuffixChars: yup.string().label(t("fields.customEmailSuffixChars.label")), userEmailEnableDisposableEmails: yup .boolean() .label(t("fields.userEmailEnableDisposableEmails.label")), userEmailEnableOtherRelays: yup .boolean() .label(t("fields.userEmailEnableOtherRelays.label")), enableImageProxy: yup.boolean().label(t("fields.enableImageProxy.label")), enableImageProxyStorage: yup.boolean().label(t("fields.enableImageProxyStorage.label")), allowStatistics: yup.boolean().label(t("fields.allowStatistics.label")), allowAliasDeletion: yup.boolean().label(t("fields.allowAliasDeletion.label")), maxAliasesPerUser: yup.number().label(t("fields.maxAliasesPerUser.label")).min(0), allowRegistrations: yup.boolean().label(t("fields.allowRegistrations.label")), } as Record) const {mutateAsync} = useMutation< UpdateAdminSettingsResponse, AxiosError, Partial >(async settings => updateAdminSettings(settings), { onError: showError, onSuccess: ({code, detail, ...newSettings}) => { if (code === "error:settings:global_settings_disabled") { return } showSuccess(t("updatedSuccessfullyMessage")) queryClient.setQueryData>(queryKey, newSettings) }, }) const formik = useFormik({ validationSchema, onSubmit: async (values, {setErrors}) => { try { await mutateAsync(values) } catch (error) { setErrors(parseFastAPIError(error as AxiosError)) } }, initialValues: settings, }) // Fields will either have a value or be filled from the default values. // That means we will never have a `null` value. return (
{t("title")} {t("description")} ), }} /> ), }} /> } /> ), }} /> ), }} /> } /> ), endAdornment: ( {t("fields.imageProxyStorageLifeTimeInHours.unit", { count: formik.values .imageProxyStorageLifeTimeInHours || 0, })} ), }} /> } disabled={formik.isSubmitting} label={t("fields.userEmailEnableDisposableEmails.label")} /> {(formik.touched.userEmailEnableDisposableEmails && formik.errors.userEmailEnableDisposableEmails) || t("fields.userEmailEnableDisposableEmails.description")} } disabled={formik.isSubmitting} label={t("fields.userEmailEnableOtherRelays.label")} /> {(formik.touched.userEmailEnableOtherRelays && formik.errors.userEmailEnableOtherRelays) || t("fields.userEmailEnableOtherRelays.description")} } disabled={formik.isSubmitting} label={t("fields.enableImageProxy.label")} /> {(formik.touched.enableImageProxy && formik.errors.enableImageProxy) || t("fields.enableImageProxy.description")} } disabled={formik.isSubmitting} label={t("fields.enableImageProxyStorage.label")} /> {(formik.touched.enableImageProxyStorage && formik.errors.enableImageProxyStorage) || t("fields.enableImageProxyStorage.description")} } disabled={formik.isSubmitting} label={t("fields.allowStatistics.label")} /> {(formik.touched.allowStatistics && formik.errors.allowStatistics) || t("fields.allowStatistics.description")} } disabled={formik.isSubmitting} label={t("fields.allowAliasDeletion.label")} /> {(formik.touched.allowAliasDeletion && formik.errors.allowAliasDeletion) || t("fields.allowAliasDeletion.description")} } disabled={formik.isSubmitting} label={t("fields.allowRegistrations.label")} /> {(formik.touched.allowRegistrations && formik.errors.allowRegistrations) || t("fields.allowRegistrations.description")} } color="warning" onClick={() => { formik.setValues(DEFAULT_ADMIN_SETTINGS) formik.submitForm() }} > {t("general.resetLabel", {ns: "common"})} } > {t("general.saveLabel", {ns: "common"})}
) }