mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-05 14:04:54 +00:00
merge source
This commit is contained in:
329
ui/dist/assets/index-BYO3zdEX.js
vendored
Normal file
329
ui/dist/assets/index-BYO3zdEX.js
vendored
Normal file
File diff suppressed because one or more lines are too long
329
ui/dist/assets/index-tBXwi-8W.js
vendored
Normal file
329
ui/dist/assets/index-tBXwi-8W.js
vendored
Normal file
File diff suppressed because one or more lines are too long
15
ui/dist/index.html
vendored
Normal file
15
ui/dist/index.html
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
||||
<script type="module" crossorigin src="/assets/index-BYO3zdEX.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-YqBWA4KK.css">
|
||||
</head>
|
||||
<body class="bg-background">
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
22
ui/src/api/notify.ts
Normal file
22
ui/src/api/notify.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { getPb } from "@/repository/api";
|
||||
|
||||
export const notifyTest = async (channel: string) => {
|
||||
const pb = getPb();
|
||||
|
||||
const resp = await pb.send("/api/notify/test", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: {
|
||||
channel,
|
||||
},
|
||||
});
|
||||
|
||||
if (resp.code != 0) {
|
||||
throw new Error(resp.msg);
|
||||
}
|
||||
|
||||
return resp;
|
||||
};
|
||||
|
@@ -8,7 +8,7 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import AccessAliyunForm from "./AccessAliyunForm";
|
||||
import AccessTencentForm from "./AccessTencentForm";
|
||||
import AccessHuaweicloudForm from "./AccessHuaweicloudForm";
|
||||
import AccessHuaweiCloudForm from "./AccessHuaweicloudForm";
|
||||
import AccessQiniuForm from "./AccessQiniuForm";
|
||||
import AccessAwsForm from "./AccessAwsForm";
|
||||
import AccessCloudflareForm from "./AccessCloudflareForm";
|
||||
@@ -63,7 +63,7 @@ const AccessEdit = ({ trigger, op, data, className }: AccessEditProps) => {
|
||||
break;
|
||||
case "huaweicloud":
|
||||
form = (
|
||||
<AccessHuaweicloudForm
|
||||
<AccessHuaweiCloudForm
|
||||
data={data}
|
||||
op={op}
|
||||
onAfterReq={() => {
|
||||
|
@@ -8,17 +8,17 @@ import { Input } from "@/components/ui/input";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { PbErrorData } from "@/domain/base";
|
||||
import { Access, accessFormType, HuaweicloudConfig, getUsageByConfigType } from "@/domain/access";
|
||||
import { Access, accessFormType, HuaweiCloudConfig, getUsageByConfigType } from "@/domain/access";
|
||||
import { save } from "@/repository/access";
|
||||
import { useConfig } from "@/providers/config";
|
||||
|
||||
type AccessHuaweicloudFormProps = {
|
||||
type AccessHuaweiCloudFormProps = {
|
||||
op: "add" | "edit" | "copy";
|
||||
data?: Access;
|
||||
onAfterReq: () => void;
|
||||
};
|
||||
|
||||
const AccessHuaweicloudForm = ({ data, op, onAfterReq }: AccessHuaweicloudFormProps) => {
|
||||
const AccessHuaweiCloudForm = ({ data, op, onAfterReq }: AccessHuaweiCloudFormProps) => {
|
||||
const { addAccess, updateAccess } = useConfig();
|
||||
const { t } = useTranslation();
|
||||
const formSchema = z.object({
|
||||
@@ -42,12 +42,12 @@ const AccessHuaweicloudForm = ({ data, op, onAfterReq }: AccessHuaweicloudFormPr
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||
});
|
||||
|
||||
let config: HuaweicloudConfig = {
|
||||
let config: HuaweiCloudConfig = {
|
||||
region: "cn-north-1",
|
||||
accessKeyId: "",
|
||||
secretAccessKey: "",
|
||||
};
|
||||
if (data) config = data.config as HuaweicloudConfig;
|
||||
if (data) config = data.config as HuaweiCloudConfig;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
@@ -215,4 +215,4 @@ const AccessHuaweicloudForm = ({ data, op, onAfterReq }: AccessHuaweicloudFormPr
|
||||
);
|
||||
};
|
||||
|
||||
export default AccessHuaweicloudForm;
|
||||
export default AccessHuaweiCloudForm;
|
||||
|
@@ -10,6 +10,8 @@ import { getErrMessage } from "@/lib/error";
|
||||
import { NotifyChannelDingTalk, NotifyChannels } from "@/domain/settings";
|
||||
import { useNotify } from "@/providers/notify";
|
||||
import { update } from "@/repository/settings";
|
||||
import Show from "@/components/Show";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
|
||||
type DingTalkSetting = {
|
||||
id: string;
|
||||
@@ -21,6 +23,8 @@ const DingTalk = () => {
|
||||
const { config, setChannels } = useNotify();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [dingtalk, setDingtalk] = useState<DingTalkSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
@@ -31,23 +35,30 @@ const DingTalk = () => {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const getDetailDingTalk = () => {
|
||||
const df: NotifyChannelDingTalk = {
|
||||
accessToken: "",
|
||||
secret: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.dingtalk) {
|
||||
return df;
|
||||
}
|
||||
const [originDingtalk, setOriginDingtalk] = useState<DingTalkSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
accessToken: "",
|
||||
secret: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
return chanels.dingtalk as NotifyChannelDingTalk;
|
||||
};
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailDingTalk();
|
||||
setOriginDingtalk({
|
||||
id: config.id ?? "",
|
||||
name: "dingtalk",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailDingTalk();
|
||||
setDingtalk({
|
||||
id: config.id ?? "",
|
||||
@@ -58,6 +69,31 @@ const DingTalk = () => {
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const getDetailDingTalk = () => {
|
||||
const df: NotifyChannelDingTalk = {
|
||||
accessToken: "",
|
||||
secret: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.dingtalk) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.dingtalk as NotifyChannelDingTalk;
|
||||
};
|
||||
|
||||
const checkChanged = (data: NotifyChannelDingTalk) => {
|
||||
if (data.accessToken !== originDingtalk.data.accessToken || data.secret !== originDingtalk.data.secret) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
@@ -87,19 +123,74 @@ const DingTalk = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("dingtalk");
|
||||
|
||||
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 = {
|
||||
...dingtalk,
|
||||
data: {
|
||||
...dingtalk.data,
|
||||
enabled: !dingtalk.data.enabled,
|
||||
},
|
||||
};
|
||||
setDingtalk(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
dingtalk: {
|
||||
...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="AccessToken"
|
||||
value={dingtalk.data.accessToken}
|
||||
onChange={(e) => {
|
||||
setDingtalk({
|
||||
const newData = {
|
||||
...dingtalk,
|
||||
data: {
|
||||
...dingtalk.data,
|
||||
accessToken: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setDingtalk(newData);
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
@@ -107,43 +198,47 @@ const DingTalk = () => {
|
||||
className="mt-2"
|
||||
value={dingtalk.data.secret}
|
||||
onChange={(e) => {
|
||||
setDingtalk({
|
||||
const newData = {
|
||||
...dingtalk,
|
||||
data: {
|
||||
...dingtalk.data,
|
||||
secret: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
checkChanged(newData.data);
|
||||
setDingtalk(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch
|
||||
id="airplane-mode"
|
||||
checked={dingtalk.data.enabled}
|
||||
onCheckedChange={() => {
|
||||
setDingtalk({
|
||||
...dingtalk,
|
||||
data: {
|
||||
...dingtalk.data,
|
||||
enabled: !dingtalk.data.enabled,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Switch id="airplane-mode" checked={dingtalk.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && dingtalk.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DingTalk;
|
||||
|
||||
|
@@ -1,14 +1,16 @@
|
||||
import { Input } from "../ui/input";
|
||||
import { Button } from "../ui/button";
|
||||
import { Switch } from "../ui/switch";
|
||||
import { Label } from "../ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useNotify } from "@/providers/notify";
|
||||
import { NotifyChannelLark, NotifyChannels } from "@/domain/settings";
|
||||
import { useEffect, useState } from "react";
|
||||
import { update } from "@/repository/settings";
|
||||
import { getErrMessage } from "@/lib/error";
|
||||
import { useToast } from "../ui/use-toast";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type LarkSetting = {
|
||||
id: string;
|
||||
@@ -20,6 +22,8 @@ const Lark = () => {
|
||||
const { config, setChannels } = useNotify();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [lark, setLark] = useState<LarkSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
@@ -29,22 +33,29 @@ const Lark = () => {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const getDetailLark = () => {
|
||||
const df: NotifyChannelLark = {
|
||||
webhookUrl: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.lark) {
|
||||
return df;
|
||||
}
|
||||
const [originLark, setOriginLark] = useState<LarkSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
webhookUrl: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
return chanels.lark as NotifyChannelLark;
|
||||
};
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailLark();
|
||||
setOriginLark({
|
||||
id: config.id ?? "",
|
||||
name: "lark",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailLark();
|
||||
setLark({
|
||||
id: config.id ?? "",
|
||||
@@ -55,6 +66,30 @@ const Lark = () => {
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const checkChanged = (data: NotifyChannelLark) => {
|
||||
if (data.webhookUrl !== originLark.data.webhookUrl) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getDetailLark = () => {
|
||||
const df: NotifyChannelLark = {
|
||||
webhookUrl: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.lark) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.lark as NotifyChannelLark;
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
@@ -78,9 +113,60 @@ const Lark = () => {
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t(
|
||||
"settings.notification.config.failed.message"
|
||||
)}: ${msg}`,
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("lark");
|
||||
|
||||
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 = {
|
||||
...lark,
|
||||
data: {
|
||||
...lark.data,
|
||||
enabled: !lark.data.enabled,
|
||||
},
|
||||
};
|
||||
setLark(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
lark: {
|
||||
...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",
|
||||
});
|
||||
}
|
||||
@@ -92,45 +178,48 @@ const Lark = () => {
|
||||
placeholder="Webhook Url"
|
||||
value={lark.data.webhookUrl}
|
||||
onChange={(e) => {
|
||||
setLark({
|
||||
const newData = {
|
||||
...lark,
|
||||
data: {
|
||||
...lark.data,
|
||||
webhookUrl: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
checkChanged(newData.data);
|
||||
setLark(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch
|
||||
id="airplane-mode"
|
||||
checked={lark.data.enabled}
|
||||
onCheckedChange={() => {
|
||||
setLark({
|
||||
...lark,
|
||||
data: {
|
||||
...lark.data,
|
||||
enabled: !lark.data.enabled,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="airplane-mode">
|
||||
{t("settings.notification.config.enable")}
|
||||
</Label>
|
||||
<Switch id="airplane-mode" checked={lark.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && lark.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Lark;
|
||||
|
||||
|
@@ -10,6 +10,8 @@ import { getErrMessage } from "@/lib/error";
|
||||
import { NotifyChannels, NotifyChannelTelegram } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { useNotify } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type TelegramSetting = {
|
||||
id: string;
|
||||
@@ -21,6 +23,8 @@ const Telegram = () => {
|
||||
const { config, setChannels } = useNotify();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [telegram, setTelegram] = useState<TelegramSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
@@ -31,23 +35,30 @@ const Telegram = () => {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const getDetailTelegram = () => {
|
||||
const df: NotifyChannelTelegram = {
|
||||
apiToken: "",
|
||||
chatId: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.telegram) {
|
||||
return df;
|
||||
}
|
||||
const [originTelegram, setOriginTelegram] = useState<TelegramSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
apiToken: "",
|
||||
chatId: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
return chanels.telegram as NotifyChannelTelegram;
|
||||
};
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailTelegram();
|
||||
setOriginTelegram({
|
||||
id: config.id ?? "",
|
||||
name: "common.provider.telegram",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailTelegram();
|
||||
setTelegram({
|
||||
id: config.id ?? "",
|
||||
@@ -58,6 +69,31 @@ const Telegram = () => {
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const checkChanged = (data: NotifyChannelTelegram) => {
|
||||
if (data.apiToken !== originTelegram.data.apiToken || data.chatId !== originTelegram.data.chatId) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getDetailTelegram = () => {
|
||||
const df: NotifyChannelTelegram = {
|
||||
apiToken: "",
|
||||
chatId: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.telegram) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.telegram as NotifyChannelTelegram;
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
const resp = await update({
|
||||
@@ -87,19 +123,75 @@ const Telegram = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("telegram");
|
||||
|
||||
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 = {
|
||||
...telegram,
|
||||
data: {
|
||||
...telegram.data,
|
||||
enabled: !telegram.data.enabled,
|
||||
},
|
||||
};
|
||||
setTelegram(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
telegram: {
|
||||
...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="ApiToken"
|
||||
value={telegram.data.apiToken}
|
||||
onChange={(e) => {
|
||||
setTelegram({
|
||||
const newData = {
|
||||
...telegram,
|
||||
data: {
|
||||
...telegram.data,
|
||||
apiToken: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
checkChanged(newData.data);
|
||||
setTelegram(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -107,44 +199,49 @@ const Telegram = () => {
|
||||
placeholder="ChatId"
|
||||
value={telegram.data.chatId}
|
||||
onChange={(e) => {
|
||||
setTelegram({
|
||||
const newData = {
|
||||
...telegram,
|
||||
data: {
|
||||
...telegram.data,
|
||||
chatId: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
checkChanged(newData.data);
|
||||
setTelegram(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch
|
||||
id="airplane-mode"
|
||||
checked={telegram.data.enabled}
|
||||
onCheckedChange={() => {
|
||||
setTelegram({
|
||||
...telegram,
|
||||
data: {
|
||||
...telegram.data,
|
||||
enabled: !telegram.data.enabled,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Switch id="airplane-mode" checked={telegram.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && telegram.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Telegram;
|
||||
|
||||
|
@@ -11,6 +11,8 @@ import { isValidURL } from "@/lib/url";
|
||||
import { NotifyChannels, NotifyChannelWebhook } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { useNotify } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type WebhookSetting = {
|
||||
id: string;
|
||||
@@ -21,6 +23,7 @@ type WebhookSetting = {
|
||||
const Webhook = () => {
|
||||
const { config, setChannels } = useNotify();
|
||||
const { t } = useTranslation();
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [webhook, setWebhook] = useState<WebhookSetting>({
|
||||
id: config.id ?? "",
|
||||
@@ -31,22 +34,29 @@ const Webhook = () => {
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const getDetailWebhook = () => {
|
||||
const df: NotifyChannelWebhook = {
|
||||
url: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.webhook) {
|
||||
return df;
|
||||
}
|
||||
const [originWebhook, setOriginWebhook] = useState<WebhookSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
url: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
return chanels.webhook as NotifyChannelWebhook;
|
||||
};
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailWebhook();
|
||||
setOriginWebhook({
|
||||
id: config.id ?? "",
|
||||
name: "webhook",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailWebhook();
|
||||
setWebhook({
|
||||
id: config.id ?? "",
|
||||
@@ -57,6 +67,30 @@ const Webhook = () => {
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const checkChanged = (data: NotifyChannelWebhook) => {
|
||||
if (data.url !== originWebhook.data.url) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getDetailWebhook = () => {
|
||||
const df: NotifyChannelWebhook = {
|
||||
url: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.webhook) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.webhook as NotifyChannelWebhook;
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
webhook.data.url = webhook.data.url.trim();
|
||||
@@ -96,50 +130,108 @@ const Webhook = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("webhook");
|
||||
|
||||
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 = {
|
||||
...webhook,
|
||||
data: {
|
||||
...webhook.data,
|
||||
enabled: !webhook.data.enabled,
|
||||
},
|
||||
};
|
||||
setWebhook(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
webhook: {
|
||||
...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="Url"
|
||||
value={webhook.data.url}
|
||||
onChange={(e) => {
|
||||
setWebhook({
|
||||
const newData = {
|
||||
...webhook,
|
||||
data: {
|
||||
...webhook.data,
|
||||
url: e.target.value,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
checkChanged(newData.data);
|
||||
setWebhook(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch
|
||||
id="airplane-mode"
|
||||
checked={webhook.data.enabled}
|
||||
onCheckedChange={() => {
|
||||
setWebhook({
|
||||
...webhook,
|
||||
data: {
|
||||
...webhook.data,
|
||||
enabled: !webhook.data.enabled,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Switch id="airplane-mode" checked={webhook.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && webhook.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Webhook;
|
||||
|
||||
|
@@ -52,7 +52,7 @@ export type Access = {
|
||||
config:
|
||||
| AliyunConfig
|
||||
| TencentConfig
|
||||
| HuaweicloudConfig
|
||||
| HuaweiCloudConfig
|
||||
| QiniuConfig
|
||||
| AwsConfig
|
||||
| CloudflareConfig
|
||||
@@ -79,7 +79,7 @@ export type TencentConfig = {
|
||||
secretKey: string;
|
||||
};
|
||||
|
||||
export type HuaweicloudConfig = {
|
||||
export type HuaweiCloudConfig = {
|
||||
region: string;
|
||||
accessKeyId: string;
|
||||
secretAccessKey: string;
|
||||
|
@@ -71,6 +71,7 @@ export const targetTypeMap: Map<string, [string, string]> = new Map([
|
||||
["aliyun-cdn", ["common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"]],
|
||||
["aliyun-dcdn", ["common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"]],
|
||||
["tencent-cdn", ["common.provider.tencent.cdn", "/imgs/providers/tencent.svg"]],
|
||||
["huaweicloud-cdn", ["common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"]],
|
||||
["qiniu-cdn", ["common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"]],
|
||||
["local", ["common.provider.local", "/imgs/providers/local.svg"]],
|
||||
["ssh", ["common.provider.ssh", "/imgs/providers/ssh.svg"]],
|
||||
|
@@ -59,6 +59,7 @@
|
||||
"common.provider.tencent": "Tencent",
|
||||
"common.provider.tencent.cdn": "Tencent - CDN",
|
||||
"common.provider.huaweicloud": "Huawei Cloud",
|
||||
"common.provider.huaweicloud.cdn": "Huawei Cloud - CDN",
|
||||
"common.provider.qiniu": "Qiniu",
|
||||
"common.provider.qiniu.cdn": "Qiniu - CDN",
|
||||
"common.provider.aws": "AWS",
|
||||
|
@@ -13,7 +13,7 @@
|
||||
"domain.deploy.started.tips": "Deployment initiated, please check the deployment log later.",
|
||||
"domain.deploy.failed.message": "Execution Failed",
|
||||
"domain.deploy.failed.tips": "Execution failed, please check the details in <1>Deployment History</1>.",
|
||||
"domain.deploy_forced": "Force Deployment",
|
||||
"domain.deploy_forced": "Force Deploy",
|
||||
|
||||
"domain.props.expiry": "Validity Period",
|
||||
"domain.props.expiry.date1": "Valid for {{date}} days",
|
||||
|
@@ -30,6 +30,9 @@
|
||||
"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.dingtalk.secret.placeholder": "Signature for signed addition",
|
||||
"settings.notification.url.errmsg.invalid": "Invalid Url format",
|
||||
|
||||
@@ -39,3 +42,4 @@
|
||||
"settings.ca.eab_hmac_key.errmsg.empty": "Please enter EAB_HMAC_KEY.",
|
||||
"settings.ca.eab_kid_hmac_key.errmsg.empty": "Please enter EAB_KID and EAB_HMAC_KEY"
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,7 @@
|
||||
"common.provider.aliyun.cdn": "阿里云 - CDN",
|
||||
"common.provider.aliyun.dcdn": "阿里云 - DCDN",
|
||||
"common.provider.huaweicloud": "华为云",
|
||||
"common.provider.huaweicloud.cdn": "华为云 - CDN",
|
||||
"common.provider.qiniu": "七牛云",
|
||||
"common.provider.qiniu.cdn": "七牛云 - CDN",
|
||||
"common.provider.aws": "AWS",
|
||||
|
@@ -30,6 +30,9 @@
|
||||
"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.dingtalk.secret.placeholder": "加签的签名",
|
||||
"settings.notification.url.errmsg.invalid": "URL 格式不正确",
|
||||
|
||||
@@ -39,3 +42,4 @@
|
||||
"settings.ca.eab_hmac_key.errmsg.empty": "请输入EAB_HMAC_KEY",
|
||||
"settings.ca.eab_kid_hmac_key.errmsg.empty": "请输入EAB_KID和EAB_HMAC_KEY"
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user