feat(ui): new SettingsNotification using antd
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
|
||||
import DingTalk from "@/components/notify/DingTalk";
|
||||
import Lark from "@/components/notify/Lark";
|
||||
import NotifyTemplate from "@/components/notify/NotifyTemplate";
|
||||
import Telegram from "@/components/notify/Telegram";
|
||||
import Webhook from "@/components/notify/Webhook";
|
||||
import ServerChan from "@/components/notify/ServerChan";
|
||||
import Email from "@/components/notify/Email";
|
||||
import Bark from "@/components/notify/Bark";
|
||||
import { NotifyProvider } from "@/providers/notify";
|
||||
|
||||
const Notification = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<NotifyProvider>
|
||||
<div className="border rounded-sm p-5 shadow-lg">
|
||||
<Accordion type={"multiple"} className="dark:text-stone-200">
|
||||
<AccordionItem value="item-1" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("settings.notification.template.label")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<NotifyTemplate />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
<div className="border rounded-md p-5 mt-7 shadow-lg">
|
||||
<Accordion type={"single"} collapsible={true} className="dark:text-stone-200">
|
||||
<AccordionItem value="item-email" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.email")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Email />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-webhook" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.webhook")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Webhook />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-dingtalk" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.dingtalk")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<DingTalk />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-lark" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.lark")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Lark />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-telegram" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.telegram")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Telegram />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-serverchan" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.serverchan")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<ServerChan />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-bark" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.notifier.bark")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Bark />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</NotifyProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notification;
|
||||
@@ -3,6 +3,7 @@ import { useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { cn } from "@/components/ui/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -11,10 +12,9 @@ import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
import { SSLProvider as SSLProviderType, SSLProviderSetting, SettingsModel } from "@/domain/settings";
|
||||
import { SETTINGS_NAMES, SSLProvider as SSLProviderType, SSLProviderSetting, SettingsModel } from "@/domain/settings";
|
||||
import { get, save } from "@/repository/settings";
|
||||
import { produce } from "immer";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
|
||||
type SSLProviderContext = {
|
||||
setting: SettingsModel<SSLProviderSetting>;
|
||||
@@ -28,6 +28,16 @@ export const useSSLProviderContext = () => {
|
||||
return useContext(Context);
|
||||
};
|
||||
|
||||
const getConfigStr = (content: SSLProviderSetting, kind: string, key: string) => {
|
||||
if (!content.config) {
|
||||
return "";
|
||||
}
|
||||
if (!content.config[kind]) {
|
||||
return "";
|
||||
}
|
||||
return content.config[kind][key] ?? "";
|
||||
};
|
||||
|
||||
const SSLProvider = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -42,7 +52,7 @@ const SSLProvider = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const setting = await get<SSLProviderSetting>("ssl-provider");
|
||||
const setting = await get<SSLProviderSetting>(SETTINGS_NAMES.SSL_PROVIDER);
|
||||
|
||||
if (setting) {
|
||||
setConfig(setting);
|
||||
@@ -95,7 +105,7 @@ const SSLProvider = () => {
|
||||
return (
|
||||
<>
|
||||
<Context.Provider value={{ onSubmit, setConfig, setting: config }}>
|
||||
<div className="w-full md:max-w-[35em]">
|
||||
<div className="md:max-w-[40rem]">
|
||||
<Label className="dark:text-stone-200">{t("common.text.ca")}</Label>
|
||||
<RadioGroup
|
||||
className="flex mt-3 dark:text-stone-200"
|
||||
@@ -147,7 +157,7 @@ const SSLProviderForm = ({ kind }: { kind: string }) => {
|
||||
case "zerossl":
|
||||
return <SSLProviderZeroSSLForm />;
|
||||
case "gts":
|
||||
return <SSLProviderGtsForm />;
|
||||
return <SSLProviderGoogleTrustServicesForm />;
|
||||
default:
|
||||
return <SSLProviderLetsEncryptForm />;
|
||||
}
|
||||
@@ -160,16 +170,6 @@ const SSLProviderForm = ({ kind }: { kind: string }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const getConfigStr = (content: SSLProviderSetting, kind: string, key: string) => {
|
||||
if (!content.config) {
|
||||
return "";
|
||||
}
|
||||
if (!content.config[kind]) {
|
||||
return "";
|
||||
}
|
||||
return content.config[kind][key] ?? "";
|
||||
};
|
||||
|
||||
const SSLProviderLetsEncryptForm = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -227,6 +227,7 @@ const SSLProviderLetsEncryptForm = () => {
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
const SSLProviderZeroSSLForm = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -334,7 +335,7 @@ const SSLProviderZeroSSLForm = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const SSLProviderGtsForm = () => {
|
||||
const SSLProviderGoogleTrustServicesForm = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { setting, onSubmit } = useSSLProviderContext();
|
||||
|
||||
@@ -5,8 +5,6 @@ import { Card, Space } from "antd";
|
||||
import { PageHeader } from "@ant-design/pro-components";
|
||||
import { KeyRound as KeyRoundIcon, Megaphone as MegaphoneIcon, ShieldCheck as ShieldCheckIcon, UserRound as UserRoundIcon } from "lucide-react";
|
||||
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
|
||||
const Settings = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
@@ -73,7 +71,6 @@ const Settings = () => {
|
||||
navigate(`/settings/${key}`);
|
||||
}}
|
||||
>
|
||||
<Toaster />
|
||||
<Outlet />
|
||||
</Card>
|
||||
</>
|
||||
|
||||
@@ -47,7 +47,7 @@ const SettingsAccount = () => {
|
||||
navigate("/login");
|
||||
}, 500);
|
||||
} catch (err) {
|
||||
notificationApi.error({ message: t("common.text.request_error"), description: <>{getErrMsg(err)}</> });
|
||||
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
||||
} finally {
|
||||
setFormPending(false);
|
||||
}
|
||||
@@ -58,7 +58,7 @@ const SettingsAccount = () => {
|
||||
{MessageContextHolder}
|
||||
{NotificationContextHolder}
|
||||
|
||||
<div className="w-full md:max-w-[35em]">
|
||||
<div className="md:max-w-[40rem]">
|
||||
<Form form={form} disabled={formPending} initialValues={initialValues} layout="vertical" onFinish={handleFormFinish}>
|
||||
<Form.Item name="username" label={t("settings.account.form.email.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("settings.account.form.email.placeholder")} onChange={handleInputChange} />
|
||||
|
||||
30
ui/src/pages/settings/SettingsNotification.tsx
Normal file
30
ui/src/pages/settings/SettingsNotification.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Card, Divider } from "antd";
|
||||
|
||||
import NotifyChannels from "@/components/notification/NotifyChannels";
|
||||
import NotifyTemplate from "@/components/notification/NotifyTemplate";
|
||||
import { useNotifyChannelStore } from "@/stores/notify";
|
||||
|
||||
const SettingsNotification = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { initialized } = useNotifyChannelStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Card className="shadow" title={t("settings.notification.template.card.title")}>
|
||||
<div className="md:max-w-[40rem]">
|
||||
<NotifyTemplate />
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card className="shadow" styles={{ body: initialized ? { padding: 0 } : {} }} title={t("settings.notification.channels.card.title")}>
|
||||
<NotifyChannels classNames={{ form: "md:max-w-[40rem]" }} />
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsNotification;
|
||||
@@ -60,7 +60,7 @@ const SettingsPassword = () => {
|
||||
navigate("/login");
|
||||
}, 500);
|
||||
} catch (err) {
|
||||
notificationApi.error({ message: t("common.text.request_error"), description: <>{getErrMsg(err)}</> });
|
||||
notificationApi.error({ message: t("common.text.request_error"), description: getErrMsg(err) });
|
||||
} finally {
|
||||
setFormPending(false);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ const SettingsPassword = () => {
|
||||
{MessageContextHolder}
|
||||
{NotificationContextHolder}
|
||||
|
||||
<div className="w-full md:max-w-[35em]">
|
||||
<div className="md:max-w-[40rem]">
|
||||
<Form form={form} disabled={formPending} layout="vertical" onFinish={handleFormFinish}>
|
||||
<Form.Item name="oldPassword" label={t("settings.password.form.old_password.label")} rules={[formRule]}>
|
||||
<Input.Password placeholder={t("settings.password.form.old_password.placeholder")} onChange={handleInputChange} />
|
||||
|
||||
Reference in New Issue
Block a user