mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-10 06:29:52 +00:00
feat: new UI for email notify settings
This commit is contained in:
parent
5d93334426
commit
8b04e96a7d
@ -24,7 +24,7 @@ func (s *Setting) GetChannelContent(channel string) (map[string]any, error) {
|
||||
|
||||
v, ok := (*conf)[channel]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("channel %s not found", channel)
|
||||
return nil, fmt.Errorf("channel \"%s\" not found", channel)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
|
@ -128,15 +128,15 @@ const Bark = () => {
|
||||
await notifyTest("bark");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -235,7 +235,7 @@ const Bark = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
@ -128,15 +128,15 @@ const DingTalk = () => {
|
||||
await notifyTest("dingtalk");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -232,7 +232,7 @@ const DingTalk = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
357
ui/src/components/notify/Email.tsx
Normal file
357
ui/src/components/notify/Email.tsx
Normal file
@ -0,0 +1,357 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMessage } from "@/lib/error";
|
||||
import { NotifyChannelEmail, NotifyChannels } from "@/domain/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { update } from "@/repository/settings";
|
||||
import Show from "@/components/Show";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
|
||||
type EmailSetting = {
|
||||
id: string;
|
||||
name: string;
|
||||
data: NotifyChannelEmail;
|
||||
};
|
||||
|
||||
const Mail = () => {
|
||||
const { config, setChannels } = useNotifyContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [mail, setMail] = useState<EmailSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
smtpHost: "",
|
||||
smtpPort: 465,
|
||||
smtpTLS: true,
|
||||
username: "",
|
||||
password: "",
|
||||
senderAddress: "",
|
||||
receiverAddress: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
const [originMail, setOriginMail] = useState<EmailSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
smtpHost: "",
|
||||
smtpPort: 465,
|
||||
smtpTLS: true,
|
||||
username: "",
|
||||
password: "",
|
||||
senderAddress: "",
|
||||
receiverAddress: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailMail();
|
||||
setOriginMail({
|
||||
id: config.id ?? "",
|
||||
name: "email",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailMail();
|
||||
setMail({
|
||||
id: config.id ?? "",
|
||||
name: "email",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const getDetailMail = () => {
|
||||
const df: NotifyChannelEmail = {
|
||||
smtpHost: "smtp.example.com",
|
||||
smtpPort: 465,
|
||||
smtpTLS: true,
|
||||
username: "",
|
||||
password: "",
|
||||
senderAddress: "",
|
||||
receiverAddress: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.email) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.email as NotifyChannelEmail;
|
||||
};
|
||||
|
||||
const checkChanged = (data: NotifyChannelEmail) => {
|
||||
if (
|
||||
data.smtpHost !== originMail.data.smtpHost ||
|
||||
data.smtpPort !== originMail.data.smtpPort ||
|
||||
data.smtpTLS !== originMail.data.smtpTLS ||
|
||||
data.username !== originMail.data.username ||
|
||||
data.password !== originMail.data.password ||
|
||||
data.senderAddress !== originMail.data.senderAddress ||
|
||||
data.receiverAddress !== originMail.data.receiverAddress
|
||||
) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
email: {
|
||||
...mail.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
toast({
|
||||
title: t("common.save.succeeded.message"),
|
||||
description: t("settings.notification.config.saved.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("email");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSwitchChange = async () => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
enabled: !mail.data.enabled,
|
||||
},
|
||||
};
|
||||
setMail(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
email: {
|
||||
...newData.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
placeholder={t("settings.notification.email.smtp_host.placeholder")}
|
||||
value={mail.data.smtpHost}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
smtpHost: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="mt-2"
|
||||
type="number"
|
||||
placeholder={t("settings.notification.email.smtp_port.placeholder")}
|
||||
value={mail.data.smtpPort}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
smtpPort: +e.target.value || 0,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
className="mt-2"
|
||||
checked={mail.data.smtpTLS}
|
||||
onCheckedChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
smtpTLS: e,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="mt-2"
|
||||
placeholder={t("settings.notification.email.username.placeholder")}
|
||||
value={mail.data.username}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
username: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="mt-2"
|
||||
placeholder={t("settings.notification.email.password.placeholder")}
|
||||
value={mail.data.password}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
password: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="mt-2"
|
||||
placeholder={t("settings.notification.email.sender_address.placeholder")}
|
||||
value={mail.data.senderAddress}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
senderAddress: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Input
|
||||
className="mt-2"
|
||||
placeholder={t("settings.notification.email.receiver_address.placeholder")}
|
||||
value={mail.data.receiverAddress}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
receiverAddress: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setMail(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="mt-2">
|
||||
<div className="flex justify-between gap-4">
|
||||
<div className="flex items-center space-x-1">
|
||||
<Switch id="airplane-mode" checked={mail.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-1">
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && mail.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Mail;
|
@ -124,15 +124,15 @@ const Lark = () => {
|
||||
await notifyTest("lark");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -213,7 +213,7 @@ const Lark = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
@ -1,319 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMessage } from "@/lib/error";
|
||||
import { NotifyChannelMail, NotifyChannels } from "@/domain/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { update } from "@/repository/settings";
|
||||
import Show from "@/components/Show";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
|
||||
type MailSetting = {
|
||||
id: string;
|
||||
name: string;
|
||||
data: NotifyChannelMail;
|
||||
};
|
||||
|
||||
const Mail = () => {
|
||||
const { config, setChannels } = useNotifyContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [mail, setmail] = useState<MailSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
senderAddress: "",
|
||||
receiverAddresses: "",
|
||||
smtpHostAddr: "",
|
||||
smtpHostPort: "25",
|
||||
username: "",
|
||||
password: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
const [originMail, setoriginMail] = useState<MailSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
senderAddress: "",
|
||||
receiverAddresses: "",
|
||||
smtpHostAddr: "",
|
||||
smtpHostPort: "25",
|
||||
username: "",
|
||||
password: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailMail();
|
||||
setoriginMail({
|
||||
id: config.id ?? "",
|
||||
name: "mail",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailMail();
|
||||
setmail({
|
||||
id: config.id ?? "",
|
||||
name: "mail",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const getDetailMail = () => {
|
||||
const df: NotifyChannelMail = {
|
||||
senderAddress: "",
|
||||
receiverAddresses: "",
|
||||
smtpHostAddr: "",
|
||||
smtpHostPort: "25",
|
||||
username: "",
|
||||
password: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.mail) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.mail as NotifyChannelMail;
|
||||
};
|
||||
|
||||
const checkChanged = (data: NotifyChannelMail) => {
|
||||
if (data.senderAddress !== originMail.data.senderAddress || data.receiverAddresses !== originMail.data.receiverAddresses || data.smtpHostAddr !== originMail.data.smtpHostAddr || data.smtpHostPort !== originMail.data.smtpHostPort || data.username !== originMail.data.username || data.password !== originMail.data.password) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
mail: {
|
||||
...mail.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
toast({
|
||||
title: t("common.save.succeeded.message"),
|
||||
description: t("settings.notification.config.saved.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("mail");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSwitchChange = async () => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
enabled: !mail.data.enabled,
|
||||
},
|
||||
};
|
||||
setmail(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
mail: {
|
||||
...newData.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.sender_address.placeholder")}
|
||||
value={mail.data.senderAddress}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
senderAddress: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.receiver_address.placeholder")}
|
||||
className="mt-2"
|
||||
value={mail.data.receiverAddresses}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
receiverAddresses: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.smtp_host.placeholder")}
|
||||
className="mt-2"
|
||||
value={mail.data.smtpHostAddr}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
smtpHostAddr: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.smtp_port.placeholder")}
|
||||
className="mt-2"
|
||||
value={mail.data.smtpHostPort}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
smtpHostPort: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.username.placeholder")}
|
||||
className="mt-2"
|
||||
value={mail.data.username}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
username: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
placeholder={t("settings.notification.mail.password.placeholder")}
|
||||
className="mt-2"
|
||||
value={mail.data.password}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...mail,
|
||||
data: {
|
||||
...mail.data,
|
||||
password: e.target.value,
|
||||
},
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setmail(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch id="airplane-mode" checked={mail.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && mail.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Mail;
|
@ -97,7 +97,7 @@ const ServerChan = () => {
|
||||
if (!isValidURL(serverchan.data.url)) {
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: t("settings.notification.url.errmsg.invalid"),
|
||||
description: t("common.errmsg.url_invalid"),
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
@ -135,15 +135,15 @@ const ServerChan = () => {
|
||||
await notifyTest("serverchan");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -225,7 +225,7 @@ const ServerChan = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
@ -128,15 +128,15 @@ const Telegram = () => {
|
||||
await notifyTest("telegram");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -235,7 +235,7 @@ const Telegram = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
@ -97,7 +97,7 @@ const Webhook = () => {
|
||||
if (!isValidURL(webhook.data.url)) {
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: t("settings.notification.url.errmsg.invalid"),
|
||||
description: t("common.errmsg.url_invalid"),
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
@ -135,15 +135,15 @@ const Webhook = () => {
|
||||
await notifyTest("webhook");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
title: t("settings.notification.push_test_message.succeeded.message"),
|
||||
description: t("settings.notification.push_test_message.succeeded.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
title: t("settings.notification.push_test_message.failed.message"),
|
||||
description: `${t("settings.notification.push_test_message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
@ -225,7 +225,7 @@ const Webhook = () => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
{t("settings.notification.push_test_message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
|
@ -18,24 +18,40 @@ export type NotifyTemplate = {
|
||||
};
|
||||
|
||||
export type NotifyChannels = {
|
||||
email?: NotifyChannelEmail;
|
||||
webhook?: NotifyChannel;
|
||||
dingtalk?: NotifyChannel;
|
||||
lark?: NotifyChannel;
|
||||
telegram?: NotifyChannel;
|
||||
webhook?: NotifyChannel;
|
||||
serverchan?: NotifyChannel;
|
||||
mail?: NotifyChannelMail;
|
||||
bark?: NotifyChannelBark;
|
||||
};
|
||||
|
||||
export type NotifyChannel =
|
||||
| NotifyChannelEmail
|
||||
| NotifyChannelWebhook
|
||||
| NotifyChannelDingTalk
|
||||
| NotifyChannelLark
|
||||
| NotifyChannelTelegram
|
||||
| NotifyChannelWebhook
|
||||
| NotifyChannelServerChan
|
||||
| NotifyChannelMail
|
||||
| NotifyChannelBark;
|
||||
|
||||
export type NotifyChannelEmail = {
|
||||
smtpHost: string;
|
||||
smtpPort: number;
|
||||
smtpTLS: boolean;
|
||||
username: string;
|
||||
password: string;
|
||||
senderAddress: string;
|
||||
receiverAddress: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelWebhook = {
|
||||
url: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelDingTalk = {
|
||||
accessToken: string;
|
||||
secret: string;
|
||||
@ -53,26 +69,11 @@ export type NotifyChannelTelegram = {
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelWebhook = {
|
||||
url: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelServerChan = {
|
||||
url: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelMail = {
|
||||
senderAddress: string;
|
||||
receiverAddresses: string;
|
||||
smtpHostAddr: string;
|
||||
smtpHostPort: string;
|
||||
username: string;
|
||||
password: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelBark = {
|
||||
deviceKey: string;
|
||||
serverUrl: string;
|
||||
|
@ -83,12 +83,12 @@
|
||||
"common.provider.local": "Local Deployment",
|
||||
"common.provider.ssh": "SSH Deployment",
|
||||
"common.provider.webhook": "Webhook",
|
||||
"common.provider.serverchan": "ServerChan",
|
||||
"common.provider.kubernetes": "Kubernetes",
|
||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||
"common.provider.email": "Email",
|
||||
"common.provider.dingtalk": "DingTalk",
|
||||
"common.provider.telegram": "Telegram",
|
||||
"common.provider.lark": "Lark",
|
||||
"common.provider.mail": "Mail",
|
||||
"common.provider.telegram": "Telegram",
|
||||
"common.provider.serverchan": "ServerChan",
|
||||
"common.provider.bark": "Bark"
|
||||
}
|
||||
|
@ -30,18 +30,17 @@
|
||||
"settings.notification.config.enable": "Enable",
|
||||
"settings.notification.config.saved.message": "Configuration saved successfully",
|
||||
"settings.notification.config.failed.message": "Configuration save failed",
|
||||
"settings.notification.config.push.test.message": "Send test notification",
|
||||
"settings.notification.config.push.test.message.failed.message": "Send test notification failed",
|
||||
"settings.notification.config.push.test.message.success.message": "Send test notification successfully",
|
||||
"settings.notification.push_test_message": "Send test notification",
|
||||
"settings.notification.push_test_message.succeeded.message": "Send test notification successfully",
|
||||
"settings.notification.push_test_message.failed.message": "Send test notification failed",
|
||||
"settings.notification.email.smtp_host.placeholder": "SMTP server address",
|
||||
"settings.notification.email.smtp_port.placeholder": "SMTP server port",
|
||||
"settings.notification.email.username.placeholder": "username",
|
||||
"settings.notification.email.password.placeholder": "password",
|
||||
"settings.notification.email.sender_address.placeholder": "Sender email address",
|
||||
"settings.notification.email.receiver_address.placeholder": "Receiver email address",
|
||||
"settings.notification.dingtalk.secret.placeholder": "Signature for signed addition",
|
||||
"settings.notification.url.errmsg.invalid": "Invalid Url format",
|
||||
"settings.notification.serverchan.url.placeholder": "Url, e.g. https://sctapi.ftqq.com/****************.send",
|
||||
"settings.notification.mail.sender_address.placeholder": "Sender email address",
|
||||
"settings.notification.mail.receiver_address.placeholder": "Receiver email address",
|
||||
"settings.notification.mail.smtp_host.placeholder": "SMTP server address",
|
||||
"settings.notification.mail.smtp_port.placeholder": "SMTP server port, if not set, default is 25",
|
||||
"settings.notification.mail.username.placeholder": "username",
|
||||
"settings.notification.mail.password.placeholder": "password",
|
||||
"settings.notification.bark.serverUrl.placeholder": "Server URL, e.g. https://your-bark-server.com, leave it blank to use the bark default server",
|
||||
"settings.notification.bark.deviceKey.placeholder": "Device Key,e.g. XXXXXXXXXXXXXXXXXXXX",
|
||||
|
||||
|
@ -83,12 +83,12 @@
|
||||
"common.provider.local": "本地部署",
|
||||
"common.provider.ssh": "SSH 部署",
|
||||
"common.provider.webhook": "Webhook",
|
||||
"common.provider.serverchan": "Server酱",
|
||||
"common.provider.kubernetes": "Kubernetes",
|
||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||
"common.provider.email": "电子邮件",
|
||||
"common.provider.dingtalk": "钉钉",
|
||||
"common.provider.telegram": "Telegram",
|
||||
"common.provider.lark": "飞书",
|
||||
"common.provider.mail": "电子邮件",
|
||||
"common.provider.telegram": "Telegram",
|
||||
"common.provider.serverchan": "Server酱",
|
||||
"common.provider.bark": "Bark"
|
||||
}
|
||||
|
@ -30,18 +30,17 @@
|
||||
"settings.notification.config.enable": "是否启用",
|
||||
"settings.notification.config.saved.message": "配置保存成功",
|
||||
"settings.notification.config.failed.message": "配置保存失败",
|
||||
"settings.notification.config.push.test.message": "推送测试消息",
|
||||
"settings.notification.config.push.test.message.failed.message": "推送测试消息失败",
|
||||
"settings.notification.config.push.test.message.success.message": "推送测试消息成功",
|
||||
"settings.notification.push_test_message": "推送测试消息",
|
||||
"settings.notification.push_test_message.failed.message": "推送测试消息失败",
|
||||
"settings.notification.push_test_message.succeeded.message": "推送测试消息成功",
|
||||
"settings.notification.email.smtp_host.placeholder": "SMTP服务器地址",
|
||||
"settings.notification.email.smtp_port.placeholder": "SMTP服务器端口, 如果未设置, 默认为25",
|
||||
"settings.notification.email.username.placeholder": "用于登录到邮件服务器的用户名",
|
||||
"settings.notification.email.password.placeholder": "用于登录到邮件服务器的密码",
|
||||
"settings.notification.email.sender_address.placeholder": "发送邮箱地址",
|
||||
"settings.notification.email.receiver_address.placeholder": "接收邮箱地址",
|
||||
"settings.notification.dingtalk.secret.placeholder": "加签的签名",
|
||||
"settings.notification.url.errmsg.invalid": "URL 格式不正确",
|
||||
"settings.notification.serverchan.url.placeholder": "Url, 形如: https://sctapi.ftqq.com/****************.send",
|
||||
"settings.notification.mail.sender_address.placeholder": "发送邮箱地址",
|
||||
"settings.notification.mail.receiver_address.placeholder": "接收邮箱地址",
|
||||
"settings.notification.mail.smtp_host.placeholder": "SMTP服务器地址",
|
||||
"settings.notification.mail.smtp_port.placeholder": "SMTP服务器端口, 如果未设置, 默认为25",
|
||||
"settings.notification.mail.username.placeholder": "用于登录到邮件服务器的用户名",
|
||||
"settings.notification.mail.password.placeholder": "用于登录到邮件服务器的密码",
|
||||
"settings.notification.bark.serverUrl.placeholder": "服务器URL,形如: https://your-bark-server.com, 留空则使用 Bark 默认服务器",
|
||||
"settings.notification.bark.deviceKey.placeholder": "设备密钥,形如: XXXXXXXXXXXXXXXXXXXX",
|
||||
|
||||
|
@ -7,7 +7,7 @@ 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 Mail from "@/components/notify/Mail";
|
||||
import Email from "@/components/notify/Email";
|
||||
import Bark from "@/components/notify/Bark";
|
||||
import { NotifyProvider } from "@/providers/notify";
|
||||
|
||||
@ -27,51 +27,52 @@ const Notify = () => {
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
<div className="border rounded-md p-5 mt-7 shadow-lg">
|
||||
<Accordion type={"single"} className="dark:text-stone-200">
|
||||
<AccordionItem value="item-2" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.dingtalk")}</AccordionTrigger>
|
||||
<AccordionItem value="item-email" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.email")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<DingTalk />
|
||||
<Email />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-3" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.lark")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Lark />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-4" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.telegram")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Telegram />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-5" className="dark:border-stone-200">
|
||||
<AccordionItem value="item-webhook" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.webhook")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Webhook />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-6" className="dark:border-stone-200">
|
||||
<AccordionItem value="item-dingtalk" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.dingtalk")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<DingTalk />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-lark" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.lark")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Lark />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-telegram" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.telegram")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Telegram />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-serverchan" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.serverchan")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<ServerChan />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-7" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.mail")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Mail />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-8" className="dark:border-stone-200">
|
||||
<AccordionItem value="item-bark" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.bark")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Bark />
|
||||
|
Loading…
x
Reference in New Issue
Block a user