mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 17:31:55 +08:00
chore: improve i18n
This commit is contained in:
parent
9bd279a8a0
commit
e397793153
1
ui/dist/assets/index-CV_7sKTK.css
vendored
Normal file
1
ui/dist/assets/index-CV_7sKTK.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
ui/dist/assets/index-CWUb5Xuf.css
vendored
1
ui/dist/assets/index-CWUb5Xuf.css
vendored
File diff suppressed because one or more lines are too long
324
ui/dist/assets/index-Dm8Q4Rp7.js
vendored
Normal file
324
ui/dist/assets/index-Dm8Q4Rp7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
332
ui/dist/assets/index-DvxNVikK.js
vendored
332
ui/dist/assets/index-DvxNVikK.js
vendored
File diff suppressed because one or more lines are too long
4
ui/dist/index.html
vendored
4
ui/dist/index.html
vendored
@ -5,8 +5,8 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
<title>Certimate - Your Trusted SSL Automation Partner</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DvxNVikK.js"></script>
|
<script type="module" crossorigin src="/assets/index-Dm8Q4Rp7.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CWUb5Xuf.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CV_7sKTK.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-background">
|
<body class="bg-background">
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
|
||||||
export default function LocaleToggle() {
|
export default function LocaleToggle() {
|
||||||
const { i18n } = useTranslation()
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
@ -22,7 +22,7 @@ export default function LocaleToggle() {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
{Object.keys(i18n.store.data).map(key => (
|
{Object.keys(i18n.store.data).map((key) => (
|
||||||
<DropdownMenuItem onClick={() => i18n.changeLanguage(key)}>
|
<DropdownMenuItem onClick={() => i18n.changeLanguage(key)}>
|
||||||
{i18n.store.data[key].name as string}
|
{i18n.store.data[key].name as string}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Moon, Sun } from "lucide-react";
|
import { Moon, Sun } from "lucide-react";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@ -14,7 +14,6 @@ export function ThemeToggle() {
|
|||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
@ -26,13 +25,13 @@ export function ThemeToggle() {
|
|||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
<DropdownMenuItem onClick={() => setTheme("light")}>
|
<DropdownMenuItem onClick={() => setTheme("light")}>
|
||||||
{t('theme.light')}
|
{t("common.theme.light")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
<DropdownMenuItem onClick={() => setTheme("dark")}>
|
||||||
{t('theme.dark')}
|
{t("common.theme.dark")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem onClick={() => setTheme("system")}>
|
<DropdownMenuItem onClick={() => setTheme("system")}>
|
||||||
{t('theme.system')}
|
{t("common.theme.system")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, AliyunConfig, getUsageByConfigType } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
AliyunConfig,
|
||||||
|
getUsageByConfigType,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
|
|
||||||
@ -35,10 +40,19 @@ const AccessAliyunForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
accessKeyId: z.string().min(1, 'access.form.access.key.id.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
accessKeyId: z
|
||||||
accessSecretId: z.string().min(1, 'access.form.access.key.secret.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
.string()
|
||||||
|
.min(1, "access.authorization.form.access_key_id.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
accessSecretId: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.access_key_secret..placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: AliyunConfig = {
|
let config: AliyunConfig = {
|
||||||
@ -51,7 +65,7 @@ const AccessAliyunForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "aliyun",
|
configType: "aliyun",
|
||||||
accessKeyId: config.accessKeyId,
|
accessKeyId: config.accessKeyId,
|
||||||
accessSecretId: config.accessKeySecret,
|
accessSecretId: config.accessKeySecret,
|
||||||
@ -71,7 +85,7 @@ const AccessAliyunForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -117,9 +131,12 @@ const AccessAliyunForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -132,7 +149,7 @@ const AccessAliyunForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -147,7 +164,7 @@ const AccessAliyunForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -162,9 +179,12 @@ const AccessAliyunForm = ({
|
|||||||
name="accessKeyId"
|
name="accessKeyId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.access.key.id')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.access_key_id.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.access.key.id.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.access_key_id.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -177,9 +197,12 @@ const AccessAliyunForm = ({
|
|||||||
name="accessSecretId"
|
name="accessSecretId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.access.key.secret')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.access_key_secret.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.access.key.secret.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.access_key_secret..placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -190,7 +213,7 @@ const AccessAliyunForm = ({
|
|||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, CloudflareConfig, getUsageByConfigType } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
CloudflareConfig,
|
||||||
|
getUsageByConfigType,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
@ -34,9 +39,15 @@ const AccessCloudflareForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
dnsApiToken: z.string().min(1, 'access.form.cloud.dns.api.token.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
dnsApiToken: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.cloud_dns_api_token.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: CloudflareConfig = {
|
let config: CloudflareConfig = {
|
||||||
@ -48,7 +59,7 @@ const AccessCloudflareForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "cloudflare",
|
configType: "cloudflare",
|
||||||
dnsApiToken: config.dnsApiToken,
|
dnsApiToken: config.dnsApiToken,
|
||||||
},
|
},
|
||||||
@ -67,7 +78,7 @@ const AccessCloudflareForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -111,9 +122,12 @@ const AccessCloudflareForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -126,7 +140,7 @@ const AccessCloudflareForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -141,7 +155,7 @@ const AccessCloudflareForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -156,9 +170,14 @@ const AccessCloudflareForm = ({
|
|||||||
name="dnsApiToken"
|
name="dnsApiToken"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.cloud.dns.api.token')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.cloud_dns_api_token.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.cloud.dns.api.token.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t(
|
||||||
|
"access.authorization.form.cloud_dns_api_token.placeholder"
|
||||||
|
)}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -167,7 +186,7 @@ const AccessCloudflareForm = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -180,15 +180,15 @@ export function AccessEdit({
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
{op == "add"
|
{op == "add"
|
||||||
? t("access.add")
|
? t("access.authorization.add")
|
||||||
: op == "edit"
|
: op == "edit"
|
||||||
? t("access.edit")
|
? t("access.authorization.edit")
|
||||||
: t("access.copy")}
|
: t("access.authorization.copy")}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ScrollArea className="max-h-[80vh]">
|
<ScrollArea className="max-h-[80vh]">
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
<Label>{t("access.type")}</Label>
|
<Label>{t("access.authorization.form.type.label")}</Label>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
@ -197,11 +197,11 @@ export function AccessEdit({
|
|||||||
defaultValue={configType}
|
defaultValue={configType}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="mt-3">
|
<SelectTrigger className="mt-3">
|
||||||
<SelectValue placeholder={t("access.type.not.empty")} />
|
<SelectValue placeholder={t("access.authorization.form.type.placeholder")} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>{t("access.type")}</SelectLabel>
|
<SelectLabel>{t("access.authorization.form.type.list")}</SelectLabel>
|
||||||
{typeKeys.map((key) => (
|
{typeKeys.map((key) => (
|
||||||
<SelectItem value={key} key={key}>
|
<SelectItem value={key} key={key}>
|
||||||
<div
|
<div
|
||||||
|
@ -39,10 +39,19 @@ const AccessGodaddyFrom = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
apiKey: z.string().min(1, 'access.form.go.daddy.api.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
apiKey: z
|
||||||
apiSecret: z.string().min(1, 'access.form.go.daddy.api.secret.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
.string()
|
||||||
|
.min(1, "access.authorization.form.godaddy_api_key.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
apiSecret: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.godaddy_api_secret.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: GodaddyConfig = {
|
let config: GodaddyConfig = {
|
||||||
@ -55,7 +64,7 @@ const AccessGodaddyFrom = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "godaddy",
|
configType: "godaddy",
|
||||||
apiKey: config.apiKey,
|
apiKey: config.apiKey,
|
||||||
apiSecret: config.apiSecret,
|
apiSecret: config.apiSecret,
|
||||||
@ -76,7 +85,7 @@ const AccessGodaddyFrom = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -120,9 +129,12 @@ const AccessGodaddyFrom = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -135,7 +147,7 @@ const AccessGodaddyFrom = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -150,7 +162,7 @@ const AccessGodaddyFrom = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -165,9 +177,12 @@ const AccessGodaddyFrom = ({
|
|||||||
name="apiKey"
|
name="apiKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.go.daddy.api.key')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.godaddy_api_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.go.daddy.api.key.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.godaddy_api_key.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -180,9 +195,14 @@ const AccessGodaddyFrom = ({
|
|||||||
name="apiSecret"
|
name="apiSecret"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.go.daddy.api.secret')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.godaddy_api_secret.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.go.daddy.api.secret.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t(
|
||||||
|
"access.authorization.form.godaddy_api_secret.placeholder"
|
||||||
|
)}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -191,7 +211,7 @@ const AccessGodaddyFrom = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -39,7 +39,10 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z.string().min(1, 'access.group.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.group.form.name.errmsg.empty")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
@ -80,7 +83,7 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
|||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-[600px] w-full dark:text-stone-200">
|
<DialogContent className="sm:max-w-[600px] w-full dark:text-stone-200">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t('access.group.add')}</DialogTitle>
|
<DialogTitle>{t("access.group.add")}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
@ -97,9 +100,13 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.group.name')}</FormLabel>
|
<FormLabel>{t("access.group.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.group.name.not.empty')} {...field} type="text" />
|
<Input
|
||||||
|
placeholder={t("access.group.form.name.errmsg.empty")}
|
||||||
|
{...field}
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -108,7 +115,7 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -48,7 +48,7 @@ const AccessGroupList = () => {
|
|||||||
reloadAccessGroups();
|
reloadAccessGroups();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast({
|
toast({
|
||||||
title: t('delete.failed'),
|
title: t("common.delete.failed.message"),
|
||||||
description: getErrMessage(e),
|
description: getErrMessage(e),
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
@ -69,10 +69,10 @@ const AccessGroupList = () => {
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="text-center text-sm text-muted-foreground mt-3">
|
<div className="text-center text-sm text-muted-foreground mt-3">
|
||||||
{t('access.group.domain.empty')}
|
{t("access.group.domains.nodata")}
|
||||||
</div>
|
</div>
|
||||||
<AccessGroupEdit
|
<AccessGroupEdit
|
||||||
trigger={<Button>{t('access.group.add')}</Button>}
|
trigger={<Button>{t("access.group.add")}</Button>}
|
||||||
className="mt-3"
|
className="mt-3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +86,11 @@ const AccessGroupList = () => {
|
|||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>{accessGroup.name}</CardTitle>
|
<CardTitle>{accessGroup.name}</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
{t('access.group.total', { total: accessGroup.expand ? accessGroup.expand.access.length : 0 })}
|
{t("access.group.total", {
|
||||||
|
total: accessGroup.expand
|
||||||
|
? accessGroup.expand.access.length
|
||||||
|
: 0,
|
||||||
|
})}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="min-h-[180px]">
|
<CardContent className="min-h-[180px]">
|
||||||
@ -120,9 +124,7 @@ const AccessGroupList = () => {
|
|||||||
<div>
|
<div>
|
||||||
<Group size={40} />
|
<Group size={40} />
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-2">
|
<div className="ml-2">{t("access.group.nodata")}</div>
|
||||||
{t('access.group.empty')}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -149,7 +151,7 @@ const AccessGroupList = () => {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('access.all')}
|
{t("access.group.domains")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
@ -157,14 +159,14 @@ const AccessGroupList = () => {
|
|||||||
<Show
|
<Show
|
||||||
when={
|
when={
|
||||||
!accessGroup.expand ||
|
!accessGroup.expand ||
|
||||||
accessGroup.expand.access.length == 0
|
accessGroup.expand.access.length == 0
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Button size="sm" onClick={handleAddAccess}>
|
<Button size="sm" onClick={handleAddAccess}>
|
||||||
{t('access.add')}
|
{t("access.authorization.add")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
@ -173,21 +175,21 @@ const AccessGroupList = () => {
|
|||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button variant={"destructive"} size={"sm"}>
|
<Button variant={"destructive"} size={"sm"}>
|
||||||
{t('delete')}
|
{t("common.delete")}
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
<AlertDialogTitle className="dark:text-gray-200">
|
<AlertDialogTitle className="dark:text-gray-200">
|
||||||
{t('access.group.delete')}
|
{t("access.group.delete")}
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
{t('access.group.delete.confirm')}
|
{t("access.group.delete.confirm")}
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel className="dark:text-gray-200">
|
<AlertDialogCancel className="dark:text-gray-200">
|
||||||
{t('cancel')}
|
{t("common.cancel")}
|
||||||
</AlertDialogCancel>
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -196,7 +198,7 @@ const AccessGroupList = () => {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('confirm')}
|
{t("common.confirm")}
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, HuaweicloudConfig, getUsageByConfigType } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
HuaweicloudConfig,
|
||||||
|
getUsageByConfigType,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
|
|
||||||
@ -35,11 +40,23 @@ const AccessHuaweicloudForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
region: z.string().min(1, 'access.form.region.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
region: z
|
||||||
accessKeyId: z.string().min(1, 'access.form.access.key.id.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
.string()
|
||||||
secretAccessKey: z.string().min(1, 'access.form.access.key.secret.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
.min(1, "access.authorization.form.region.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
accessKeyId: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.access_key_id.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
secretAccessKey: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.access_key_secret..placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: HuaweicloudConfig = {
|
let config: HuaweicloudConfig = {
|
||||||
@ -53,7 +70,7 @@ const AccessHuaweicloudForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "huaweicloud",
|
configType: "huaweicloud",
|
||||||
region: config.region,
|
region: config.region,
|
||||||
accessKeyId: config.accessKeyId,
|
accessKeyId: config.accessKeyId,
|
||||||
@ -75,7 +92,7 @@ const AccessHuaweicloudForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -121,9 +138,12 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -136,7 +156,7 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -151,7 +171,7 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -166,9 +186,12 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="region"
|
name="region"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.region')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.region.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.region.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.region.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -181,9 +204,12 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="accessKeyId"
|
name="accessKeyId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.access.key.id')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.access_key_id.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.access.key.id.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.access_key_id.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -196,9 +222,12 @@ const AccessHuaweicloudForm = ({
|
|||||||
name="secretAccessKey"
|
name="secretAccessKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.access.key.secret')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.access_key_secret.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.access.key.secret.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.access_key_secret..placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -209,7 +238,7 @@ const AccessHuaweicloudForm = ({
|
|||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -35,8 +35,8 @@ const AccessLocalForm = ({
|
|||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "access.form.name.not.empty")
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
.max(64, t("zod.rule.string.max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,10 +107,10 @@ const AccessLocalForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("name")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.name.not.empty")}
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -125,7 +125,7 @@ const AccessLocalForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t("access.form.config.field")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -140,7 +140,7 @@ const AccessLocalForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t("access.form.config.field")}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -153,7 +153,7 @@ const AccessLocalForm = ({
|
|||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t("save")}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, getUsageByConfigType, NamesiloConfig } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
getUsageByConfigType,
|
||||||
|
NamesiloConfig,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
@ -34,9 +39,15 @@ const AccessNamesiloForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
apiKey: z.string().min(1, 'access.form.namesilo.api.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
apiKey: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.namesilo_api_key.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: NamesiloConfig = {
|
let config: NamesiloConfig = {
|
||||||
@ -48,7 +59,7 @@ const AccessNamesiloForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "namesilo",
|
configType: "namesilo",
|
||||||
apiKey: config.apiKey,
|
apiKey: config.apiKey,
|
||||||
},
|
},
|
||||||
@ -66,7 +77,7 @@ const AccessNamesiloForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -110,9 +121,12 @@ const AccessNamesiloForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -125,7 +139,7 @@ const AccessNamesiloForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -140,7 +154,7 @@ const AccessNamesiloForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -155,9 +169,12 @@ const AccessNamesiloForm = ({
|
|||||||
name="apiKey"
|
name="apiKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.namesilo.api.key')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.namesilo_api_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.namesilo.api.key.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.namesilo_api_key.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -166,7 +183,7 @@ const AccessNamesiloForm = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, getUsageByConfigType, QiniuConfig } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
getUsageByConfigType,
|
||||||
|
QiniuConfig,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
|
|
||||||
@ -35,10 +40,13 @@ const AccessQiniuForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
accessKey: z.string().min(1, 'access.form.access.key.not.empty').max(64),
|
accessKey: z.string().min(1, "access.authorization.form.access_key.placeholder").max(64),
|
||||||
secretKey: z.string().min(1, 'access.form.secret.key.not.empty').max(64),
|
secretKey: z.string().min(1, "access.authorization.form.secret_key.placeholder").max(64),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: QiniuConfig = {
|
let config: QiniuConfig = {
|
||||||
@ -51,7 +59,7 @@ const AccessQiniuForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "qiniu",
|
configType: "qiniu",
|
||||||
accessKey: config.accessKey,
|
accessKey: config.accessKey,
|
||||||
secretKey: config.secretKey,
|
secretKey: config.secretKey,
|
||||||
@ -71,7 +79,7 @@ const AccessQiniuForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -116,9 +124,12 @@ const AccessQiniuForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -131,7 +142,7 @@ const AccessQiniuForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -146,7 +157,7 @@ const AccessQiniuForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -161,9 +172,12 @@ const AccessQiniuForm = ({
|
|||||||
name="accessKey"
|
name="accessKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.access.key')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.access_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.access.key.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.access_key.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -176,9 +190,12 @@ const AccessQiniuForm = ({
|
|||||||
name="secretKey"
|
name="secretKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.secret.key')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.secret_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.secret.key.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.secret_key.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -189,7 +206,7 @@ const AccessQiniuForm = ({
|
|||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -67,34 +67,34 @@ const AccessSSHForm = ({
|
|||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "access.form.name.not.empty")
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
.max(64, t("zod.rule.string.max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
host: z.string().refine(
|
host: z.string().refine(
|
||||||
(str) => {
|
(str) => {
|
||||||
return ipReg.test(str) || domainReg.test(str);
|
return ipReg.test(str) || domainReg.test(str);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: "zod.rule.ssh.host",
|
message: "common.errmsg.host_invalid",
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
group: z.string().optional(),
|
group: z.string().optional(),
|
||||||
port: z
|
port: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "access.form.ssh.port.not.empty")
|
.min(1, "access.authorization.form.ssh_port.placeholder")
|
||||||
.max(5, t("zod.rule.string.max", { max: 5 })),
|
.max(5, t("common.errmsg.string_max", { max: 5 })),
|
||||||
username: z
|
username: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, "username.not.empty")
|
.min(1, "username.not.empty")
|
||||||
.max(64, t("zod.rule.string.max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
password: z
|
password: z
|
||||||
.string()
|
.string()
|
||||||
.min(0, "password.not.empty")
|
.min(0, "password.not.empty")
|
||||||
.max(64, t("zod.rule.string.max", { max: 64 })),
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
key: z
|
key: z
|
||||||
.string()
|
.string()
|
||||||
.min(0, "access.form.ssh.key.not.empty")
|
.min(0, "access.authorization.form.ssh_key.placeholder")
|
||||||
.max(20480, t("zod.rule.string.max", { max: 20480 })),
|
.max(20480, t("common.errmsg.string_max", { max: 20480 })),
|
||||||
keyFile: z.any().optional(),
|
keyFile: z.any().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -225,10 +225,14 @@ const AccessSSHForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("name")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.name.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.name.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.name.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -244,12 +248,12 @@ const AccessSSHForm = ({
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="w-full flex justify-between">
|
<FormLabel className="w-full flex justify-between">
|
||||||
<div>{t("access.form.ssh.group.label")}</div>
|
<div>{t("access.authorization.form.ssh_group.label")}</div>
|
||||||
<AccessGroupEdit
|
<AccessGroupEdit
|
||||||
trigger={
|
trigger={
|
||||||
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
||||||
<Plus size={14} />
|
<Plus size={14} />
|
||||||
{t("add")}
|
{t("common.add")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -265,7 +269,9 @@ const AccessSSHForm = ({
|
|||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t("access.group.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.access_group.placeholder"
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -306,7 +312,9 @@ const AccessSSHForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t("access.form.config.field")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.config.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -321,7 +329,9 @@ const AccessSSHForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t("access.form.config.field")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.config.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -336,10 +346,14 @@ const AccessSSHForm = ({
|
|||||||
name="host"
|
name="host"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="grow">
|
<FormItem className="grow">
|
||||||
<FormLabel>{t("access.form.ssh.host")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.ssh_host.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.host.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_host.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -354,10 +368,14 @@ const AccessSSHForm = ({
|
|||||||
name="port"
|
name="port"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("access.form.ssh.port")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.ssh_port.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.port.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_port.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
type="number"
|
type="number"
|
||||||
/>
|
/>
|
||||||
@ -374,9 +392,16 @@ const AccessSSHForm = ({
|
|||||||
name="username"
|
name="username"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("username")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.username.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t("username.not.empty")} {...field} />
|
<Input
|
||||||
|
placeholder={t(
|
||||||
|
"access.authorization.form.username.placeholder"
|
||||||
|
)}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -389,10 +414,14 @@ const AccessSSHForm = ({
|
|||||||
name="password"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("password")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.password.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("password.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.password.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
@ -408,10 +437,14 @@ const AccessSSHForm = ({
|
|||||||
name="key"
|
name="key"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem hidden>
|
<FormItem hidden>
|
||||||
<FormLabel>{t("access.form.ssh.key")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.ssh_key.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.key.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_key.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -426,7 +459,9 @@ const AccessSSHForm = ({
|
|||||||
name="keyFile"
|
name="keyFile"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("access.form.ssh.key")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("access.authorization.form.ssh_key.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
@ -438,10 +473,14 @@ const AccessSSHForm = ({
|
|||||||
>
|
>
|
||||||
{fileName
|
{fileName
|
||||||
? fileName
|
? fileName
|
||||||
: t("access.form.ssh.key.file.not.empty")}
|
: t(
|
||||||
|
"access.authorization.form.ssh_key_file.placeholder"
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.key.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_key.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
className="hidden"
|
className="hidden"
|
||||||
@ -460,7 +499,7 @@ const AccessSSHForm = ({
|
|||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t("save")}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, getUsageByConfigType, TencentConfig } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
getUsageByConfigType,
|
||||||
|
TencentConfig,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
@ -34,10 +39,19 @@ const AccessTencentForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
secretId: z.string().min(1, 'access.form.secret.id.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
secretId: z
|
||||||
secretKey: z.string().min(1, 'access.form.secret.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
.string()
|
||||||
|
.min(1, "access.authorization.form.secret_id.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
|
secretKey: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.secret_key.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: TencentConfig = {
|
let config: TencentConfig = {
|
||||||
@ -50,7 +64,7 @@ const AccessTencentForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "tencent",
|
configType: "tencent",
|
||||||
secretId: config.secretId,
|
secretId: config.secretId,
|
||||||
secretKey: config.secretKey,
|
secretKey: config.secretKey,
|
||||||
@ -70,7 +84,7 @@ const AccessTencentForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -113,9 +127,12 @@ const AccessTencentForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -128,7 +145,7 @@ const AccessTencentForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -143,7 +160,7 @@ const AccessTencentForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -158,9 +175,12 @@ const AccessTencentForm = ({
|
|||||||
name="secretId"
|
name="secretId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.secret.id')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.secret_id.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.secret.id.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.secret_id.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -173,9 +193,12 @@ const AccessTencentForm = ({
|
|||||||
name="secretKey"
|
name="secretKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.secret.key')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.secret_key.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.secret.key.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.secret_key.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -184,7 +207,7 @@ const AccessTencentForm = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -15,7 +15,12 @@ import {
|
|||||||
} from "@/components/ui/form";
|
} from "@/components/ui/form";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
import { Access, accessFormType, getUsageByConfigType, WebhookConfig } from "@/domain/access";
|
import {
|
||||||
|
Access,
|
||||||
|
accessFormType,
|
||||||
|
getUsageByConfigType,
|
||||||
|
WebhookConfig,
|
||||||
|
} from "@/domain/access";
|
||||||
import { save } from "@/repository/access";
|
import { save } from "@/repository/access";
|
||||||
import { useConfig } from "@/providers/config";
|
import { useConfig } from "@/providers/config";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
@ -34,9 +39,12 @@ const WebhookForm = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
name: z
|
||||||
|
.string()
|
||||||
|
.min(1, "access.authorization.form.name.placeholder")
|
||||||
|
.max(64, t("common.errmsg.string_max", { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
url: z.string().url('zod.rule.url'),
|
url: z.string().url("common.errmsg.url_invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: WebhookConfig = {
|
let config: WebhookConfig = {
|
||||||
@ -48,7 +56,7 @@ const WebhookForm = ({
|
|||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name || '',
|
name: data?.name || "",
|
||||||
configType: "webhook",
|
configType: "webhook",
|
||||||
url: config.url,
|
url: config.url,
|
||||||
},
|
},
|
||||||
@ -66,7 +74,7 @@ const WebhookForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
req.id = op == "copy" ? "" : req.id;
|
req.id = op == "copy" ? "" : req.id;
|
||||||
const rs = await save(req);
|
const rs = await save(req);
|
||||||
|
|
||||||
onAfterReq();
|
onAfterReq();
|
||||||
@ -110,9 +118,12 @@ const WebhookForm = ({
|
|||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('name')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.name.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.name.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -125,7 +136,7 @@ const WebhookForm = ({
|
|||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -140,7 +151,7 @@ const WebhookForm = ({
|
|||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.config.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -155,9 +166,12 @@ const WebhookForm = ({
|
|||||||
name="url"
|
name="url"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('access.form.webhook.url')}</FormLabel>
|
<FormLabel>{t("access.authorization.form.webhook_url.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('access.form.webhook.url.not.empty')} {...field} />
|
<Input
|
||||||
|
placeholder={t("access.authorization.form.webhook_url.placeholder")}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -166,7 +180,7 @@ const WebhookForm = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -113,13 +113,13 @@ const DeployList = ({ deploys, onChange }: DeployListProps) => {
|
|||||||
fallback={
|
fallback={
|
||||||
<Alert className="w-full border dark:border-stone-400">
|
<Alert className="w-full border dark:border-stone-400">
|
||||||
<AlertDescription className="flex flex-col items-center">
|
<AlertDescription className="flex flex-col items-center">
|
||||||
<div>{t("deployment.not.added")}</div>
|
<div>{t("domain.deployment.nodata")}</div>
|
||||||
<div className="flex justify-end mt-2">
|
<div className="flex justify-end mt-2">
|
||||||
<DeployEditDialog
|
<DeployEditDialog
|
||||||
onSave={(config: DeployConfig) => {
|
onSave={(config: DeployConfig) => {
|
||||||
handleAdd(config);
|
handleAdd(config);
|
||||||
}}
|
}}
|
||||||
trigger={<Button size={"sm"}>{t("add")}</Button>}
|
trigger={<Button size={"sm"}>{t("common.add")}</Button>}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
@ -128,7 +128,7 @@ const DeployList = ({ deploys, onChange }: DeployListProps) => {
|
|||||||
>
|
>
|
||||||
<div className="flex justify-end py-2 border-b dark:border-stone-400">
|
<div className="flex justify-end py-2 border-b dark:border-stone-400">
|
||||||
<DeployEditDialog
|
<DeployEditDialog
|
||||||
trigger={<Button size={"sm"}>{t("add")}</Button>}
|
trigger={<Button size={"sm"}>{t("common.add")}</Button>}
|
||||||
onSave={(config: DeployConfig) => {
|
onSave={(config: DeployConfig) => {
|
||||||
handleAdd(config);
|
handleAdd(config);
|
||||||
}}
|
}}
|
||||||
@ -308,13 +308,13 @@ const DeployEditDialog = ({
|
|||||||
// 关闭弹框
|
// 关闭弹框
|
||||||
const newError = { ...error };
|
const newError = { ...error };
|
||||||
if (locDeployConfig.type === "") {
|
if (locDeployConfig.type === "") {
|
||||||
newError.type = t("domain.management.edit.access.not.empty.message");
|
newError.type = t("domain.deployment.form.access.placeholder");
|
||||||
} else {
|
} else {
|
||||||
newError.type = "";
|
newError.type = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locDeployConfig.access === "") {
|
if (locDeployConfig.access === "") {
|
||||||
newError.access = t("domain.management.edit.access.not.empty.message");
|
newError.access = t("domain.deployment.form.access.placeholder");
|
||||||
} else {
|
} else {
|
||||||
newError.access = "";
|
newError.access = "";
|
||||||
}
|
}
|
||||||
@ -351,12 +351,13 @@ const DeployEditDialog = ({
|
|||||||
<DialogTrigger>{trigger}</DialogTrigger>
|
<DialogTrigger>{trigger}</DialogTrigger>
|
||||||
<DialogContent className="dark:text-stone-200">
|
<DialogContent className="dark:text-stone-200">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t("deployment")}</DialogTitle>
|
<DialogTitle>{t("history.page.title")}</DialogTitle>
|
||||||
<DialogDescription></DialogDescription>
|
<DialogDescription></DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
{/* 授权类型 */}
|
|
||||||
|
{/* 部署方式 */}
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("deployment.access.type")}</Label>
|
<Label>{t("domain.deployment.form.type.label")}</Label>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
value={locDeployConfig.type}
|
value={locDeployConfig.type}
|
||||||
@ -366,15 +367,13 @@ const DeployEditDialog = ({
|
|||||||
>
|
>
|
||||||
<SelectTrigger className="mt-2">
|
<SelectTrigger className="mt-2">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t(
|
placeholder={t("domain.deployment.form.type.placeholder")}
|
||||||
"domain.management.edit.access.not.empty.message"
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>
|
<SelectLabel>
|
||||||
{t("domain.management.edit.access.label")}
|
{t("domain.deployment.form.type.list")}
|
||||||
</SelectLabel>
|
</SelectLabel>
|
||||||
{targetTypeKeys.map((item) => (
|
{targetTypeKeys.map((item) => (
|
||||||
<SelectItem key={item} value={item}>
|
<SelectItem key={item} value={item}>
|
||||||
@ -393,15 +392,16 @@ const DeployEditDialog = ({
|
|||||||
|
|
||||||
<div className="text-red-500 text-sm mt-1">{error.type}</div>
|
<div className="text-red-500 text-sm mt-1">{error.type}</div>
|
||||||
</div>
|
</div>
|
||||||
{/* 授权 */}
|
|
||||||
|
{/* 授权配置 */}
|
||||||
<div>
|
<div>
|
||||||
<Label className="flex justify-between">
|
<Label className="flex justify-between">
|
||||||
<div>{t("deployment.access.config")}</div>
|
<div>{t("domain.deployment.form.access.label")}</div>
|
||||||
<AccessEdit
|
<AccessEdit
|
||||||
trigger={
|
trigger={
|
||||||
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
||||||
<Plus size={14} />
|
<Plus size={14} />
|
||||||
{t("add")}
|
{t("common.add")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
op="add"
|
op="add"
|
||||||
@ -417,14 +417,14 @@ const DeployEditDialog = ({
|
|||||||
<SelectTrigger className="mt-2">
|
<SelectTrigger className="mt-2">
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"domain.management.edit.access.not.empty.message"
|
"domain.deployment.form.access.placeholder"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>
|
<SelectLabel>
|
||||||
{t("domain.management.edit.access.label")}
|
{t("domain.deployment.form.access.list")}
|
||||||
</SelectLabel>
|
</SelectLabel>
|
||||||
{targetAccesses.map((item) => (
|
{targetAccesses.map((item) => (
|
||||||
<SelectItem key={item.id} value={item.id}>
|
<SelectItem key={item.id} value={item.id}>
|
||||||
@ -444,6 +444,7 @@ const DeployEditDialog = ({
|
|||||||
<div className="text-red-500 text-sm mt-1">{error.access}</div>
|
<div className="text-red-500 text-sm mt-1">{error.access}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 其他参数 */}
|
||||||
<DeployEdit type={deployType!} />
|
<DeployEdit type={deployType!} />
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
@ -453,7 +454,7 @@ const DeployEditDialog = ({
|
|||||||
handleSaveClick();
|
handleSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("save")}
|
{t("common.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@ -516,9 +517,9 @@ const DeploySSH = () => {
|
|||||||
<>
|
<>
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("access.form.ssh.cert.path")}</Label>
|
<Label>{t("access.authorization.form.ssh_cert_path.label")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.cert.path")}
|
placeholder={t("access.authorization.form.ssh_cert_path.label")}
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
value={data?.config?.certPath}
|
value={data?.config?.certPath}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -533,9 +534,11 @@ const DeploySSH = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("access.form.ssh.key.path")}</Label>
|
<Label>{t("access.authorization.form.ssh_key_path.label")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("access.form.ssh.key.path")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_key_path.placeholder"
|
||||||
|
)}
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
value={data?.config?.keyPath}
|
value={data?.config?.keyPath}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -551,11 +554,13 @@ const DeploySSH = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("access.form.ssh.pre.command")}</Label>
|
<Label>{t("access.authorization.form.ssh_pre_command.label")}</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
className="mt-1"
|
className="mt-1"
|
||||||
value={data?.config?.preCommand}
|
value={data?.config?.preCommand}
|
||||||
placeholder={t("access.form.ssh.pre.command.not.empty")}
|
placeholder={t(
|
||||||
|
"access.authorization.form.ssh_pre_command.placeholder"
|
||||||
|
)}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const newData = produce(data, (draft) => {
|
const newData = produce(data, (draft) => {
|
||||||
if (!draft.config) {
|
if (!draft.config) {
|
||||||
@ -569,11 +574,11 @@ const DeploySSH = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("access.form.ssh.command")}</Label>
|
<Label>{t("access.authorization.form.ssh_command.label")}</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
className="mt-1"
|
className="mt-1"
|
||||||
value={data?.config?.command}
|
value={data?.config?.command}
|
||||||
placeholder={t("access.form.ssh.command.not.empty")}
|
placeholder={t("access.authorization.form.ssh_command.placeholder")}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const newData = produce(data, (draft) => {
|
const newData = produce(data, (draft) => {
|
||||||
if (!draft.config) {
|
if (!draft.config) {
|
||||||
@ -617,15 +622,17 @@ const DeployCDN = () => {
|
|||||||
const domainSchema = z
|
const domainSchema = z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
message: t("domain.not.empty.verify.message"),
|
message: t("common.errmsg.domain_invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("deployment.access.cdn.deploy.to.domain")}</Label>
|
<Label>{t("domain.deployment.form.cdn_domain.label")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("deployment.access.cdn.deploy.to.domain")}
|
placeholder={t(
|
||||||
|
"domain.deployment.form.cdn_domain.placeholder"
|
||||||
|
)}
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
value={data?.config?.domain}
|
value={data?.config?.domain}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -714,17 +721,17 @@ const DeployOSS = () => {
|
|||||||
const domainSchema = z
|
const domainSchema = z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
message: t("domain.not.empty.verify.message"),
|
message: t("common.errmsg.domain_invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const bucketSchema = z.string().min(1, {
|
const bucketSchema = z.string().min(1, {
|
||||||
message: t("deployment.access.oss.bucket.not.empty"),
|
message: t("domain.deployment.form.oss_bucket.placeholder"),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("deployment.access.oss.endpoint")}</Label>
|
<Label>{t("domain.deployment.form.oss_endpoint.label")}</Label>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
@ -743,9 +750,11 @@ const DeployOSS = () => {
|
|||||||
/>
|
/>
|
||||||
<div className="text-red-600 text-sm mt-1">{error?.endpoint}</div>
|
<div className="text-red-600 text-sm mt-1">{error?.endpoint}</div>
|
||||||
|
|
||||||
<Label>{t("deployment.access.oss.bucket")}</Label>
|
<Label>{t("domain.deployment.form.oss_bucket")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("deployment.access.oss.bucket.not.empty")}
|
placeholder={t(
|
||||||
|
"domain.deployment.form.oss_bucket.placeholder"
|
||||||
|
)}
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
value={data?.config?.bucket}
|
value={data?.config?.bucket}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -775,9 +784,9 @@ const DeployOSS = () => {
|
|||||||
/>
|
/>
|
||||||
<div className="text-red-600 text-sm mt-1">{error?.bucket}</div>
|
<div className="text-red-600 text-sm mt-1">{error?.bucket}</div>
|
||||||
|
|
||||||
<Label>{t("deployment.access.cdn.deploy.to.domain")}</Label>
|
<Label>{t("domain.deployment.form.cdn_domain.label")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("deployment.access.cdn.deploy.to.domain")}
|
placeholder={t("domain.deployment.form.cdn_domain.label")}
|
||||||
className="w-full mt-1"
|
className="w-full mt-1"
|
||||||
value={data?.config?.domain}
|
value={data?.config?.domain}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
|
||||||
import { Separator } from "../ui/separator";
|
import { Separator } from "../ui/separator";
|
||||||
|
|
||||||
@ -16,58 +15,52 @@ const DeployProgress = ({ phase, phaseSuccess }: DeployProgressProps) => {
|
|||||||
let step = 0;
|
let step = 0;
|
||||||
|
|
||||||
if (phase === "check") {
|
if (phase === "check") {
|
||||||
step = 1
|
step = 1;
|
||||||
} else if (phase === "apply") {
|
} else if (phase === "apply") {
|
||||||
step = 2
|
step = 2;
|
||||||
} else if (phase === "deploy") {
|
} else if (phase === "deploy") {
|
||||||
step = 3
|
step = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className={
|
<div
|
||||||
cn(
|
className={cn(
|
||||||
"text-xs text-nowrap",
|
"text-xs text-nowrap",
|
||||||
step === 1 ? phaseSuccess ? "text-green-600" : "text-red-600" : "",
|
step === 1 ? (phaseSuccess ? "text-green-600" : "text-red-600") : "",
|
||||||
step > 1 ? "text-green-600" : "",
|
step > 1 ? "text-green-600" : ""
|
||||||
)
|
)}
|
||||||
}>
|
>
|
||||||
{t('deploy.progress.check')}
|
{t("history.props.stage.progress.check")}
|
||||||
</div>
|
</div>
|
||||||
<Separator className={
|
<Separator
|
||||||
cn(
|
className={cn("h-1 grow max-w-[60px]", step > 1 ? "bg-green-600" : "")}
|
||||||
"h-1 grow max-w-[60px]",
|
/>
|
||||||
step > 1 ? "bg-green-600" : "",
|
<div
|
||||||
)
|
className={cn(
|
||||||
} />
|
|
||||||
<div className={
|
|
||||||
cn(
|
|
||||||
"text-xs text-nowrap",
|
"text-xs text-nowrap",
|
||||||
step < 2 ? "text-muted-foreground" : "",
|
step < 2 ? "text-muted-foreground" : "",
|
||||||
step === 2 ? phaseSuccess ? "text-green-600" : "text-red-600" : "",
|
step === 2 ? (phaseSuccess ? "text-green-600" : "text-red-600") : "",
|
||||||
step > 2 ? "text-green-600" : "",
|
step > 2 ? "text-green-600" : ""
|
||||||
)
|
)}
|
||||||
}>
|
>
|
||||||
{t('deploy.progress.apply')}
|
{t("history.props.stage.progress.apply")}
|
||||||
</div>
|
</div>
|
||||||
<Separator className={
|
<Separator
|
||||||
cn(
|
className={cn("h-1 grow max-w-[60px]", step > 2 ? "bg-green-600" : "")}
|
||||||
"h-1 grow max-w-[60px]",
|
/>
|
||||||
step > 2 ? "bg-green-600" : "",
|
<div
|
||||||
)
|
className={cn(
|
||||||
} />
|
|
||||||
<div className={
|
|
||||||
cn(
|
|
||||||
"text-xs text-nowrap",
|
"text-xs text-nowrap",
|
||||||
step < 3 ? "text-muted-foreground" : "",
|
step < 3 ? "text-muted-foreground" : "",
|
||||||
step === 3 ? phaseSuccess ? "text-green-600" : "text-red-600" : "",
|
step === 3 ? (phaseSuccess ? "text-green-600" : "text-red-600") : "",
|
||||||
step > 3 ? "text-green-600" : "",
|
step > 3 ? "text-green-600" : ""
|
||||||
)
|
)}
|
||||||
}>
|
>
|
||||||
{t('deploy.progress.deploy')}
|
{t("history.props.stage.progress.deploy")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeployProgress;
|
export default DeployProgress;
|
||||||
|
@ -43,7 +43,7 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
email: z.string().email("email.valid.message"),
|
email: z.string().email("common.errmsg.email_invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
@ -56,7 +56,7 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
|||||||
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
||||||
if ((emails.content as EmailsSetting).emails.includes(data.email)) {
|
if ((emails.content as EmailsSetting).emails.includes(data.email)) {
|
||||||
form.setError("email", {
|
form.setError("email", {
|
||||||
message: "email.already.exist",
|
message: "common.errmsg.email_duplicate",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
|||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-[600px] w-full dark:text-stone-200">
|
<DialogContent className="sm:max-w-[600px] w-full dark:text-stone-200">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t('email.add')}</DialogTitle>
|
<DialogTitle>{t("domain.application.form.email.add")}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
@ -120,9 +120,13 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
|||||||
name="email"
|
name="email"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('email')}</FormLabel>
|
<FormLabel>{t("domain.application.form.email.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('email.not.empty.message')} {...field} type="email" />
|
<Input
|
||||||
|
placeholder={t("common.errmsg.email_empty")}
|
||||||
|
{...field}
|
||||||
|
type="email"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -131,7 +135,7 @@ const EmailsEdit = ({ className, trigger }: EmailsEditProps) => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('save')}</Button>
|
<Button type="submit">{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -71,7 +71,7 @@ const KVList = ({ variables, onValueChange }: KVListProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex justify-between dark:text-stone-200">
|
<div className="flex justify-between dark:text-stone-200">
|
||||||
<Label>{t("variable")}</Label>
|
<Label>{t("domain.deployment.form.variables.label")}</Label>
|
||||||
<Show when={!!locVariables?.length}>
|
<Show when={!!locVariables?.length}>
|
||||||
<KVEdit
|
<KVEdit
|
||||||
variable={{
|
variable={{
|
||||||
@ -82,7 +82,7 @@ const KVList = ({ variables, onValueChange }: KVListProps) => {
|
|||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Plus size={16} className="cursor-pointer " />
|
<Plus size={16} className="cursor-pointer " />
|
||||||
|
|
||||||
<div className="text-sm ">{t("add")}</div>
|
<div className="text-sm ">{t("common.add")}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
onSave={(variable) => {
|
onSave={(variable) => {
|
||||||
@ -97,7 +97,7 @@ const KVList = ({ variables, onValueChange }: KVListProps) => {
|
|||||||
fallback={
|
fallback={
|
||||||
<div className="border rounded-md p-3 text-sm mt-2 flex flex-col items-center">
|
<div className="border rounded-md p-3 text-sm mt-2 flex flex-col items-center">
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
{t("variable.not.added")}
|
{t("domain.deployment.form.variables.empty")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<KVEdit
|
<KVEdit
|
||||||
@ -105,7 +105,7 @@ const KVList = ({ variables, onValueChange }: KVListProps) => {
|
|||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Plus size={16} className="cursor-pointer " />
|
<Plus size={16} className="cursor-pointer " />
|
||||||
|
|
||||||
<div className="text-sm ">{t("add")}</div>
|
<div className="text-sm ">{t("common.add")}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
variable={{
|
variable={{
|
||||||
@ -175,14 +175,14 @@ const KVEdit = ({ variable, trigger, onSave }: KVEditProps) => {
|
|||||||
const handleSaveClick = () => {
|
const handleSaveClick = () => {
|
||||||
if (!locVariable.key) {
|
if (!locVariable.key) {
|
||||||
setErr({
|
setErr({
|
||||||
key: t("variable.name.required"),
|
key: t("domain.deployment.form.variables.key.required"),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!locVariable.value) {
|
if (!locVariable.value) {
|
||||||
setErr({
|
setErr({
|
||||||
value: t("variable.value.required"),
|
value: t("domain.deployment.form.variables.value.required"),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -204,12 +204,12 @@ const KVEdit = ({ variable, trigger, onSave }: KVEditProps) => {
|
|||||||
<DialogTrigger>{trigger}</DialogTrigger>
|
<DialogTrigger>{trigger}</DialogTrigger>
|
||||||
<DialogContent className="dark:text-stone-200">
|
<DialogContent className="dark:text-stone-200">
|
||||||
<DialogHeader className="flex flex-col">
|
<DialogHeader className="flex flex-col">
|
||||||
<DialogTitle>{t("variable")}</DialogTitle>
|
<DialogTitle>{t("domain.deployment.form.variables.label")}</DialogTitle>
|
||||||
|
|
||||||
<div className="pt-5 flex flex-col items-start">
|
<div className="pt-5 flex flex-col items-start">
|
||||||
<Label>{t("variable.name")}</Label>
|
<Label>{t("domain.deployment.form.variables.key")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("variable.name.placeholder")}
|
placeholder={t("domain.deployment.form.variables.key.placeholder")}
|
||||||
value={locVariable?.key}
|
value={locVariable?.key}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setLocVariable({ ...locVariable, key: e.target.value });
|
setLocVariable({ ...locVariable, key: e.target.value });
|
||||||
@ -220,9 +220,9 @@ const KVEdit = ({ variable, trigger, onSave }: KVEditProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-2 flex flex-col items-start">
|
<div className="pt-2 flex flex-col items-start">
|
||||||
<Label>{t("variable.value")}</Label>
|
<Label>{t("domain.deployment.form.variables.value")}</Label>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("variable.value.placeholder")}
|
placeholder={t("domain.deployment.form.variables.value.placeholder")}
|
||||||
value={locVariable?.value}
|
value={locVariable?.value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setLocVariable({ ...locVariable, value: e.target.value });
|
setLocVariable({ ...locVariable, value: e.target.value });
|
||||||
@ -240,7 +240,7 @@ const KVEdit = ({ variable, trigger, onSave }: KVEditProps) => {
|
|||||||
handleSaveClick();
|
handleSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("save")}
|
{t("common.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
@ -25,9 +25,9 @@ type StringListProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const titles: Record<string, string> = {
|
const titles: Record<string, string> = {
|
||||||
domain: "domain",
|
domain: "common.text.domain",
|
||||||
ip: "IP",
|
ip: "common.text.ip",
|
||||||
dns: "dns",
|
dns: "common.text.dns",
|
||||||
};
|
};
|
||||||
|
|
||||||
const StringList = ({
|
const StringList = ({
|
||||||
@ -90,7 +90,7 @@ const StringList = ({
|
|||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Plus size={16} className="cursor-pointer " />
|
<Plus size={16} className="cursor-pointer " />
|
||||||
|
|
||||||
<div className="text-sm ">{t("add")}</div>
|
<div className="text-sm ">{t("common.add")}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -102,12 +102,12 @@ const StringList = ({
|
|||||||
fallback={
|
fallback={
|
||||||
<div className="border rounded-md p-3 text-sm mt-2 flex flex-col items-center">
|
<div className="border rounded-md p-3 text-sm mt-2 flex flex-col items-center">
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
{t("not.added.yet." + valueType)}
|
{t('common.text.' + valueType + '.empty')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StringEdit
|
<StringEdit
|
||||||
value={""}
|
value={""}
|
||||||
trigger={t("add")}
|
trigger={t("common.add")}
|
||||||
onValueChange={addVal}
|
onValueChange={addVal}
|
||||||
valueType={valueType}
|
valueType={valueType}
|
||||||
/>
|
/>
|
||||||
@ -182,10 +182,10 @@ const StringEdit = ({
|
|||||||
const domainSchema = z
|
const domainSchema = z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
.regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
message: t("domain.not.empty.verify.message"),
|
message: t("common.errmsg.domain_invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const ipSchema = z.string().ip({ message: t("ip.not.empty.verify.message") });
|
const ipSchema = z.string().ip({ message: t("common.errmsg.ip_invalid") });
|
||||||
|
|
||||||
const schedules: Record<ValueType, z.ZodString> = {
|
const schedules: Record<ValueType, z.ZodString> = {
|
||||||
domain: domainSchema,
|
domain: domainSchema,
|
||||||
@ -240,7 +240,7 @@ const StringEdit = ({
|
|||||||
onSaveClick();
|
onSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{op === "add" ? t("add") : t("confirm")}
|
{op === "add" ? t("common.add") : t("common.confirm")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
@ -5,7 +5,7 @@ import { Separator } from "../ui/separator";
|
|||||||
import { version } from "@/domain/version";
|
import { version } from "@/domain/version";
|
||||||
|
|
||||||
const Version = () => {
|
const Version = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed right-0 bottom-0 w-full flex justify-between p-5">
|
<div className="fixed right-0 bottom-0 w-full flex justify-between p-5">
|
||||||
@ -17,7 +17,7 @@ const Version = () => {
|
|||||||
className="flex items-center"
|
className="flex items-center"
|
||||||
>
|
>
|
||||||
<BookOpen size={16} />
|
<BookOpen size={16} />
|
||||||
<div className="ml-1">{t('document')}</div>
|
<div className="ml-1">{t("common.menu.document")}</div>
|
||||||
</a>
|
</a>
|
||||||
<Separator orientation="vertical" className="mx-2" />
|
<Separator orientation="vertical" className="mx-2" />
|
||||||
<a
|
<a
|
||||||
|
@ -8,7 +8,7 @@ import { useEffect, useState } from "react";
|
|||||||
import { update } from "@/repository/settings";
|
import { update } from "@/repository/settings";
|
||||||
import { getErrMessage } from "@/lib/error";
|
import { getErrMessage } from "@/lib/error";
|
||||||
import { useToast } from "../ui/use-toast";
|
import { useToast } from "../ui/use-toast";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
type DingTalkSetting = {
|
type DingTalkSetting = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -72,15 +72,17 @@ const DingTalk = () => {
|
|||||||
|
|
||||||
setChannels(resp);
|
setChannels(resp);
|
||||||
toast({
|
toast({
|
||||||
title: t('save.succeed'),
|
title: t("common.save.succeeded.message"),
|
||||||
description: t('setting.notify.config.save.succeed'),
|
description: t("settings.notification.config.saved.message"),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = getErrMessage(e);
|
const msg = getErrMessage(e);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t('save.failed'),
|
title: t("common.save.failed.message"),
|
||||||
description: `${t('setting.notify.config.save.failed')}: ${msg}`,
|
description: `${t(
|
||||||
|
"settings.notification.config.failed.message"
|
||||||
|
)}: ${msg}`,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -102,7 +104,7 @@ const DingTalk = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('access.form.ding.access.token.placeholder')}
|
placeholder={t("settings.notification.dingtalk.secret.placeholder")}
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
value={dingtalk.data.secret}
|
value={dingtalk.data.secret}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -129,7 +131,9 @@ const DingTalk = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="airplane-mode">{t('setting.notify.config.enable')}</Label>
|
<Label htmlFor="airplane-mode">
|
||||||
|
{t("settings.notification.config.enable")}
|
||||||
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end mt-2">
|
<div className="flex justify-end mt-2">
|
||||||
@ -138,7 +142,7 @@ const DingTalk = () => {
|
|||||||
handleSaveClick();
|
handleSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('save')}
|
{t("common.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from "@/domain/settings";
|
} from "@/domain/settings";
|
||||||
import { getSetting, update } from "@/repository/settings";
|
import { getSetting, update } from "@/repository/settings";
|
||||||
import { useToast } from "../ui/use-toast";
|
import { useToast } from "../ui/use-toast";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const NotifyTemplate = () => {
|
const NotifyTemplate = () => {
|
||||||
const [id, setId] = useState("");
|
const [id, setId] = useState("");
|
||||||
@ -68,8 +68,8 @@ const NotifyTemplate = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t('save.succeed'),
|
title: t("common.save.succeeded.message"),
|
||||||
description: t('setting.notify.template.save.succeed'),
|
description: t("settings.notification.template.saved.message"),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ const NotifyTemplate = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="text-muted-foreground text-sm mt-1">
|
<div className="text-muted-foreground text-sm mt-1">
|
||||||
{t('setting.notify.template.variables.tips.title')}
|
{t("settings.notification.template.variables.tips.title")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
@ -94,10 +94,10 @@ const NotifyTemplate = () => {
|
|||||||
}}
|
}}
|
||||||
></Textarea>
|
></Textarea>
|
||||||
<div className="text-muted-foreground text-sm mt-1">
|
<div className="text-muted-foreground text-sm mt-1">
|
||||||
{t('setting.notify.template.variables.tips.content')}
|
{t("settings.notification.template.variables.tips.content")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-end mt-2">
|
<div className="flex justify-end mt-2">
|
||||||
<Button onClick={handleSaveClick}>{t('save')}</Button>
|
<Button onClick={handleSaveClick}>{t("common.save")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -50,7 +50,7 @@ const Telegram = () => {
|
|||||||
const data = getDetailTelegram();
|
const data = getDetailTelegram();
|
||||||
setTelegram({
|
setTelegram({
|
||||||
id: config.id ?? "",
|
id: config.id ?? "",
|
||||||
name: "telegram",
|
name: "common.provider.telegram",
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
}, [config]);
|
}, [config]);
|
||||||
@ -72,15 +72,17 @@ const Telegram = () => {
|
|||||||
|
|
||||||
setChannels(resp);
|
setChannels(resp);
|
||||||
toast({
|
toast({
|
||||||
title: t('save.succeed'),
|
title: t("common.save.succeeded.message"),
|
||||||
description: t('setting.notify.config.save.succeed'),
|
description: t("settings.notification.config.saved.message"),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = getErrMessage(e);
|
const msg = getErrMessage(e);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t('save.failed'),
|
title: t("common.save.failed.message"),
|
||||||
description: `${t('setting.notify.config.save.failed')}: ${msg}`,
|
description: `${t(
|
||||||
|
"settings.notification.config.failed.message"
|
||||||
|
)}: ${msg}`,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -130,7 +132,9 @@ const Telegram = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="airplane-mode">{t('setting.notify.config.enable')}</Label>
|
<Label htmlFor="airplane-mode">
|
||||||
|
{t("settings.notification.config.enable")}
|
||||||
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end mt-2">
|
<div className="flex justify-end mt-2">
|
||||||
@ -139,7 +143,7 @@ const Telegram = () => {
|
|||||||
handleSaveClick();
|
handleSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('save')}
|
{t("common.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,7 +9,7 @@ import { update } from "@/repository/settings";
|
|||||||
import { getErrMessage } from "@/lib/error";
|
import { getErrMessage } from "@/lib/error";
|
||||||
import { useToast } from "../ui/use-toast";
|
import { useToast } from "../ui/use-toast";
|
||||||
import { isValidURL } from "@/lib/url";
|
import { isValidURL } from "@/lib/url";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
type WebhookSetting = {
|
type WebhookSetting = {
|
||||||
id: string;
|
id: string;
|
||||||
@ -61,8 +61,8 @@ const Webhook = () => {
|
|||||||
webhook.data.url = webhook.data.url.trim();
|
webhook.data.url = webhook.data.url.trim();
|
||||||
if (!isValidURL(webhook.data.url)) {
|
if (!isValidURL(webhook.data.url)) {
|
||||||
toast({
|
toast({
|
||||||
title: t('save.failed'),
|
title: t("common.save.failed.message"),
|
||||||
description: t('setting.notify.config.save.failed.url.not.valid'),
|
description: t("settings.notification.url.errmsg.invalid"),
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -81,15 +81,17 @@ const Webhook = () => {
|
|||||||
|
|
||||||
setChannels(resp);
|
setChannels(resp);
|
||||||
toast({
|
toast({
|
||||||
title: t('save.succeed'),
|
title: t("common.save.succeeded.message"),
|
||||||
description: t('setting.notify.config.save.succeed'),
|
description: t("settings.notification.config.saved.message"),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const msg = getErrMessage(e);
|
const msg = getErrMessage(e);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t('save.failed'),
|
title: t("common.save.failed.message"),
|
||||||
description: `${t('setting.notify.config.save.failed')}: ${msg}`,
|
description: `${t(
|
||||||
|
"settings.notification.config.failed.message"
|
||||||
|
)}: ${msg}`,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -125,7 +127,9 @@ const Webhook = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor="airplane-mode">{t('setting.notify.config.enable')}</Label>
|
<Label htmlFor="airplane-mode">
|
||||||
|
{t("settings.notification.config.enable")}
|
||||||
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end mt-2">
|
<div className="flex justify-end mt-2">
|
||||||
@ -134,7 +138,7 @@ const Webhook = () => {
|
|||||||
handleSaveClick();
|
handleSaveClick();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('save')}
|
{t("common.save")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
||||||
import { ChevronDown } from "lucide-react"
|
import { ChevronDown } from "lucide-react";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const Accordion = AccordionPrimitive.Root
|
const Accordion = AccordionPrimitive.Root;
|
||||||
|
|
||||||
const AccordionItem = React.forwardRef<
|
const AccordionItem = React.forwardRef<
|
||||||
React.ElementRef<typeof AccordionPrimitive.Item>,
|
React.ElementRef<typeof AccordionPrimitive.Item>,
|
||||||
@ -15,8 +15,8 @@ const AccordionItem = React.forwardRef<
|
|||||||
className={cn("border-b", className)}
|
className={cn("border-b", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
AccordionItem.displayName = "AccordionItem"
|
AccordionItem.displayName = "AccordionItem";
|
||||||
|
|
||||||
const AccordionTrigger = React.forwardRef<
|
const AccordionTrigger = React.forwardRef<
|
||||||
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
||||||
@ -35,8 +35,8 @@ const AccordionTrigger = React.forwardRef<
|
|||||||
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
))
|
));
|
||||||
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
||||||
|
|
||||||
const AccordionContent = React.forwardRef<
|
const AccordionContent = React.forwardRef<
|
||||||
React.ElementRef<typeof AccordionPrimitive.Content>,
|
React.ElementRef<typeof AccordionPrimitive.Content>,
|
||||||
@ -49,8 +49,8 @@ const AccordionContent = React.forwardRef<
|
|||||||
>
|
>
|
||||||
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
||||||
</AccordionPrimitive.Content>
|
</AccordionPrimitive.Content>
|
||||||
))
|
));
|
||||||
|
|
||||||
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
||||||
|
|
||||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
const alertVariants = cva(
|
const alertVariants = cva(
|
||||||
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
|
"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
|
||||||
@ -17,7 +17,7 @@ const alertVariants = cva(
|
|||||||
variant: "default",
|
variant: "default",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
|
|
||||||
const Alert = React.forwardRef<
|
const Alert = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
@ -29,8 +29,8 @@ const Alert = React.forwardRef<
|
|||||||
className={cn(alertVariants({ variant }), className)}
|
className={cn(alertVariants({ variant }), className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
Alert.displayName = "Alert"
|
Alert.displayName = "Alert";
|
||||||
|
|
||||||
const AlertTitle = React.forwardRef<
|
const AlertTitle = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
@ -41,8 +41,8 @@ const AlertTitle = React.forwardRef<
|
|||||||
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
className={cn("mb-1 font-medium leading-none tracking-tight", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
AlertTitle.displayName = "AlertTitle"
|
AlertTitle.displayName = "AlertTitle";
|
||||||
|
|
||||||
const AlertDescription = React.forwardRef<
|
const AlertDescription = React.forwardRef<
|
||||||
HTMLParagraphElement,
|
HTMLParagraphElement,
|
||||||
@ -53,7 +53,7 @@ const AlertDescription = React.forwardRef<
|
|||||||
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
className={cn("text-sm [&_p]:leading-relaxed", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
));
|
||||||
AlertDescription.displayName = "AlertDescription"
|
AlertDescription.displayName = "AlertDescription";
|
||||||
|
|
||||||
export { Alert, AlertTitle, AlertDescription }
|
export { Alert, AlertTitle, AlertDescription };
|
||||||
|
@ -64,7 +64,7 @@ const PaginationPrevious = ({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof PaginationLink>) => {
|
}: React.ComponentProps<typeof PaginationLink>) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaginationLink
|
<PaginationLink
|
||||||
@ -74,9 +74,9 @@ const PaginationPrevious = ({
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronLeft className="h-4 w-4" />
|
<ChevronLeft className="h-4 w-4" />
|
||||||
<span>{t('pagination.prev')}</span>
|
<span>{t("common.pagination.prev")}</span>
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
PaginationPrevious.displayName = "PaginationPrevious";
|
PaginationPrevious.displayName = "PaginationPrevious";
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ const PaginationNext = ({
|
|||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof PaginationLink>) => {
|
}: React.ComponentProps<typeof PaginationLink>) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PaginationLink
|
<PaginationLink
|
||||||
@ -93,26 +93,30 @@ const PaginationNext = ({
|
|||||||
className={cn("gap-1 pr-2.5", className)}
|
className={cn("gap-1 pr-2.5", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<span>{t('pagination.next')}</span>
|
<span>{t("common.pagination.next")}</span>
|
||||||
<ChevronRight className="h-4 w-4" />
|
<ChevronRight className="h-4 w-4" />
|
||||||
</PaginationLink>
|
</PaginationLink>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
PaginationNext.displayName = "PaginationNext";
|
PaginationNext.displayName = "PaginationNext";
|
||||||
|
|
||||||
const PaginationEllipsis = ({
|
const PaginationEllipsis = ({
|
||||||
className,
|
className,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"span">) => (
|
}: React.ComponentProps<"span">) => {
|
||||||
<span
|
const { t } = useTranslation();
|
||||||
aria-hidden
|
|
||||||
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
return (
|
||||||
{...props}
|
<span
|
||||||
>
|
aria-hidden
|
||||||
<MoreHorizontal className="h-4 w-4" />
|
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
||||||
<span className="sr-only">More pages</span>
|
{...props}
|
||||||
</span>
|
>
|
||||||
);
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
<span className="sr-only">{t("common.pagination.more")}</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
PaginationEllipsis.displayName = "PaginationEllipsis";
|
PaginationEllipsis.displayName = "PaginationEllipsis";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -1,76 +1,73 @@
|
|||||||
// Inspired by react-hot-toast library
|
// Inspired by react-hot-toast library
|
||||||
import * as React from "react"
|
import * as React from "react";
|
||||||
|
|
||||||
import type {
|
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
|
||||||
ToastActionElement,
|
|
||||||
ToastProps,
|
|
||||||
} from "@/components/ui/toast"
|
|
||||||
|
|
||||||
const TOAST_LIMIT = 1
|
const TOAST_LIMIT = 1;
|
||||||
const TOAST_REMOVE_DELAY = 1000000
|
const TOAST_REMOVE_DELAY = 1000000;
|
||||||
|
|
||||||
type ToasterToast = ToastProps & {
|
type ToasterToast = ToastProps & {
|
||||||
id: string
|
id: string;
|
||||||
title?: React.ReactNode
|
title?: React.ReactNode;
|
||||||
description?: React.ReactNode
|
description?: React.ReactNode;
|
||||||
action?: ToastActionElement
|
action?: ToastActionElement;
|
||||||
}
|
};
|
||||||
|
|
||||||
const actionTypes = {
|
const actionTypes = {
|
||||||
ADD_TOAST: "ADD_TOAST",
|
ADD_TOAST: "ADD_TOAST",
|
||||||
UPDATE_TOAST: "UPDATE_TOAST",
|
UPDATE_TOAST: "UPDATE_TOAST",
|
||||||
DISMISS_TOAST: "DISMISS_TOAST",
|
DISMISS_TOAST: "DISMISS_TOAST",
|
||||||
REMOVE_TOAST: "REMOVE_TOAST",
|
REMOVE_TOAST: "REMOVE_TOAST",
|
||||||
} as const
|
} as const;
|
||||||
|
|
||||||
let count = 0
|
let count = 0;
|
||||||
|
|
||||||
function genId() {
|
function genId() {
|
||||||
count = (count + 1) % Number.MAX_SAFE_INTEGER
|
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
||||||
return count.toString()
|
return count.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionType = typeof actionTypes
|
type ActionType = typeof actionTypes;
|
||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
| {
|
| {
|
||||||
type: ActionType["ADD_TOAST"]
|
type: ActionType["ADD_TOAST"];
|
||||||
toast: ToasterToast
|
toast: ToasterToast;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: ActionType["UPDATE_TOAST"]
|
type: ActionType["UPDATE_TOAST"];
|
||||||
toast: Partial<ToasterToast>
|
toast: Partial<ToasterToast>;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: ActionType["DISMISS_TOAST"]
|
type: ActionType["DISMISS_TOAST"];
|
||||||
toastId?: ToasterToast["id"]
|
toastId?: ToasterToast["id"];
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: ActionType["REMOVE_TOAST"]
|
type: ActionType["REMOVE_TOAST"];
|
||||||
toastId?: ToasterToast["id"]
|
toastId?: ToasterToast["id"];
|
||||||
}
|
};
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
toasts: ToasterToast[]
|
toasts: ToasterToast[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
|
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||||
|
|
||||||
const addToRemoveQueue = (toastId: string) => {
|
const addToRemoveQueue = (toastId: string) => {
|
||||||
if (toastTimeouts.has(toastId)) {
|
if (toastTimeouts.has(toastId)) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
toastTimeouts.delete(toastId)
|
toastTimeouts.delete(toastId);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "REMOVE_TOAST",
|
type: "REMOVE_TOAST",
|
||||||
toastId: toastId,
|
toastId: toastId,
|
||||||
})
|
});
|
||||||
}, TOAST_REMOVE_DELAY)
|
}, TOAST_REMOVE_DELAY);
|
||||||
|
|
||||||
toastTimeouts.set(toastId, timeout)
|
toastTimeouts.set(toastId, timeout);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const reducer = (state: State, action: Action): State => {
|
export const reducer = (state: State, action: Action): State => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
@ -78,7 +75,7 @@ export const reducer = (state: State, action: Action): State => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
||||||
}
|
};
|
||||||
|
|
||||||
case "UPDATE_TOAST":
|
case "UPDATE_TOAST":
|
||||||
return {
|
return {
|
||||||
@ -86,19 +83,19 @@ export const reducer = (state: State, action: Action): State => {
|
|||||||
toasts: state.toasts.map((t) =>
|
toasts: state.toasts.map((t) =>
|
||||||
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
||||||
),
|
),
|
||||||
}
|
};
|
||||||
|
|
||||||
case "DISMISS_TOAST": {
|
case "DISMISS_TOAST": {
|
||||||
const { toastId } = action
|
const { toastId } = action;
|
||||||
|
|
||||||
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
||||||
// but I'll keep it here for simplicity
|
// but I'll keep it here for simplicity
|
||||||
if (toastId) {
|
if (toastId) {
|
||||||
addToRemoveQueue(toastId)
|
addToRemoveQueue(toastId);
|
||||||
} else {
|
} else {
|
||||||
state.toasts.forEach((toast) => {
|
state.toasts.forEach((toast) => {
|
||||||
addToRemoveQueue(toast.id)
|
addToRemoveQueue(toast.id);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -111,44 +108,44 @@ export const reducer = (state: State, action: Action): State => {
|
|||||||
}
|
}
|
||||||
: t
|
: t
|
||||||
),
|
),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
case "REMOVE_TOAST":
|
case "REMOVE_TOAST":
|
||||||
if (action.toastId === undefined) {
|
if (action.toastId === undefined) {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
toasts: [],
|
toasts: [],
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const listeners: Array<(state: State) => void> = []
|
const listeners: Array<(state: State) => void> = [];
|
||||||
|
|
||||||
let memoryState: State = { toasts: [] }
|
let memoryState: State = { toasts: [] };
|
||||||
|
|
||||||
function dispatch(action: Action) {
|
function dispatch(action: Action) {
|
||||||
memoryState = reducer(memoryState, action)
|
memoryState = reducer(memoryState, action);
|
||||||
listeners.forEach((listener) => {
|
listeners.forEach((listener) => {
|
||||||
listener(memoryState)
|
listener(memoryState);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type Toast = Omit<ToasterToast, "id">
|
type Toast = Omit<ToasterToast, "id">;
|
||||||
|
|
||||||
function toast({ ...props }: Toast) {
|
function toast({ ...props }: Toast) {
|
||||||
const id = genId()
|
const id = genId();
|
||||||
|
|
||||||
const update = (props: ToasterToast) =>
|
const update = (props: ToasterToast) =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE_TOAST",
|
type: "UPDATE_TOAST",
|
||||||
toast: { ...props, id },
|
toast: { ...props, id },
|
||||||
})
|
});
|
||||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
|
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "ADD_TOAST",
|
type: "ADD_TOAST",
|
||||||
@ -157,36 +154,36 @@ function toast({ ...props }: Toast) {
|
|||||||
id,
|
id,
|
||||||
open: true,
|
open: true,
|
||||||
onOpenChange: (open) => {
|
onOpenChange: (open) => {
|
||||||
if (!open) dismiss()
|
if (!open) dismiss();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
dismiss,
|
dismiss,
|
||||||
update,
|
update,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function useToast() {
|
function useToast() {
|
||||||
const [state, setState] = React.useState<State>(memoryState)
|
const [state, setState] = React.useState<State>(memoryState);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
listeners.push(setState)
|
listeners.push(setState);
|
||||||
return () => {
|
return () => {
|
||||||
const index = listeners.indexOf(setState)
|
const index = listeners.indexOf(setState);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
listeners.splice(index, 1)
|
listeners.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [state])
|
}, [state]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
toast,
|
toast,
|
||||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { useToast, toast }
|
export { useToast, toast };
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const accessTypeMap: Map<string, [string, string]> = new Map([
|
export const accessTypeMap: Map<string, [string, string]> = new Map([
|
||||||
["aliyun", ["aliyun", "/imgs/providers/aliyun.svg"]],
|
["aliyun", ["common.provider.aliyun", "/imgs/providers/aliyun.svg"]],
|
||||||
["tencent", ["tencent", "/imgs/providers/tencent.svg"]],
|
["tencent", ["common.provider.tencent", "/imgs/providers/tencent.svg"]],
|
||||||
["huaweicloud", ["huaweicloud", "/imgs/providers/huaweicloud.svg"]],
|
["huaweicloud", ["common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg"]],
|
||||||
["qiniu", ["qiniu", "/imgs/providers/qiniu.svg"]],
|
["qiniu", ["common.provider.qiniu", "/imgs/providers/qiniu.svg"]],
|
||||||
["cloudflare", ["cloudflare", "/imgs/providers/cloudflare.svg"]],
|
["cloudflare", ["common.provider.cloudflare", "/imgs/providers/cloudflare.svg"]],
|
||||||
["namesilo", ["namesilo", "/imgs/providers/namesilo.svg"]],
|
["namesilo", ["common.provider.namesilo", "/imgs/providers/namesilo.svg"]],
|
||||||
["godaddy", ["go.daddy", "/imgs/providers/godaddy.svg"]],
|
["godaddy", ["common.provider.godaddy", "/imgs/providers/godaddy.svg"]],
|
||||||
["local", ["local.deployment", "/imgs/providers/local.svg"]],
|
["local", ["common.provider.local", "/imgs/providers/local.svg"]],
|
||||||
["ssh", ["ssh", "/imgs/providers/ssh.svg"]],
|
["ssh", ["common.provider.ssh", "/imgs/providers/ssh.svg"]],
|
||||||
["webhook", ["webhook", "/imgs/providers/webhook.svg"]],
|
["webhook", ["common.provider.webhook", "/imgs/providers/webhook.svg"]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const getProviderInfo = (t: string) => {
|
export const getProviderInfo = (t: string) => {
|
||||||
@ -30,7 +30,7 @@ export const accessFormType = z.union(
|
|||||||
z.literal("ssh"),
|
z.literal("ssh"),
|
||||||
z.literal("webhook"),
|
z.literal("webhook"),
|
||||||
],
|
],
|
||||||
{ message: "access.not.empty" }
|
{ message: "access.common.type.errmsg.empty" }
|
||||||
);
|
);
|
||||||
|
|
||||||
type AccessUsage = "apply" | "deploy" | "all";
|
type AccessUsage = "apply" | "deploy" | "all";
|
||||||
|
@ -66,14 +66,14 @@ export const getLastDeployment = (domain: Domain): Deployment | undefined => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const targetTypeMap: Map<string, [string, string]> = new Map([
|
export const targetTypeMap: Map<string, [string, string]> = new Map([
|
||||||
["aliyun-cdn", ["aliyun.cdn", "/imgs/providers/aliyun.svg"]],
|
["aliyun-oss", ["common.provider.aliyun.oss", "/imgs/providers/aliyun.svg"]],
|
||||||
["aliyun-oss", ["aliyun.oss", "/imgs/providers/aliyun.svg"]],
|
["aliyun-cdn", ["common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"]],
|
||||||
["aliyun-dcdn", ["aliyun.dcdn", "/imgs/providers/aliyun.svg"]],
|
["aliyun-dcdn", ["common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"]],
|
||||||
["tencent-cdn", ["tencent.cdn", "/imgs/providers/tencent.svg"]],
|
["tencent-cdn", ["common.provider.tencent.cdn", "/imgs/providers/tencent.svg"]],
|
||||||
["ssh", ["ssh", "/imgs/providers/ssh.svg"]],
|
["qiniu-cdn", ["common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"]],
|
||||||
["qiniu-cdn", ["qiniu.cdn", "/imgs/providers/qiniu.svg"]],
|
["local", ["common.provider.local", "/imgs/providers/local.svg"]],
|
||||||
["webhook", ["webhook", "/imgs/providers/webhook.svg"]],
|
["ssh", ["common.provider.ssh", "/imgs/providers/ssh.svg"]],
|
||||||
["local", ["local.deployment", "/imgs/providers/local.svg"]],
|
["webhook", ["common.provider.webhook", "/imgs/providers/webhook.svg"]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const targetTypeKeys = Array.from(targetTypeMap.keys());
|
export const targetTypeKeys = Array.from(targetTypeMap.keys());
|
||||||
|
@ -50,8 +50,8 @@ export type NotifyChannelWebhook = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const defaultNotifyTemplate: NotifyTemplate = {
|
export const defaultNotifyTemplate: NotifyTemplate = {
|
||||||
title: "您有{COUNT}张证书即将过期",
|
title: "您有 {COUNT} 张证书即将过期",
|
||||||
content: "有{COUNT}张证书即将过期,域名分别为{DOMAINS},请保持关注!",
|
content: "有 {COUNT} 张证书即将过期,域名分别为 {DOMAINS},请保持关注!",
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SSLProvider = "letsencrypt" | "zerossl";
|
export type SSLProvider = "letsencrypt" | "zerossl";
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import i18n from 'i18next';
|
import i18n from "i18next";
|
||||||
import { initReactI18next } from 'react-i18next';
|
import { initReactI18next } from "react-i18next";
|
||||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
|
|
||||||
import resources from './locales'
|
import resources from "./locales";
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(LanguageDetector)
|
.use(LanguageDetector)
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
resources,
|
resources,
|
||||||
fallbackLng: 'zh',
|
fallbackLng: "zh",
|
||||||
debug: true,
|
debug: true,
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false,
|
escapeValue: false,
|
||||||
},
|
},
|
||||||
backend: {
|
backend: {
|
||||||
loadPath: '/locales/{{lng}}.json',
|
loadPath: "/locales/{{lng}}.json",
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
export default i18n;
|
||||||
|
@ -1,247 +0,0 @@
|
|||||||
{
|
|
||||||
"ca": "Certificate Authority",
|
|
||||||
"username": "Username",
|
|
||||||
"username.not.empty": "Please enter username",
|
|
||||||
"password": "Password",
|
|
||||||
"password.not.empty": "Please enter password",
|
|
||||||
"ip.not.empty.verify.message": "Please enter Ip",
|
|
||||||
"email": "Email",
|
|
||||||
"logout": "Logout",
|
|
||||||
"setting": "Settings",
|
|
||||||
"account": "Account",
|
|
||||||
"template": "Template",
|
|
||||||
"save": "Save",
|
|
||||||
"next": "Next",
|
|
||||||
"no.data": "No data available",
|
|
||||||
"status": "Status",
|
|
||||||
"operation": "Operation",
|
|
||||||
"enable": "Enable",
|
|
||||||
"disable": "Disable",
|
|
||||||
"deploy": "Deploy",
|
|
||||||
"download": "Download",
|
|
||||||
"delete": "Delete",
|
|
||||||
"cancel": "Cancel",
|
|
||||||
"confirm": "Confirm",
|
|
||||||
"edit": "Edit",
|
|
||||||
"copy": "Copy",
|
|
||||||
"succeed": "Successful",
|
|
||||||
"add": "Add",
|
|
||||||
"document": "Document",
|
|
||||||
"variables": "Variables",
|
|
||||||
"dns": "Domain Name Server",
|
|
||||||
"name": "Name",
|
|
||||||
"timeout": "Time Out",
|
|
||||||
"not.added.yet.domain": "Domain not added yet.",
|
|
||||||
"not.added.yet.dns": "Nameserver not added yet.",
|
|
||||||
"create.time": "CreateTime",
|
|
||||||
"update.time": "UpdateTime",
|
|
||||||
"created.in": "Created in",
|
|
||||||
"updated.in": "Updated in",
|
|
||||||
"apply.setting": "Apply Settings",
|
|
||||||
"deploy.setting": "Deploy Settings",
|
|
||||||
"operation.succeed": "Operation Successful",
|
|
||||||
"save.succeed": "Save Successful",
|
|
||||||
"save.failed": "Save Failed",
|
|
||||||
"update.succeed": "Update Successful",
|
|
||||||
"update.failed": "Update Failed",
|
|
||||||
"delete.failed": "Delete Failed",
|
|
||||||
"ding.talk": "Ding Talk",
|
|
||||||
"telegram": "Telegram",
|
|
||||||
"webhook": "Webhook",
|
|
||||||
"local.deployment": "Local Deployment",
|
|
||||||
"tencent": "Tencent",
|
|
||||||
"tencent.cdn": "Tencent-CDN",
|
|
||||||
"aliyun": "Alibaba Cloud",
|
|
||||||
"aliyun.cdn": "Alibaba Cloud-CDN",
|
|
||||||
"aliyun.oss": "Alibaba Cloud-OSS",
|
|
||||||
"aliyun.dcdn": "Alibaba Cloud-DCDN",
|
|
||||||
"huaweicloud": "Huawei Cloud",
|
|
||||||
"qiniu": "Qiniu",
|
|
||||||
"qiniu.cdn": "Qiniu-CDN",
|
|
||||||
"cloudflare": "Cloudflare",
|
|
||||||
"namesilo": "Namesilo",
|
|
||||||
"go.daddy": "GoDaddy",
|
|
||||||
"ssh": "SSH Deployment",
|
|
||||||
"zod.rule.string.max": "Please enter no more than {{max}} characters",
|
|
||||||
"zod.rule.url": "Please enter a valid URL",
|
|
||||||
"zod.rule.ssh.host": "Please enter the correct domain name or IP",
|
|
||||||
"login.submit": "Log In",
|
|
||||||
"login.username.no.empty.message": "Please enter a valid email address",
|
|
||||||
"login.password.length.message": "Password should be at least 10 characters",
|
|
||||||
"menu.auth.management": "Authorization Management",
|
|
||||||
"theme.light": "Light",
|
|
||||||
"theme.dark": "Dark",
|
|
||||||
"theme.system": "System",
|
|
||||||
"dashboard": "Dashboard",
|
|
||||||
"dashboard.all": "All",
|
|
||||||
"dashboard.near.expired": "About to Expire",
|
|
||||||
"dashboard.enabled": "Enabled",
|
|
||||||
"dashboard.not.enabled": "Not Enabled",
|
|
||||||
"dashboard.unit": "Unit",
|
|
||||||
"deployment.log.name": "Deployment History",
|
|
||||||
"deployment.log.empty": "You have not created any deployments yet, please add a domain to start deployment!",
|
|
||||||
"deployment.log.status": "Status",
|
|
||||||
"deployment.log.stage": "Stage",
|
|
||||||
"deployment.log.last.execution.time": "Last Execution Time",
|
|
||||||
"deployment.log.detail.button.text": "Log",
|
|
||||||
"deployment.log.detail": "Deployment Details",
|
|
||||||
"pagination.next": "Next",
|
|
||||||
"pagination.prev": "Previous",
|
|
||||||
"domain": "Domain",
|
|
||||||
"domain.add": "Add Domain",
|
|
||||||
"domain.edit": "Edit Domain",
|
|
||||||
"domain.delete": "Delete Domain",
|
|
||||||
"domain.not.empty.verify.message": "Please enter domain",
|
|
||||||
"domain.management.name": "Domain List",
|
|
||||||
"domain.management.start.deploy.succeed.tips": "Deployment initiated, please check the deployment log later.",
|
|
||||||
"domain.management.execution.failed": "Execution Failed",
|
|
||||||
"domain.management.execution.failed.tips": "Execution failed, please check the details in <1>Deployment History</1>.",
|
|
||||||
"domain.management.empty": "Please add a domain to start deploying the certificate.",
|
|
||||||
"domain.management.expiry.date": "Validity Period",
|
|
||||||
"domain.management.expiry.date1": "Valid for {{date}} days",
|
|
||||||
"domain.management.expiry.date2": "Expiry on {{date}}",
|
|
||||||
"domain.management.last.execution.time": "Last Execution Time",
|
|
||||||
"domain.management.last.execution.status": "Last Execution Status",
|
|
||||||
"domain.management.last.execution.stage": "Last Execution Stage",
|
|
||||||
"domain.management.enable": "Enable",
|
|
||||||
"domain.management.start.deploying": "Deploy Now",
|
|
||||||
"domain.management.forced.deployment": "Force Deployment",
|
|
||||||
"domain.management.delete.confirm": "Are you sure you want to delete this domain?",
|
|
||||||
"domain.management.edit.title": "Edit Domain",
|
|
||||||
"domain.management.edit.dns.access.label": "DNS Provider Authorization Configuration",
|
|
||||||
"domain.management.edit.dns.access.not.empty.message": "Please select DNS provider authorization configuration",
|
|
||||||
"domain.management.edit.access.label": "Provider Authorization Configuration",
|
|
||||||
"domain.management.edit.access.not.empty.message": "Please select authorization configuration",
|
|
||||||
"domain.management.edit.target.type": "Deployment Service Type",
|
|
||||||
"domain.management.edit.target.type.not.empty.message": "Please select deployment service type",
|
|
||||||
"domain.management.edit.succeed.tips": "Successful domain editing",
|
|
||||||
"domain.management.edit.target.access": "Deployment Service Provider Authorization Configuration",
|
|
||||||
"domain.management.edit.target.access.content.label": "Provider Authorization Configuration",
|
|
||||||
"domain.management.edit.target.access.not.empty.message": "Please select authorization configuration",
|
|
||||||
"domain.management.edit.target.access.verify.msg": "At least one of the deployment authorization and deployment authorization group must be selected",
|
|
||||||
"domain.management.edit.group.label": "Deployment Configuration Group (used to deploy a domain certificate to multiple ssh hosts)",
|
|
||||||
"domain.management.edit.group.not.empty.message": "Please select group",
|
|
||||||
"domain.management.edit.email.not.empty.message": "Please select email",
|
|
||||||
"domain.management.edit.email.description": "(A email is required to apply for a certificate)",
|
|
||||||
"domain.management.edit.variables.placeholder": "It can be used in SSH deployment, like:\nkey=val;\nkey2=val2;",
|
|
||||||
"domain.management.edit.dns.placeholder": "Custom domain name server, separates multiple entries with semicolon, like:\n8.8.8.8;\n8.8.4.4;",
|
|
||||||
"domain.management.add.succeed.tips": "Domain added successfully",
|
|
||||||
"domain.management.edit.timeout.placeholder": "Timeout (seconds)",
|
|
||||||
"domain.management.edit.deploy.error": "Please save applyment configuration first",
|
|
||||||
"domain.management.enabled.failed": "Enable failed",
|
|
||||||
"domain.management.enabled.without.deployments": "Failed to enable, no deployment configuration found",
|
|
||||||
"email.add": "Add Email",
|
|
||||||
"email.list": "Email List",
|
|
||||||
"email.valid.message": "Please enter a valid email address",
|
|
||||||
"email.already.exist": "Email already exists",
|
|
||||||
"email.not.empty.message": "Please enter email",
|
|
||||||
"setting.notify.menu": "Notification Push",
|
|
||||||
"setting.submit": "Confirm Changes",
|
|
||||||
"setting.account.email.valid.message": "Please enter a valid email address",
|
|
||||||
"setting.account.email.placeholder": "Please enter email",
|
|
||||||
"setting.account.email.change.succeed": "Account email altered successfully",
|
|
||||||
"setting.account.email.change.failed": "Account email alteration failed",
|
|
||||||
"setting.account.log.back.in": "Please login again",
|
|
||||||
"setting.password.length.message": "Password should be at least 10 characters",
|
|
||||||
"setting.password.not.match": "Passwords do not match",
|
|
||||||
"setting.password.change.succeed": "Password changed successfully",
|
|
||||||
"setting.password.change.failed": "Password change failed",
|
|
||||||
"setting.password.current.password": "Current Password",
|
|
||||||
"setting.password.new.password": "New Password",
|
|
||||||
"setting.password.confirm.password": "Confirm Password",
|
|
||||||
"setting.notify.template.save.succeed": "Notification template saved successfully",
|
|
||||||
"setting.notify.template.variables.tips.title": "Optional variables, COUNT: number of expiring soon",
|
|
||||||
"setting.notify.template.variables.tips.content": "Optional variables, COUNT: number of expiring soon, DOMAINS: Domain list",
|
|
||||||
"setting.notify.config.enable": "Enable",
|
|
||||||
"setting.notify.config.save.succeed": "Configuration saved successfully",
|
|
||||||
"setting.notify.config.save.failed": "Configuration save failed",
|
|
||||||
"setting.notify.config.save.failed.url.not.valid": "Invalid Url format",
|
|
||||||
"setting.ca.not.empty": "Please select a Certificate Authority",
|
|
||||||
"setting.ca.eab_kid.not.empty": "Please enter EAB_KID",
|
|
||||||
"setting.ca.eab_hmac_key.not.empty": "Please enter EAB_HMAC_KEY.",
|
|
||||||
"setting.ca.eab_kid_hmac_key.not.empty": "Please enter EAB_KID and EAB_HMAC_KEY",
|
|
||||||
"deploy.progress.check": "Check",
|
|
||||||
"deploy.progress.apply": "Apply",
|
|
||||||
"deploy.progress.deploy": "Deploy",
|
|
||||||
"access.management": "Authorization Management",
|
|
||||||
"access.add": "Add Authorization",
|
|
||||||
"access.edit": "Edit Authorization",
|
|
||||||
"access.copy": "Copy Authorization",
|
|
||||||
"access.delete.confirm": "Are you sure you want to delete the deployment authorization?",
|
|
||||||
"access.all": "All Authorizations",
|
|
||||||
"access.list": "Authorization List",
|
|
||||||
"access.type": "Provider",
|
|
||||||
"access.type.not.empty": "Please select a provider",
|
|
||||||
"access.not.empty": "Please select a cloud provider",
|
|
||||||
"access.empty": "Please add authorization to start deploying certificate.",
|
|
||||||
"access.group.management": "Authorization Group Management",
|
|
||||||
"access.group.add": "Add Authorization Group",
|
|
||||||
"access.group.not.empty": "Please select a group",
|
|
||||||
"access.group.name": "Group Name",
|
|
||||||
"access.group.name.not.empty": "Please enter group name",
|
|
||||||
"access.group.delete": "Delete Group",
|
|
||||||
"access.group.delete.confirm": "Are you sure you want to delete the deployment authorization group?",
|
|
||||||
"access.group.domain.empty": "Please add a domain to start deploying the certificate.",
|
|
||||||
"access.group.empty": "No deployment authorization configuration yet, please add after starting use.",
|
|
||||||
"access.group.total": "Totally {{total}} deployment authorization configuration",
|
|
||||||
"access.form.name.not.empty": "Please enter authorization name",
|
|
||||||
"access.form.config.field": "Configuration Type",
|
|
||||||
"access.form.access.key.id": "AccessKeyId",
|
|
||||||
"access.form.access.key.id.not.empty": "Please enter AccessKeyId",
|
|
||||||
"access.form.access.key.secret": "AccessKeySecret",
|
|
||||||
"access.form.access.key.secret.not.empty": "Please enter AccessKeySecret",
|
|
||||||
"access.form.cloud.dns.api.token": "CLOUD_DNS_API_TOKEN",
|
|
||||||
"access.form.cloud.dns.api.token.not.empty": "Please enter CLOUD_DNS_API_TOKEN",
|
|
||||||
"access.form.go.daddy.api.key": "GO_DADDY_API_KEY",
|
|
||||||
"access.form.go.daddy.api.key.not.empty": "Please enter GO_DADDY_API_KEY",
|
|
||||||
"access.form.go.daddy.api.secret": "GO_DADDY_API_SECRET",
|
|
||||||
"access.form.go.daddy.api.secret.not.empty": "Please enter GO_DADDY_API_SECRET",
|
|
||||||
"access.form.namesilo.api.key": "NAMESILO_API_KEY",
|
|
||||||
"access.form.namesilo.api.key.not.empty": "Please enter NAMESILO_API_KEY",
|
|
||||||
"access.form.secret.id": "SecretId",
|
|
||||||
"access.form.secret.id.not.empty": "Please enter SecretId",
|
|
||||||
"access.form.secret.key": "SecretKey",
|
|
||||||
"access.form.secret.key.not.empty": "Please enter SecretKey",
|
|
||||||
"access.form.access.key": "AccessKey",
|
|
||||||
"access.form.access.key.not.empty": "Please enter AccessKey",
|
|
||||||
"access.form.region": "Region",
|
|
||||||
"access.form.region.not.empty": "Please enter Region",
|
|
||||||
"access.form.webhook.url": "Webhook URL",
|
|
||||||
"access.form.webhook.url.not.empty": "Please enter Webhook URL",
|
|
||||||
"access.form.ssh.group.label": "Authorization Configuration Group (used to deploy a single domain certificate to multiple SSH hosts)",
|
|
||||||
"access.form.ssh.host": "Server Host",
|
|
||||||
"access.form.ssh.host.not.empty": "Please enter Host",
|
|
||||||
"access.form.ssh.port": "SSH Port",
|
|
||||||
"access.form.ssh.port.not.empty": "Please enter Port",
|
|
||||||
"access.form.ssh.key": "Key (Log in using certificate)",
|
|
||||||
"access.form.ssh.key.not.empty": "Please enter Key",
|
|
||||||
"access.form.ssh.key.file.not.empty": "Please select file",
|
|
||||||
"access.form.ssh.cert.path": "Certificate Save Path",
|
|
||||||
"access.form.ssh.cert.path.not.empty": "Please enter certificate save path",
|
|
||||||
"access.form.ssh.key.path": "Private Key Save Path",
|
|
||||||
"access.form.ssh.key.path.not.empty": "Please enter private key save path",
|
|
||||||
"access.form.ssh.pre.command": "Pre-deployment Command",
|
|
||||||
"access.form.ssh.pre.command.not.empty": "Command to be executed before deploying the certificate",
|
|
||||||
"access.form.ssh.command": "Command",
|
|
||||||
"access.form.ssh.command.not.empty": "Please enter command",
|
|
||||||
"access.form.ding.access.token.placeholder": "Signature for signed addition",
|
|
||||||
|
|
||||||
"variable": "Variable",
|
|
||||||
"variable.name": "Name",
|
|
||||||
"variable.value": "Value",
|
|
||||||
"variable.not.added": "Variable not added yet",
|
|
||||||
"variable.name.required": "Variable name cannot be empty",
|
|
||||||
"variable.value.required": "Variable value cannot be empty",
|
|
||||||
"variable.name.placeholder": "Variable name",
|
|
||||||
"variable.value.placeholder": "Variable value",
|
|
||||||
|
|
||||||
"deployment": "Deployment",
|
|
||||||
"deployment.not.added": "Deployment not added yet",
|
|
||||||
"deployment.access.type": "Access Type",
|
|
||||||
"deployment.access.config": "Access Configuration",
|
|
||||||
"deployment.access.cdn.deploy.to.domain": "Deploy to domain",
|
|
||||||
|
|
||||||
"deployment.access.oss.bucket": "Bucket",
|
|
||||||
"deployment.access.oss.bucket.not.empty": "Please enter Bucket",
|
|
||||||
"deployment.access.oss.endpoint": "Endpoint"
|
|
||||||
}
|
|
17
ui/src/i18n/locales/en/index.ts
Normal file
17
ui/src/i18n/locales/en/index.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import nlsCommon from "./nls.common.json";
|
||||||
|
import nlsLogin from "./nls.login.json";
|
||||||
|
import nlsDashboard from "./nls.dashboard.json";
|
||||||
|
import nlsSettings from "./nls.settings.json";
|
||||||
|
import nlsDomain from "./nls.domain.json";
|
||||||
|
import nlsAccess from "./nls.access.json";
|
||||||
|
import nlsHistory from "./nls.history.json";
|
||||||
|
|
||||||
|
export default Object.freeze({
|
||||||
|
...nlsCommon,
|
||||||
|
...nlsLogin,
|
||||||
|
...nlsDashboard,
|
||||||
|
...nlsSettings,
|
||||||
|
...nlsDomain,
|
||||||
|
...nlsAccess,
|
||||||
|
...nlsHistory,
|
||||||
|
});
|
79
ui/src/i18n/locales/en/nls.access.json
Normal file
79
ui/src/i18n/locales/en/nls.access.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"access.page.title": "Authorization Management",
|
||||||
|
|
||||||
|
"access.authorization.tab": "Authorization",
|
||||||
|
"access.authorization.nodata": "Please add authorization to start deploying certificate.",
|
||||||
|
|
||||||
|
"access.authorization.add": "Add Authorization",
|
||||||
|
"access.authorization.edit": "Edit Authorization",
|
||||||
|
"access.authorization.copy": "Copy Authorization",
|
||||||
|
"access.authorization.delete": "Delete Authorization",
|
||||||
|
"access.authorization.delete.confirm": "Are you sure you want to delete the deployment authorization?",
|
||||||
|
|
||||||
|
"access.authorization.form.type.label": "Provider",
|
||||||
|
"access.authorization.form.type.placeholder": "Please select a provider",
|
||||||
|
"access.authorization.form.type.list": "Authorization List",
|
||||||
|
"access.authorization.form.name.label": "Name",
|
||||||
|
"access.authorization.form.name.placeholder": "Please enter authorization name",
|
||||||
|
"access.authorization.form.config.label": "Configuration Type",
|
||||||
|
"access.authorization.form.region.label": "Region",
|
||||||
|
"access.authorization.form.region.placeholder": "Please enter Region",
|
||||||
|
"access.authorization.form.access_key_id.label": "AccessKeyId",
|
||||||
|
"access.authorization.form.access_key_id.placeholder": "Please enter AccessKeyId",
|
||||||
|
"access.authorization.form.access_key_secret.label": "AccessKeySecret",
|
||||||
|
"access.authorization.form.access_key_secret..placeholder": "Please enter AccessKeySecret",
|
||||||
|
"access.authorization.form.access_key.label": "AccessKey",
|
||||||
|
"access.authorization.form.access_key.placeholder": "Please enter AccessKey",
|
||||||
|
"access.authorization.form.secret_id.label": "SecretId",
|
||||||
|
"access.authorization.form.secret_id.placeholder": "Please enter SecretId",
|
||||||
|
"access.authorization.form.secret_key.label": "SecretKey",
|
||||||
|
"access.authorization.form.secret_key.placeholder": "Please enter SecretKey",
|
||||||
|
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
||||||
|
"access.authorization.form.cloud_dns_api_token.placeholder": "Please enter CLOUD_DNS_API_TOKEN",
|
||||||
|
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
||||||
|
"access.authorization.form.godaddy_api_key.placeholder": "Please enter GO_DADDY_API_KEY",
|
||||||
|
"access.authorization.form.godaddy_api_secret.label": "GO_DADDY_API_SECRET",
|
||||||
|
"access.authorization.form.godaddy_api_secret.placeholder": "Please enter GO_DADDY_API_SECRET",
|
||||||
|
"access.authorization.form.namesilo_api_key.label": "NAMESILO_API_KEY",
|
||||||
|
"access.authorization.form.namesilo_api_key.placeholder": "Please enter NAMESILO_API_KEY",
|
||||||
|
"access.authorization.form.username.label": "Username",
|
||||||
|
"access.authorization.form.username.placeholder": "Please enter username",
|
||||||
|
"access.authorization.form.password.label": "Password",
|
||||||
|
"access.authorization.form.password.placeholder": "Please enter password",
|
||||||
|
"access.authorization.form.access_group.placeholder": "Please select a group",
|
||||||
|
"access.authorization.form.ssh_group.label": "Authorization Configuration Group (used to deploy a single domain certificate to multiple SSH hosts)",
|
||||||
|
"access.authorization.form.ssh_host.label": "Server Host",
|
||||||
|
"access.authorization.form.ssh_host.placeholder": "Please enter Host",
|
||||||
|
"access.authorization.form.ssh_port.label": "SSH Port",
|
||||||
|
"access.authorization.form.ssh_port.placeholder": "Please enter Port",
|
||||||
|
"access.authorization.form.ssh_key.label": "Key (Log in using private key)",
|
||||||
|
"access.authorization.form.ssh_key.placeholder": "Please enter Key",
|
||||||
|
"access.authorization.form.ssh_key_file.placeholder": "Please select file",
|
||||||
|
"access.authorization.form.ssh_key_path.label": "Private Key Save Path",
|
||||||
|
"access.authorization.form.ssh_key_path.placeholder": "Please enter private key save path",
|
||||||
|
"access.authorization.form.ssh_cert_path.label": "Certificate Save Path",
|
||||||
|
"access.authorization.form.ssh_cert_path.placeholder": "Please enter certificate save path",
|
||||||
|
"access.authorization.form.ssh_pre_command.label": "Pre-deployment Command",
|
||||||
|
"access.authorization.form.ssh_pre_command.placeholder": "Command to be executed before deploying the certificate",
|
||||||
|
"access.authorization.form.ssh_command.label": "Command",
|
||||||
|
"access.authorization.form.ssh_command.placeholder": "Please enter command",
|
||||||
|
"access.authorization.form.webhook_url.label": "Webhook URL",
|
||||||
|
"access.authorization.form.webhook_url.placeholder": "Please enter Webhook URL",
|
||||||
|
|
||||||
|
"access.group.tab": "Authorization Group",
|
||||||
|
|
||||||
|
"access.group.nodata": "No deployment authorization configuration yet, please add after starting use.",
|
||||||
|
"access.group.total": "Totally {{total}} deployment authorization configuration",
|
||||||
|
|
||||||
|
"access.group.add": "Add Group",
|
||||||
|
"access.group.delete": "Delete Group",
|
||||||
|
"access.group.delete.confirm": "Are you sure you want to delete the deployment authorization group?",
|
||||||
|
|
||||||
|
"access.group.form.name.label": "Group Name",
|
||||||
|
"access.group.form.name.errmsg.empty": "Please enter group name",
|
||||||
|
|
||||||
|
"access.group.domains": "All Authorizations",
|
||||||
|
"access.group.domains.nodata": "Please add a domain to start deploying the certificate.",
|
||||||
|
|
||||||
|
"access.common.type.errmsg.empty": "Please select a provider"
|
||||||
|
}
|
72
ui/src/i18n/locales/en/nls.common.json
Normal file
72
ui/src/i18n/locales/en/nls.common.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"common.save": "Save",
|
||||||
|
"common.save.succeeded.message": "Save Successful",
|
||||||
|
"common.save.failed.message": "Save Failed",
|
||||||
|
"common.add": "Add",
|
||||||
|
"common.edit": "Edit",
|
||||||
|
"common.copy": "Copy",
|
||||||
|
"common.download": "Download",
|
||||||
|
"common.delete": "Delete",
|
||||||
|
"common.delete.succeeded.message": "Delete Successful",
|
||||||
|
"common.delete.failed.message": "Delete Failed",
|
||||||
|
"common.next": "Next",
|
||||||
|
"common.confirm": "Confirm",
|
||||||
|
"common.cancel": "Cancel",
|
||||||
|
"common.submit": "Submit",
|
||||||
|
"common.update": "Update",
|
||||||
|
"common.update.succeeded.message": "Update Successful",
|
||||||
|
"common.update.failed.message": "Update Failed",
|
||||||
|
|
||||||
|
"common.text.domain": "Domain",
|
||||||
|
"common.text.domain.empty": "No Domain",
|
||||||
|
"common.text.ip": "IP Address",
|
||||||
|
"common.text.ip.empty": "No IP address",
|
||||||
|
"common.text.dns": "Domain Name Server",
|
||||||
|
"common.text.dns.empty": "No DNS",
|
||||||
|
"common.text.ca": "Certificate Authority",
|
||||||
|
"common.text.provider": "Provider",
|
||||||
|
"common.text.name": "Name",
|
||||||
|
"common.text.created_at": "Created At",
|
||||||
|
"common.text.updated_at": "Updated At",
|
||||||
|
"common.text.operations": "Operations",
|
||||||
|
"common.text.nodata": "No data available",
|
||||||
|
|
||||||
|
"common.menu.settings": "Settings",
|
||||||
|
"common.menu.logout": "Logout",
|
||||||
|
"common.menu.document": "Document",
|
||||||
|
|
||||||
|
"common.pagination.next": "Next",
|
||||||
|
"common.pagination.prev": "Previous",
|
||||||
|
"common.pagination.more": "More pages",
|
||||||
|
|
||||||
|
"common.theme.light": "Light",
|
||||||
|
"common.theme.dark": "Dark",
|
||||||
|
"common.theme.system": "System",
|
||||||
|
|
||||||
|
"common.errmsg.string_max": "Please enter no more than {{max}} characters",
|
||||||
|
"common.errmsg.email_invalid": "Please enter a valid email address",
|
||||||
|
"common.errmsg.email_empty": "Please enter email",
|
||||||
|
"common.errmsg.email_duplicate": "Email already exists",
|
||||||
|
"common.errmsg.domain_invalid": "Please enter domain",
|
||||||
|
"common.errmsg.host_invalid": "Please enter the correct domain name or IP",
|
||||||
|
"common.errmsg.ip_invalid": "Please enter IP",
|
||||||
|
"common.errmsg.url_invalid": "Please enter a valid URL",
|
||||||
|
|
||||||
|
"common.provider.aliyun": "Alibaba Cloud",
|
||||||
|
"common.provider.aliyun.cdn": "Alibaba Cloud-CDN",
|
||||||
|
"common.provider.aliyun.oss": "Alibaba Cloud-OSS",
|
||||||
|
"common.provider.aliyun.dcdn": "Alibaba Cloud-DCDN",
|
||||||
|
"common.provider.tencent": "Tencent",
|
||||||
|
"common.provider.tencent.cdn": "Tencent-CDN",
|
||||||
|
"common.provider.huaweicloud": "Huawei Cloud",
|
||||||
|
"common.provider.qiniu": "Qiniu",
|
||||||
|
"common.provider.qiniu.cdn": "Qiniu-CDN",
|
||||||
|
"common.provider.cloudflare": "Cloudflare",
|
||||||
|
"common.provider.namesilo": "Namesilo",
|
||||||
|
"common.provider.godaddy": "GoDaddy",
|
||||||
|
"common.provider.local": "Local Deployment",
|
||||||
|
"common.provider.ssh": "SSH Deployment",
|
||||||
|
"common.provider.webhook": "Webhook",
|
||||||
|
"common.provider.dingtalk": "DingTalk",
|
||||||
|
"common.provider.telegram": "Telegram"
|
||||||
|
}
|
11
ui/src/i18n/locales/en/nls.dashboard.json
Normal file
11
ui/src/i18n/locales/en/nls.dashboard.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"dashboard.page.title": "Dashboard",
|
||||||
|
|
||||||
|
"dashboard.statistics.all": "All",
|
||||||
|
"dashboard.statistics.near_expired": "About to Expire",
|
||||||
|
"dashboard.statistics.enabled": "Enabled",
|
||||||
|
"dashboard.statistics.disabled": "Not Enabled",
|
||||||
|
"dashboard.statistics.unit": "",
|
||||||
|
|
||||||
|
"dashboard.history": "Deployment History"
|
||||||
|
}
|
65
ui/src/i18n/locales/en/nls.domain.json
Normal file
65
ui/src/i18n/locales/en/nls.domain.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"domain.page.title": "Domain List",
|
||||||
|
|
||||||
|
"domain.nodata": "Please add a domain to start deploying the certificate.",
|
||||||
|
|
||||||
|
"domain.add": "Add Domain",
|
||||||
|
"domain.edit": "Edit Domain",
|
||||||
|
"domain.delete": "Delete Domain",
|
||||||
|
"domain.delete.confirm": "Are you sure you want to delete this domain?",
|
||||||
|
"domain.history": "Deployment History",
|
||||||
|
"domain.deploy": "Deploy Now",
|
||||||
|
"domain.deploy.started.message": "Deploy Started",
|
||||||
|
"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.props.expiry": "Validity Period",
|
||||||
|
"domain.props.expiry.date1": "Valid for {{date}} days",
|
||||||
|
"domain.props.expiry.date2": "Expiry on {{date}}",
|
||||||
|
"domain.props.last_execution_status": "Last Execution Status",
|
||||||
|
"domain.props.last_execution_stage": "Last Execution Stage",
|
||||||
|
"domain.props.last_execution_time": "Last Execution Time",
|
||||||
|
"domain.props.enable": "Enable",
|
||||||
|
"domain.props.enable.enabled": "Enable",
|
||||||
|
"domain.props.enable.disabled": "Disable",
|
||||||
|
|
||||||
|
"domain.application.tab": "Apply Settings",
|
||||||
|
"domain.application.form.domain.added.message": "Domain added successfully",
|
||||||
|
"domain.application.form.domain.changed.message": "Domain updated successfully",
|
||||||
|
"domain.application.form.email.label": "Email",
|
||||||
|
"domain.application.form.email.tips": "(A email is required to apply for a certificate)",
|
||||||
|
"domain.application.form.email.add": "Add Email",
|
||||||
|
"domain.application.form.email.list": "Email List",
|
||||||
|
"domain.application.form.email.errmsg.empty": "Please select email",
|
||||||
|
"domain.application.form.access.label": "DNS Provider Authorization Configuration",
|
||||||
|
"domain.application.form.access.placeholder": "Please select DNS provider authorization configuration",
|
||||||
|
"domain.application.form.access.errmsg.empty": "Please select DNS provider authorization configuration",
|
||||||
|
"domain.application.form.access.list": "Provider Authorization Configurations",
|
||||||
|
"domain.application.form.timeout.label": "Timeout",
|
||||||
|
"domain.application.form.timeoue.placeholder": "Timeout (seconds)",
|
||||||
|
"domain.application.unsaved.message": "Please save applyment configuration first",
|
||||||
|
|
||||||
|
"domain.deployment.tab": "Deploy Settings",
|
||||||
|
"domain.deployment.nodata": "Deployment not added yet",
|
||||||
|
"domain.deployment.form.type.label": "Deploy Method",
|
||||||
|
"domain.deployment.form.type.placeholder": "Please select deploy method",
|
||||||
|
"domain.deployment.form.type.list": "Deploy Method List",
|
||||||
|
"domain.deployment.form.access.label": "Access Configuration",
|
||||||
|
"domain.deployment.form.access.placeholder": "Please select provider authorization configuration",
|
||||||
|
"domain.deployment.form.access.list": "Provider Authorization Configurations",
|
||||||
|
"domain.deployment.form.cdn_domain.label": "Deploy to domain",
|
||||||
|
"domain.deployment.form.cdn_domain.placeholder": "Please enter CDN domain",
|
||||||
|
"domain.deployment.form.oss_endpoint.label": "Endpoint",
|
||||||
|
"domain.deployment.form.oss_bucket": "Bucket",
|
||||||
|
"domain.deployment.form.oss_bucket.placeholder": "Please enter Bucket",
|
||||||
|
"domain.deployment.form.variables.label": "Variable",
|
||||||
|
"domain.deployment.form.variables.key": "Name",
|
||||||
|
"domain.deployment.form.variables.value": "Value",
|
||||||
|
"domain.deployment.form.variables.empty": "Variable not added yet",
|
||||||
|
"domain.deployment.form.variables.key.required": "Variable name cannot be empty",
|
||||||
|
"domain.deployment.form.variables.value.required": "Variable value cannot be empty",
|
||||||
|
"domain.deployment.form.variables.key.placeholder": "Variable name",
|
||||||
|
"domain.deployment.form.variables.value.placeholder": "Variable value"
|
||||||
|
}
|
16
ui/src/i18n/locales/en/nls.history.json
Normal file
16
ui/src/i18n/locales/en/nls.history.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"history.page.title": "Deployment",
|
||||||
|
|
||||||
|
"history.nodata": "You have not created any deployments yet, please add a domain to start deployment!",
|
||||||
|
|
||||||
|
"history.props.domain": "Domain",
|
||||||
|
"history.props.status": "Status",
|
||||||
|
"history.props.stage": "Stage",
|
||||||
|
"history.props.last_execution_time": "Last Execution Time",
|
||||||
|
|
||||||
|
"history.props.stage.progress.check": "Check",
|
||||||
|
"history.props.stage.progress.apply": "Apply",
|
||||||
|
"history.props.stage.progress.deploy": "Deploy",
|
||||||
|
|
||||||
|
"history.log": "Log"
|
||||||
|
}
|
9
ui/src/i18n/locales/en/nls.login.json
Normal file
9
ui/src/i18n/locales/en/nls.login.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"login.username.label": "Username",
|
||||||
|
"login.username.placeholder": "Username/Email",
|
||||||
|
"login.username.errmsg.invalid": "Please enter a valid email address",
|
||||||
|
"login.password.label": "Password",
|
||||||
|
"login.password.placeholder": "Password",
|
||||||
|
"login.password.errmsg.invalid": "Password should be at least 10 characters",
|
||||||
|
"login.submit": "Log In"
|
||||||
|
}
|
41
ui/src/i18n/locales/en/nls.settings.json
Normal file
41
ui/src/i18n/locales/en/nls.settings.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"settings.page.title": "Settings",
|
||||||
|
|
||||||
|
"settings.account.relogin.message": "Please login again",
|
||||||
|
|
||||||
|
"settings.account.tab": "Account",
|
||||||
|
"settings.account.email.label": "Email",
|
||||||
|
"settings.account.email.placeholder": "Please enter email",
|
||||||
|
"settings.account.email.errmsg.invalid": "Please enter a valid email address",
|
||||||
|
"settings.account.email.changed.message": "Account email altered successfully",
|
||||||
|
"settings.account.email.failed.message": "Account email alteration failed",
|
||||||
|
|
||||||
|
"settings.password.tab": "Password",
|
||||||
|
"settings.password.current_password.label": "Current Password",
|
||||||
|
"settings.password.current_password.placeholder": "Please enter the current password",
|
||||||
|
"settings.password.new_password.label": "New Password",
|
||||||
|
"settings.password.new_password.placeholder": "Please enter the new password",
|
||||||
|
"settings.password.confirm_password.label": "Confirm Password",
|
||||||
|
"settings.password.confirm_password.placeholder": "Please enter the new password again",
|
||||||
|
"settings.password.password.errmsg.length": "Password should be at least 10 characters",
|
||||||
|
"settings.password.password.errmsg.not_matched": "Passwords do not match",
|
||||||
|
"settings.password.changed.message": "Password changed successfully",
|
||||||
|
"settings.password.failed.message": "Password change failed",
|
||||||
|
|
||||||
|
"settings.notification.tab": "Notification",
|
||||||
|
"settings.notification.template.label": "Template",
|
||||||
|
"settings.notification.template.saved.message": "Notification template saved successfully",
|
||||||
|
"settings.notification.template.variables.tips.title": "Optional variables ({COUNT}: number of expiring soon)",
|
||||||
|
"settings.notification.template.variables.tips.content": "Optional variables ({COUNT}: number of expiring soon. {DOMAINS}: Domain list)",
|
||||||
|
"settings.notification.config.enable": "Enable",
|
||||||
|
"settings.notification.config.saved.message": "Configuration saved successfully",
|
||||||
|
"settings.notification.config.failed.message": "Configuration save failed",
|
||||||
|
"settings.notification.dingtalk.secret.placeholder": "Signature for signed addition",
|
||||||
|
"settings.notification.url.errmsg.invalid": "Invalid Url format",
|
||||||
|
|
||||||
|
"settings.ca.tab": "Certificate Authority",
|
||||||
|
"settings.ca.provider.errmsg.empty": "Please select a Certificate Authority",
|
||||||
|
"settings.ca.eab_kid.errmsg.empty": "Please enter EAB_KID",
|
||||||
|
"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"
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
import { Resource } from 'i18next'
|
import { Resource } from "i18next";
|
||||||
|
|
||||||
import zh from './zh.json'
|
import zh from "./zh";
|
||||||
import en from './en.json'
|
import en from "./en";
|
||||||
|
|
||||||
const resources: Resource = {
|
const resources: Resource = {
|
||||||
zh: {
|
zh: {
|
||||||
name: '简体中文',
|
name: "简体中文",
|
||||||
translation: zh
|
translation: zh,
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
name: 'English',
|
name: "English",
|
||||||
translation: en
|
translation: en,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export default resources;
|
export default resources;
|
@ -1,247 +0,0 @@
|
|||||||
{
|
|
||||||
"ca": "证书颁发机构",
|
|
||||||
"username": "用户名",
|
|
||||||
"username.not.empty": "请输入用户名",
|
|
||||||
"password": "密码",
|
|
||||||
"password.not.empty": "请输入密码",
|
|
||||||
"ip.not.empty.verify.message": "请输入 IP",
|
|
||||||
"email": "邮箱",
|
|
||||||
"logout": "退出登录",
|
|
||||||
"setting": "设置",
|
|
||||||
"account": "账户",
|
|
||||||
"template": "模版",
|
|
||||||
"save": "保存",
|
|
||||||
"next": "下一步",
|
|
||||||
"no.data": "暂无数据",
|
|
||||||
"status": "状态",
|
|
||||||
"operation": "操作",
|
|
||||||
"enable": "启用",
|
|
||||||
"disable": "禁用",
|
|
||||||
"deploy": "部署",
|
|
||||||
"download": "下载",
|
|
||||||
"delete": "删除",
|
|
||||||
"cancel": "取消",
|
|
||||||
"confirm": "确认",
|
|
||||||
"edit": "编辑",
|
|
||||||
"copy": "复制",
|
|
||||||
"succeed": "成功",
|
|
||||||
"add": "新增",
|
|
||||||
"document": "文档",
|
|
||||||
"variables": "变量",
|
|
||||||
"dns": "域名服务器",
|
|
||||||
"name": "名称",
|
|
||||||
"timeout": "超时时间",
|
|
||||||
"not.added.yet.domain": "域名未添加",
|
|
||||||
"not.added.yet.dns": "域名服务器暂未添加",
|
|
||||||
"create.time": "创建时间",
|
|
||||||
"update.time": "更新时间",
|
|
||||||
"created.in": "创建于",
|
|
||||||
"updated.in": "更新于",
|
|
||||||
"apply.setting": "申请设置",
|
|
||||||
"deploy.setting": "部署设置",
|
|
||||||
"operation.succeed": "操作成功",
|
|
||||||
"save.succeed": "保存成功",
|
|
||||||
"save.failed": "保存失败",
|
|
||||||
"update.succeed": "修改成功",
|
|
||||||
"update.failed": "修改失败",
|
|
||||||
"delete.failed": "删除失败",
|
|
||||||
"ding.talk": "钉钉",
|
|
||||||
"telegram": "Telegram",
|
|
||||||
"webhook": "Webhook",
|
|
||||||
"local.deployment": "本地部署",
|
|
||||||
"tencent": "腾讯云",
|
|
||||||
"tencent.cdn": "腾讯云-CDN",
|
|
||||||
"aliyun": "阿里云",
|
|
||||||
"aliyun.cdn": "阿里云-CDN",
|
|
||||||
"aliyun.oss": "阿里云-OSS",
|
|
||||||
"aliyun.dcdn": "阿里云-DCDN",
|
|
||||||
"huaweicloud": "华为云",
|
|
||||||
"qiniu": "七牛云",
|
|
||||||
"qiniu.cdn": "七牛云-CDN",
|
|
||||||
"cloudflare": "Cloudflare",
|
|
||||||
"namesilo": "Namesilo",
|
|
||||||
"go.daddy": "GoDaddy",
|
|
||||||
"ssh": "SSH 部署",
|
|
||||||
"zod.rule.string.max": "请输入不超过 {{max}} 个字符",
|
|
||||||
"zod.rule.url": "请输入有效的 url 地址",
|
|
||||||
"zod.rule.ssh.host": "请输入正确的域名或IP",
|
|
||||||
"login.submit": "登录",
|
|
||||||
"login.username.no.empty.message": "请输入正确的邮箱地址",
|
|
||||||
"login.password.length.message": "密码至少10个字符",
|
|
||||||
"menu.auth.management": "授权管理",
|
|
||||||
"theme.light": "浅色",
|
|
||||||
"theme.dark": "暗黑",
|
|
||||||
"theme.system": "系统",
|
|
||||||
"dashboard": "控制面板",
|
|
||||||
"dashboard.all": "所有",
|
|
||||||
"dashboard.near.expired": "即将过期",
|
|
||||||
"dashboard.enabled": "启用中",
|
|
||||||
"dashboard.not.enabled": "未启用",
|
|
||||||
"dashboard.unit": "个",
|
|
||||||
"deployment.log.name": "部署历史",
|
|
||||||
"deployment.log.empty": "你暂未创建任何部署,请先添加域名进行部署吧!",
|
|
||||||
"deployment.log.status": "状态",
|
|
||||||
"deployment.log.stage": "阶段",
|
|
||||||
"deployment.log.last.execution.time": "最近执行时间",
|
|
||||||
"deployment.log.detail.button.text": "日志",
|
|
||||||
"deployment.log.detail": "部署详情",
|
|
||||||
"pagination.next": "下一页",
|
|
||||||
"pagination.prev": "上一页",
|
|
||||||
"domain": "域名",
|
|
||||||
"domain.add": "新增域名",
|
|
||||||
"domain.edit": "编辑域名",
|
|
||||||
"domain.delete": "删除域名",
|
|
||||||
"domain.not.empty.verify.message": "请输入域名",
|
|
||||||
"domain.management.name": "域名列表",
|
|
||||||
"domain.management.start.deploy.succeed.tips": "已发起部署,请稍后查看部署日志。",
|
|
||||||
"domain.management.execution.failed": "执行失败",
|
|
||||||
"domain.management.execution.failed.tips": "执行失败,请在 <1>部署历史</1> 查看详情。",
|
|
||||||
"domain.management.empty": "请添加域名开始部署证书吧。",
|
|
||||||
"domain.management.expiry.date": "有效期限",
|
|
||||||
"domain.management.expiry.date1": "有效期 {{date}} 天",
|
|
||||||
"domain.management.expiry.date2": "{{date}} 到期",
|
|
||||||
"domain.management.last.execution.time": "最近执行时间",
|
|
||||||
"domain.management.last.execution.status": "最近执行状态",
|
|
||||||
"domain.management.last.execution.stage": "最近执行阶段",
|
|
||||||
"domain.management.enable": "是否启用",
|
|
||||||
"domain.management.start.deploying": "立即部署",
|
|
||||||
"domain.management.forced.deployment": "强行部署",
|
|
||||||
"domain.management.delete.confirm": "确定要删除域名吗?",
|
|
||||||
"domain.management.edit.title": "编辑域名",
|
|
||||||
"domain.management.edit.dns.access.label": "DNS 服务商授权配置",
|
|
||||||
"domain.management.edit.dns.access.not.empty.message": "请选择DNS服务商授权配置",
|
|
||||||
"domain.management.edit.access.label": "服务商授权配置",
|
|
||||||
"domain.management.edit.access.not.empty.message": "请选择授权配置",
|
|
||||||
"domain.management.edit.target.type": "部署服务类型",
|
|
||||||
"domain.management.edit.target.type.not.empty.message": "请选择部署服务类型",
|
|
||||||
"domain.management.edit.succeed.tips": "域名编辑成功",
|
|
||||||
"domain.management.edit.target.access": "部署服务商授权配置",
|
|
||||||
"domain.management.edit.target.access.content.label": "服务商授权配置",
|
|
||||||
"domain.management.edit.target.access.not.empty.message": "请选择授权配置",
|
|
||||||
"domain.management.edit.target.access.verify.msg": "部署授权和部署授权组至少选一个",
|
|
||||||
"domain.management.edit.group.label": "部署配置组(用于将一个域名证书部署到多个 ssh 主机)",
|
|
||||||
"domain.management.edit.group.not.empty.message": "请选择分组",
|
|
||||||
"domain.management.edit.email.not.empty.message": "请选择邮箱",
|
|
||||||
"domain.management.edit.email.description": "(申请证书需要提供邮箱)",
|
|
||||||
"domain.management.edit.variables.placeholder": "可在SSH部署中使用,形如:\nkey=val;\nkey2=val2;",
|
|
||||||
"domain.management.edit.dns.placeholder": "自定义域名服务器,多个用分号隔开,如:\n8.8.8.8;\n8.8.4.4;",
|
|
||||||
"domain.management.add.succeed.tips": "域名添加成功",
|
|
||||||
"domain.management.edit.timeout.placeholder": "超时时间(单位:秒)",
|
|
||||||
"domain.management.edit.deploy.error": "请先保存申请配置",
|
|
||||||
"domain.management.enabled.failed": "启用失败",
|
|
||||||
"domain.management.enabled.without.deployments": "启用失败,请先设置部署配置",
|
|
||||||
"email.add": "添加邮箱",
|
|
||||||
"email.list": "邮箱列表",
|
|
||||||
"email.valid.message": "请输入正确的邮箱地址",
|
|
||||||
"email.already.exist": "邮箱已存在",
|
|
||||||
"email.not.empty.message": "请输入邮箱",
|
|
||||||
"setting.notify.menu": "消息推送",
|
|
||||||
"setting.submit": "确认修改",
|
|
||||||
"setting.account.email.valid.message": "请输入正确的邮箱地址",
|
|
||||||
"setting.account.email.placeholder": "请输入邮箱",
|
|
||||||
"setting.account.email.change.succeed": "修改账户邮箱成功",
|
|
||||||
"setting.account.email.change.failed": "修改账户邮箱失败",
|
|
||||||
"setting.account.log.back.in": "请重新登录",
|
|
||||||
"setting.password.length.message": "密码至少10个字符",
|
|
||||||
"setting.password.not.match": "两次密码不一致",
|
|
||||||
"setting.password.change.succeed": "修改密码成功",
|
|
||||||
"setting.password.change.failed": "修改密码失败",
|
|
||||||
"setting.password.current.password": "当前密码",
|
|
||||||
"setting.password.new.password": "新密码",
|
|
||||||
"setting.password.confirm.password": "确认密码",
|
|
||||||
"setting.notify.template.save.succeed": "通知模板保存成功",
|
|
||||||
"setting.notify.template.variables.tips.title": "可选的变量, COUNT:即将过期张数",
|
|
||||||
"setting.notify.template.variables.tips.content": "可选的变量, COUNT:即将过期张数,DOMAINS:域名列表",
|
|
||||||
"setting.notify.config.enable": "是否启用",
|
|
||||||
"setting.notify.config.save.succeed": "配置保存成功",
|
|
||||||
"setting.notify.config.save.failed": "配置保存失败",
|
|
||||||
"setting.notify.config.save.failed.url.not.valid": "Url格式不正确",
|
|
||||||
"setting.ca.not.empty": "请选择证书分发机构",
|
|
||||||
"setting.ca.eab_kid.not.empty": "请输入EAB_KID",
|
|
||||||
"setting.ca.eab_hmac_key.not.empty": "请输入EAB_HMAC_KEY",
|
|
||||||
"setting.ca.eab_kid_hmac_key.not.empty": "请输入EAB_KID和EAB_HMAC_KEY",
|
|
||||||
"deploy.progress.check": "检查",
|
|
||||||
"deploy.progress.apply": "获取",
|
|
||||||
"deploy.progress.deploy": "部署",
|
|
||||||
"access.management": "授权管理",
|
|
||||||
"access.add": "添加授权",
|
|
||||||
"access.edit": "编辑授权",
|
|
||||||
"access.copy": "复制授权",
|
|
||||||
"access.delete.confirm": "确定要删除授权吗?",
|
|
||||||
"access.all": "所有授权",
|
|
||||||
"access.list": "授权列表",
|
|
||||||
"access.type": "服务商",
|
|
||||||
"access.type.not.empty": "请选择服务商",
|
|
||||||
"access.not.empty": "请选择云服务商",
|
|
||||||
"access.empty": "请添加授权开始部署证书吧。",
|
|
||||||
"access.group.management": "授权组管理",
|
|
||||||
"access.group.add": "添加授权组",
|
|
||||||
"access.group.not.empty": "请选择分组",
|
|
||||||
"access.group.name": "组名",
|
|
||||||
"access.group.name.not.empty": "请输入组名",
|
|
||||||
"access.group.delete": "删除组",
|
|
||||||
"access.group.delete.confirm": "确定要删除部署授权组吗?",
|
|
||||||
"access.group.domain.empty": "请添加域名开始部署证书吧。",
|
|
||||||
"access.group.empty": "暂无部署授权配置,请添加后开始使用吧",
|
|
||||||
"access.group.total": "共有 {{total}} 个部署授权配置",
|
|
||||||
"access.form.name.not.empty": "请输入授权名称",
|
|
||||||
"access.form.config.field": "配置类型",
|
|
||||||
"access.form.access.key.id": "AccessKeyId",
|
|
||||||
"access.form.access.key.id.not.empty": "请输入 AccessKeyId",
|
|
||||||
"access.form.access.key.secret": "AccessKeySecret",
|
|
||||||
"access.form.access.key.secret.not.empty": "请输入 AccessKeySecret",
|
|
||||||
"access.form.cloud.dns.api.token": "CLOUD_DNS_API_TOKEN",
|
|
||||||
"access.form.cloud.dns.api.token.not.empty": "请输入 CLOUD_DNS_API_TOKEN",
|
|
||||||
"access.form.go.daddy.api.key": "GO_DADDY_API_KEY",
|
|
||||||
"access.form.go.daddy.api.key.not.empty": "请输入 GO_DADDY_API_KEY",
|
|
||||||
"access.form.go.daddy.api.secret": "GO_DADDY_API_SECRET",
|
|
||||||
"access.form.go.daddy.api.secret.not.empty": "请输入 GO_DADDY_API_SECRET",
|
|
||||||
"access.form.namesilo.api.key": "NAMESILO_API_KEY",
|
|
||||||
"access.form.namesilo.api.key.not.empty": "请输入 NAMESILO_API_KEY",
|
|
||||||
"access.form.secret.id": "SecretId",
|
|
||||||
"access.form.secret.id.not.empty": "请输入 SecretId",
|
|
||||||
"access.form.secret.key": "SecretKey",
|
|
||||||
"access.form.secret.key.not.empty": "请输入 SecretKey",
|
|
||||||
"access.form.access.key": "AccessKey",
|
|
||||||
"access.form.access.key.not.empty": "请输入 AccessKey",
|
|
||||||
"access.form.region": "Region",
|
|
||||||
"access.form.region.not.empty": "请输入区域",
|
|
||||||
"access.form.webhook.url": "Webhook URL",
|
|
||||||
"access.form.webhook.url.not.empty": "请输入 Webhook URL",
|
|
||||||
"access.form.ssh.group.label": "授权配置组(用于将一个域名证书部署到多个 ssh 主机)",
|
|
||||||
"access.form.ssh.host": "服务器 Host",
|
|
||||||
"access.form.ssh.host.not.empty": "请输入 Host",
|
|
||||||
"access.form.ssh.port": "SSH 端口",
|
|
||||||
"access.form.ssh.port.not.empty": "请输入 Port",
|
|
||||||
"access.form.ssh.key": "Key(使用证书登录)",
|
|
||||||
"access.form.ssh.key.not.empty": "请输入 Key",
|
|
||||||
"access.form.ssh.key.file.not.empty": "请选择文件",
|
|
||||||
"access.form.ssh.cert.path": "证书保存路径",
|
|
||||||
"access.form.ssh.cert.path.not.empty": "请输入证书保存路径",
|
|
||||||
"access.form.ssh.key.path": "私钥保存路径",
|
|
||||||
"access.form.ssh.key.path.not.empty": "请输入私钥保存路径",
|
|
||||||
"access.form.ssh.pre.command": "前置 Command",
|
|
||||||
"access.form.ssh.pre.command.not.empty": "在部署证书前执行的前置命令",
|
|
||||||
"access.form.ssh.command": "Command",
|
|
||||||
"access.form.ssh.command.not.empty": "请输入要执行的命令",
|
|
||||||
"access.form.ding.access.token.placeholder": "加签的签名",
|
|
||||||
|
|
||||||
"variable": "变量",
|
|
||||||
"variable.name": "变量名",
|
|
||||||
"variable.value": "值",
|
|
||||||
"variable.not.added": "尚未添加变量",
|
|
||||||
"variable.name.required": "变量名不能为空",
|
|
||||||
"variable.value.required": "变量值不能为空",
|
|
||||||
"variable.name.placeholder": "请输入变量名",
|
|
||||||
"variable.value.placeholder": "请输入变量值",
|
|
||||||
|
|
||||||
"deployment": "部署",
|
|
||||||
"deployment.not.added": "暂无部署配置,请添加后开始部署证书吧",
|
|
||||||
"deployment.access.type": "授权类型",
|
|
||||||
"deployment.access.config": "授权配置",
|
|
||||||
"deployment.access.cdn.deploy.to.domain": "部署到域名",
|
|
||||||
|
|
||||||
"deployment.access.oss.bucket": "Bucket",
|
|
||||||
"deployment.access.oss.bucket.not.empty": "请输入 Bucket",
|
|
||||||
"deployment.access.oss.endpoint": "Endpoint"
|
|
||||||
}
|
|
17
ui/src/i18n/locales/zh/index.ts
Normal file
17
ui/src/i18n/locales/zh/index.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import nlsCommon from "./nls.common.json";
|
||||||
|
import nlsLogin from "./nls.login.json";
|
||||||
|
import nlsDashboard from "./nls.dashboard.json";
|
||||||
|
import nlsSettings from "./nls.settings.json";
|
||||||
|
import nlsDomain from "./nls.domain.json";
|
||||||
|
import nlsAccess from "./nls.access.json";
|
||||||
|
import nlsHistory from "./nls.history.json";
|
||||||
|
|
||||||
|
export default Object.freeze({
|
||||||
|
...nlsCommon,
|
||||||
|
...nlsLogin,
|
||||||
|
...nlsDashboard,
|
||||||
|
...nlsSettings,
|
||||||
|
...nlsDomain,
|
||||||
|
...nlsAccess,
|
||||||
|
...nlsHistory,
|
||||||
|
});
|
80
ui/src/i18n/locales/zh/nls.access.json
Normal file
80
ui/src/i18n/locales/zh/nls.access.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"access.page.title": "授权管理",
|
||||||
|
|
||||||
|
"access.authorization.tab": "授权",
|
||||||
|
"access.authorization.nodata": "请添加授权开始部署证书吧。",
|
||||||
|
|
||||||
|
"access.authorization.add": "新增授权",
|
||||||
|
"access.authorization.edit": "编辑授权",
|
||||||
|
"access.authorization.copy": "复制授权",
|
||||||
|
"access.authorization.delete": "删除授权",
|
||||||
|
"access.authorization.delete.confirm": "确定要删除授权吗?",
|
||||||
|
|
||||||
|
"access.authorization.form.type.label": "服务商",
|
||||||
|
"access.authorization.form.type.placeholder": "请选择服务商",
|
||||||
|
"access.authorization.form.type.list": "服务商列表",
|
||||||
|
"access.authorization.form.name.label": "名称",
|
||||||
|
"access.authorization.form.name.placeholder": "请输入授权名称",
|
||||||
|
"access.authorization.form.config.label": "配置类型",
|
||||||
|
"access.authorization.form.region.label": "Region",
|
||||||
|
"access.authorization.form.region.placeholder": "请输入区域",
|
||||||
|
"access.authorization.form.access_key_id.label": "AccessKeyId",
|
||||||
|
"access.authorization.form.access_key_id.placeholder": "请输入 AccessKeyId",
|
||||||
|
"access.authorization.form.access_key_secret.label": "AccessKeySecret",
|
||||||
|
"access.authorization.form.access_key_secret..placeholder": "请输入 AccessKeySecret",
|
||||||
|
"access.authorization.form.access_key.label": "AccessKey",
|
||||||
|
"access.authorization.form.access_key.placeholder": "请输入 AccessKey",
|
||||||
|
"access.authorization.form.secret_id.label": "SecretId",
|
||||||
|
"access.authorization.form.secret_id.placeholder": "请输入 SecretId",
|
||||||
|
"access.authorization.form.secret_key.label": "SecretKey",
|
||||||
|
"access.authorization.form.secret_key.placeholder": "请输入 SecretKey",
|
||||||
|
"access.authorization.form.cloud_dns_api_token.label": "CLOUD_DNS_API_TOKEN",
|
||||||
|
"access.authorization.form.cloud_dns_api_token.placeholder": "请输入 CLOUD_DNS_API_TOKEN",
|
||||||
|
"access.authorization.form.godaddy_api_key.label": "GO_DADDY_API_KEY",
|
||||||
|
"access.authorization.form.godaddy_api_key.placeholder": "请输入 GO_DADDY_API_KEY",
|
||||||
|
"access.authorization.form.godaddy_api_secret.label": "GO_DADDY_API_SECRET",
|
||||||
|
"access.authorization.form.godaddy_api_secret.placeholder": "请输入 GO_DADDY_API_SECRET",
|
||||||
|
"access.authorization.form.namesilo_api_key.label": "NAMESILO_API_KEY",
|
||||||
|
"access.authorization.form.namesilo_api_key.placeholder": "请输入 NAMESILO_API_KEY",
|
||||||
|
"access.authorization.form.username.label": "用户名",
|
||||||
|
"access.authorization.form.username.placeholder": "请输入用户名",
|
||||||
|
"access.authorization.form.password.label": "密码",
|
||||||
|
"access.authorization.form.password.placeholder": "请输入密码",
|
||||||
|
"access.authorization.form.access_group.placeholder": "请选择分组",
|
||||||
|
"access.authorization.form.ssh_group.label": "授权配置组(用于将一个域名证书部署到多个 SSH 主机)",
|
||||||
|
"access.authorization.form.ssh_host.label": "服务器 Host",
|
||||||
|
"access.authorization.form.ssh_host.placeholder": "请输入 Host",
|
||||||
|
"access.authorization.form.ssh_port.label": "SSH 端口",
|
||||||
|
"access.authorization.form.ssh_port.placeholder": "请输入 Port",
|
||||||
|
"access.authorization.form.ssh_key.label": "Key(使用私钥登录)",
|
||||||
|
"access.authorization.form.ssh_key.placeholder": "请输入 Key",
|
||||||
|
"access.authorization.form.ssh_key_file.placeholder": "请选择文件",
|
||||||
|
"access.authorization.form.ssh_key.label.passphrase": "私钥密码",
|
||||||
|
"access.authorization.form.ssh_key_path.label": "私钥保存路径",
|
||||||
|
"access.authorization.form.ssh_key_path.placeholder": "请输入私钥保存路径",
|
||||||
|
"access.authorization.form.ssh_cert_path.label": "证书保存路径",
|
||||||
|
"access.authorization.form.ssh_cert_path.placeholder": "请输入证书保存路径",
|
||||||
|
"access.authorization.form.ssh_pre_command.label": "前置 Command",
|
||||||
|
"access.authorization.form.ssh_pre_command.placeholder": "在部署证书前执行的前置命令",
|
||||||
|
"access.authorization.form.ssh_command.label": "Command",
|
||||||
|
"access.authorization.form.ssh_command.placeholder": "请输入要执行的命令",
|
||||||
|
"access.authorization.form.webhook_url.label": "Webhook URL",
|
||||||
|
"access.authorization.form.webhook_url.placeholder": "请输入 Webhook URL",
|
||||||
|
|
||||||
|
"access.group.tab": "授权组",
|
||||||
|
|
||||||
|
"access.group.nodata": "暂无部署授权配置,请添加后开始使用吧",
|
||||||
|
"access.group.total": "共有 {{total}} 个部署授权配置",
|
||||||
|
|
||||||
|
"access.group.add": "添加授权组",
|
||||||
|
"access.group.delete": "删除组",
|
||||||
|
"access.group.delete.confirm": "确定要删除部署授权组吗?",
|
||||||
|
|
||||||
|
"access.group.form.name.label": "组名",
|
||||||
|
"access.group.form.name.errmsg.empty": "请输入组名",
|
||||||
|
|
||||||
|
"access.group.domains": "所有授权",
|
||||||
|
"access.group.domains.nodata": "请添加域名开始部署证书吧。",
|
||||||
|
|
||||||
|
"access.common.type.errmsg.empty": "请选择服务商"
|
||||||
|
}
|
72
ui/src/i18n/locales/zh/nls.common.json
Normal file
72
ui/src/i18n/locales/zh/nls.common.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"common.add": "新增",
|
||||||
|
"common.save": "保存",
|
||||||
|
"common.save.succeeded.message": "保存成功",
|
||||||
|
"common.save.failed.message": "保存失败",
|
||||||
|
"common.edit": "编辑",
|
||||||
|
"common.copy": "复制",
|
||||||
|
"common.download": "下载",
|
||||||
|
"common.delete": "刪除",
|
||||||
|
"common.delete.succeeded.message": "删除成功",
|
||||||
|
"common.delete.failed.message": "删除失败",
|
||||||
|
"common.next": "下一步",
|
||||||
|
"common.confirm": "确认",
|
||||||
|
"common.cancel": "取消",
|
||||||
|
"common.submit": "提交",
|
||||||
|
"common.update": "更新",
|
||||||
|
"common.update.succeeded.message": "修改成功",
|
||||||
|
"common.update.failed.message": "修改失败",
|
||||||
|
|
||||||
|
"common.text.domain": "域名",
|
||||||
|
"common.text.domain.empty": "无域名",
|
||||||
|
"common.text.ip": "IP 地址",
|
||||||
|
"common.text.ip.empty": "无 IP 地址",
|
||||||
|
"common.text.dns": "DNS(域名服务器)",
|
||||||
|
"common.text.dns.empty": "无 DNS 地址",
|
||||||
|
"common.text.ca": "CA(证书颁发机构)",
|
||||||
|
"common.text.name": "名称",
|
||||||
|
"common.text.provider": "服务商",
|
||||||
|
"common.text.created_at": "创建时间",
|
||||||
|
"common.text.updated_at": "更新时间",
|
||||||
|
"common.text.operations": "操作",
|
||||||
|
"common.text.nodata": "暂无数据",
|
||||||
|
|
||||||
|
"common.menu.settings": "系统设置",
|
||||||
|
"common.menu.logout": "退出登录",
|
||||||
|
"common.menu.document": "文档",
|
||||||
|
|
||||||
|
"common.pagination.next": "下一页",
|
||||||
|
"common.pagination.prev": "上一页",
|
||||||
|
"common.pagination.more": "更多",
|
||||||
|
|
||||||
|
"common.theme.light": "浅色",
|
||||||
|
"common.theme.dark": "暗黑",
|
||||||
|
"common.theme.system": "跟随系统",
|
||||||
|
|
||||||
|
"common.errmsg.string_max": "请输入不超过 {{max}} 个字符",
|
||||||
|
"common.errmsg.email_empty": "请输入邮箱",
|
||||||
|
"common.errmsg.email_invalid": "请输入正确的邮箱",
|
||||||
|
"common.errmsg.email_duplicate": "邮箱已存在",
|
||||||
|
"common.errmsg.domain_invalid": "请输入正确的域名",
|
||||||
|
"common.errmsg.host_invalid": "请输入正确的域名或 IP 地址",
|
||||||
|
"common.errmsg.ip_invalid": "请输入正确的 IP 地址",
|
||||||
|
"common.errmsg.url_invalid": "请输入正确的 URL",
|
||||||
|
|
||||||
|
"common.provider.tencent": "腾讯云",
|
||||||
|
"common.provider.tencent.cdn": "腾讯云-CDN",
|
||||||
|
"common.provider.aliyun": "阿里云",
|
||||||
|
"common.provider.aliyun.cdn": "阿里云-CDN",
|
||||||
|
"common.provider.aliyun.oss": "阿里云-OSS",
|
||||||
|
"common.provider.aliyun.dcdn": "阿里云-DCDN",
|
||||||
|
"common.provider.huaweicloud": "华为云",
|
||||||
|
"common.provider.qiniu": "七牛云",
|
||||||
|
"common.provider.qiniu.cdn": "七牛云-CDN",
|
||||||
|
"common.provider.cloudflare": "Cloudflare",
|
||||||
|
"common.provider.namesilo": "Namesilo",
|
||||||
|
"common.provider.godaddy": "GoDaddy",
|
||||||
|
"common.provider.local": "本地部署",
|
||||||
|
"common.provider.ssh": "SSH 部署",
|
||||||
|
"common.provider.webhook": "Webhook",
|
||||||
|
"common.provider.dingtalk": "钉钉",
|
||||||
|
"common.provider.telegram": "Telegram"
|
||||||
|
}
|
11
ui/src/i18n/locales/zh/nls.dashboard.json
Normal file
11
ui/src/i18n/locales/zh/nls.dashboard.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"dashboard.page.title": "仪表盘",
|
||||||
|
|
||||||
|
"dashboard.statistics.all": "所有",
|
||||||
|
"dashboard.statistics.near_expired": "即将过期",
|
||||||
|
"dashboard.statistics.enabled": "启用中",
|
||||||
|
"dashboard.statistics.disabled": "未启用",
|
||||||
|
"dashboard.statistics.unit": "个",
|
||||||
|
|
||||||
|
"dashboard.history": "部署历史"
|
||||||
|
}
|
65
ui/src/i18n/locales/zh/nls.domain.json
Normal file
65
ui/src/i18n/locales/zh/nls.domain.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"domain.page.title": "域名列表",
|
||||||
|
|
||||||
|
"domain.nodata": "请添加域名开始部署证书吧。",
|
||||||
|
|
||||||
|
"domain.add": "新增域名",
|
||||||
|
"domain.edit": "编辑域名",
|
||||||
|
"domain.delete": "删除域名",
|
||||||
|
"domain.delete.confirm": "确定要删除域名吗?",
|
||||||
|
"domain.history": "部署历史",
|
||||||
|
"domain.deploy": "立即部署",
|
||||||
|
"domain.deploy.started.message": "开始部署",
|
||||||
|
"domain.deploy.started.tips": "已发起部署,请稍后查看部署日志。",
|
||||||
|
"domain.deploy.failed.message": "执行失败",
|
||||||
|
"domain.deploy.failed.tips": "执行失败,请在 <1>部署历史</1> 查看详情。",
|
||||||
|
"domain.deploy_forced": "强行部署",
|
||||||
|
|
||||||
|
"domain.props.expiry": "有效期限",
|
||||||
|
"domain.props.expiry.date1": "有效期 {{date}} 天",
|
||||||
|
"domain.props.expiry.date2": "{{date}} 到期",
|
||||||
|
"domain.props.last_execution_status": "最近执行状态",
|
||||||
|
"domain.props.last_execution_stage": "最近执行阶段",
|
||||||
|
"domain.props.last_execution_time": "最近执行时间",
|
||||||
|
"domain.props.enable": "是否启用",
|
||||||
|
"domain.props.enable.enabled": "启用",
|
||||||
|
"domain.props.enable.disabled": "禁用",
|
||||||
|
|
||||||
|
"domain.application.tab": "申请配置",
|
||||||
|
"domain.application.form.domain.added.message": "域名添加成功",
|
||||||
|
"domain.application.form.domain.changed.message": "域名编辑成功",
|
||||||
|
"domain.application.form.email.label": "邮箱",
|
||||||
|
"domain.application.form.email.tips": "(申请证书需要提供邮箱)",
|
||||||
|
"domain.application.form.email.add": "添加邮箱",
|
||||||
|
"domain.application.form.email.list": "邮箱列表",
|
||||||
|
"domain.application.form.email.errmsg.empty": "请选择邮箱",
|
||||||
|
"domain.application.form.access.label": "DNS 服务商授权配置",
|
||||||
|
"domain.application.form.access.placeholder": "请选择 DNS 服务商授权配置",
|
||||||
|
"domain.application.form.access.errmsg.empty": "请选择 DNS 服务商授权配置",
|
||||||
|
"domain.application.form.access.list": "已有的 DNS 服务商授权配置",
|
||||||
|
"domain.application.form.timeout.label": "超时时间",
|
||||||
|
"domain.application.form.timeoue.placeholder": "超时时间(单位:秒)",
|
||||||
|
"domain.application.unsaved.message": "请先保存申请配置",
|
||||||
|
|
||||||
|
"domain.deployment.tab": "部署配置",
|
||||||
|
"domain.deployment.nodata": "暂无部署配置,请添加后开始部署证书吧",
|
||||||
|
"domain.deployment.form.type.label": "部署方式",
|
||||||
|
"domain.deployment.form.type.placeholder": "请选择部署方式",
|
||||||
|
"domain.deployment.form.type.list": "支持的部署方式",
|
||||||
|
"domain.deployment.form.access.label": "授权配置",
|
||||||
|
"domain.deployment.form.access.placeholder": "请选择授权配置",
|
||||||
|
"domain.deployment.form.access.list": "已有的服务商授权配置",
|
||||||
|
"domain.deployment.form.cdn_domain.label": "部署到域名",
|
||||||
|
"domain.deployment.form.cdn_domain.placeholder": "请输入 CDN 域名",
|
||||||
|
"domain.deployment.form.oss_endpoint.label": "Endpoint",
|
||||||
|
"domain.deployment.form.oss_bucket": "存储桶",
|
||||||
|
"domain.deployment.form.oss_bucket.placeholder": "请输入存储桶名",
|
||||||
|
"domain.deployment.form.variables.label": "变量",
|
||||||
|
"domain.deployment.form.variables.key": "变量名",
|
||||||
|
"domain.deployment.form.variables.value": "值",
|
||||||
|
"domain.deployment.form.variables.empty": "尚未添加变量",
|
||||||
|
"domain.deployment.form.variables.key.required": "变量名不能为空",
|
||||||
|
"domain.deployment.form.variables.value.required": "变量值不能为空",
|
||||||
|
"domain.deployment.form.variables.key.placeholder": "请输入变量名",
|
||||||
|
"domain.deployment.form.variables.value.placeholder": "请输入变量值"
|
||||||
|
}
|
15
ui/src/i18n/locales/zh/nls.history.json
Normal file
15
ui/src/i18n/locales/zh/nls.history.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"history.page.title": "部署",
|
||||||
|
|
||||||
|
"history.nodata": "你暂未创建任何部署,请先添加域名进行部署吧!",
|
||||||
|
|
||||||
|
"history.props.domain": "域名",
|
||||||
|
"history.props.status": "状态",
|
||||||
|
"history.props.stage": "阶段",
|
||||||
|
"history.props.stage.progress.check": "检查",
|
||||||
|
"history.props.stage.progress.apply": "获取",
|
||||||
|
"history.props.stage.progress.deploy": "部署",
|
||||||
|
"history.props.last_execution_time": "最近执行时间",
|
||||||
|
|
||||||
|
"history.log": "日志"
|
||||||
|
}
|
9
ui/src/i18n/locales/zh/nls.login.json
Normal file
9
ui/src/i18n/locales/zh/nls.login.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"login.username.label": "用户名",
|
||||||
|
"login.username.placeholder": "请输入用户名/邮箱",
|
||||||
|
"login.username.errmsg.invalid": "请输入正确的用户名/邮箱",
|
||||||
|
"login.password.label": "密码",
|
||||||
|
"login.password.placeholder": "请输入密码",
|
||||||
|
"login.password.errmsg.invalid": "密码至少 10 个字符",
|
||||||
|
"login.submit": "登录"
|
||||||
|
}
|
41
ui/src/i18n/locales/zh/nls.settings.json
Normal file
41
ui/src/i18n/locales/zh/nls.settings.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"settings.page.title": "系统设置",
|
||||||
|
|
||||||
|
"settings.account.relogin.message": "请重新登录",
|
||||||
|
|
||||||
|
"settings.account.tab": "账号",
|
||||||
|
"settings.account.email.label": "登录邮箱",
|
||||||
|
"settings.account.email.errmsg.invalid": "请输入正确的邮箱地址",
|
||||||
|
"settings.account.email.placeholder": "请输入邮箱",
|
||||||
|
"settings.account.email.changed.message": "修改账户邮箱成功",
|
||||||
|
"settings.account.email.failed.message": "修改账户邮箱失败",
|
||||||
|
|
||||||
|
"settings.password.tab": "密码",
|
||||||
|
"settings.password.password.errmsg.length": "密码至少10个字符",
|
||||||
|
"settings.password.password.errmsg.not_matched": "两次密码不一致",
|
||||||
|
"settings.password.current_password.label": "当前密码",
|
||||||
|
"settings.password.current_password.placeholder": "请输入旧密码",
|
||||||
|
"settings.password.new_password.label": "新密码",
|
||||||
|
"settings.password.new_password.placeholder": "请输入新密码",
|
||||||
|
"settings.password.confirm_password.label": "确认密码",
|
||||||
|
"settings.password.confirm_password.placeholder": "请再次输入新密码",
|
||||||
|
"settings.password.changed.message": "修改密码成功",
|
||||||
|
"settings.password.failed.message": "修改密码失败",
|
||||||
|
|
||||||
|
"settings.notification.tab": "消息推送",
|
||||||
|
"settings.notification.template.label": "内容模板",
|
||||||
|
"settings.notification.template.saved.message": "通知模板保存成功",
|
||||||
|
"settings.notification.template.variables.tips.title": "可选的变量({COUNT}: 即将过期张数)",
|
||||||
|
"settings.notification.template.variables.tips.content": "可选的变量({COUNT}: 即将过期张数;{DOMAINS}: 域名列表)",
|
||||||
|
"settings.notification.config.enable": "是否启用",
|
||||||
|
"settings.notification.config.saved.message": "配置保存成功",
|
||||||
|
"settings.notification.config.failed.message": "配置保存失败",
|
||||||
|
"settings.notification.dingtalk.secret.placeholder": "加签的签名",
|
||||||
|
"settings.notification.url.errmsg.invalid": "URL 格式不正确",
|
||||||
|
|
||||||
|
"settings.ca.tab": "证书颁发机构(CA)",
|
||||||
|
"settings.ca.provider.errmsg.empty": "请选择证书分发机构",
|
||||||
|
"settings.ca.eab_kid.errmsg.empty": "请输入EAB_KID",
|
||||||
|
"settings.ca.eab_hmac_key.errmsg.empty": "请输入EAB_HMAC_KEY",
|
||||||
|
"settings.ca.eab_kid_hmac_key.errmsg.empty": "请输入EAB_KID和EAB_HMAC_KEY"
|
||||||
|
}
|
@ -14,8 +14,6 @@ import {
|
|||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
|
||||||
@ -30,7 +28,7 @@ import Version from "@/components/certimate/Version";
|
|||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (!getPb().authStore.isValid || !getPb().authStore.isAdmin) {
|
if (!getPb().authStore.isValid || !getPb().authStore.isAdmin) {
|
||||||
return <Navigate to="/login" />;
|
return <Navigate to="/login" />;
|
||||||
@ -73,7 +71,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Home className="h-4 w-4" />
|
<Home className="h-4 w-4" />
|
||||||
{t('dashboard')}
|
{t("dashboard.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/domains"
|
to="/domains"
|
||||||
@ -83,7 +81,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Earth className="h-4 w-4" />
|
<Earth className="h-4 w-4" />
|
||||||
{t('domain.management.name')}
|
{t("domain.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/access"
|
to="/access"
|
||||||
@ -93,7 +91,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Server className="h-4 w-4" />
|
<Server className="h-4 w-4" />
|
||||||
{t('menu.auth.management')}
|
{t("access.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
@ -104,7 +102,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<History className="h-4 w-4" />
|
<History className="h-4 w-4" />
|
||||||
{t('deployment.log.name')}
|
{t("history.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@ -141,7 +139,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Home className="h-5 w-5" />
|
<Home className="h-5 w-5" />
|
||||||
{t('dashboard')}
|
{t("dashboard.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/domains"
|
to="/domains"
|
||||||
@ -151,7 +149,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Earth className="h-5 w-5" />
|
<Earth className="h-5 w-5" />
|
||||||
{t('domain.management.name')}
|
{t("domain.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/access"
|
to="/access"
|
||||||
@ -161,7 +159,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Server className="h-5 w-5" />
|
<Server className="h-5 w-5" />
|
||||||
{t('menu.auth.management')}
|
{t("access.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
@ -172,7 +170,7 @@ export default function Dashboard() {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<History className="h-5 w-5" />
|
<History className="h-5 w-5" />
|
||||||
{t('deployment.log.name')}
|
{t("history.page.title")}
|
||||||
</Link>
|
</Link>
|
||||||
</nav>
|
</nav>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
@ -192,15 +190,11 @@ export default function Dashboard() {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end">
|
<DropdownMenuContent align="end">
|
||||||
<DropdownMenuLabel>{t('account')}</DropdownMenuLabel>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
|
|
||||||
<DropdownMenuItem onClick={handleSettingClick}>
|
<DropdownMenuItem onClick={handleSettingClick}>
|
||||||
{t('setting')}
|
{t("common.menu.settings")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
|
||||||
<DropdownMenuItem onClick={handleLogoutClick}>
|
<DropdownMenuItem onClick={handleLogoutClick}>
|
||||||
{t('logout')}
|
{t("common.menu.logout")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
@ -22,7 +22,7 @@ const SettingLayout = () => {
|
|||||||
<div>
|
<div>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
<div className="text-muted-foreground border-b dark:border-stone-500 py-5">
|
<div className="text-muted-foreground border-b dark:border-stone-500 py-5">
|
||||||
{t("setting")}
|
{t("settings.page.title")}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full mt-5 p-0 md:p-3 flex justify-center">
|
<div className="w-full mt-5 p-0 md:p-3 flex justify-center">
|
||||||
<Tabs defaultValue="account" className="w-full" value={tabValue}>
|
<Tabs defaultValue="account" className="w-full" value={tabValue}>
|
||||||
@ -35,8 +35,9 @@ const SettingLayout = () => {
|
|||||||
className="px-5"
|
className="px-5"
|
||||||
>
|
>
|
||||||
<UserRound size={14} />
|
<UserRound size={14} />
|
||||||
<div className="ml-1">{t("account")}</div>
|
<div className="ml-1">{t("settings.account.tab")}</div>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="password"
|
value="password"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -45,7 +46,7 @@ const SettingLayout = () => {
|
|||||||
className="px-5"
|
className="px-5"
|
||||||
>
|
>
|
||||||
<KeyRound size={14} />
|
<KeyRound size={14} />
|
||||||
<div className="ml-1">{t("password")}</div>
|
<div className="ml-1">{t("settings.password.tab")}</div>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
@ -56,8 +57,9 @@ const SettingLayout = () => {
|
|||||||
className="px-5"
|
className="px-5"
|
||||||
>
|
>
|
||||||
<Megaphone size={14} />
|
<Megaphone size={14} />
|
||||||
<div className="ml-1">{t("setting.notify.menu")}</div>
|
<div className="ml-1">{t("settings.notification.tab")}</div>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
|
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="ssl-provider"
|
value="ssl-provider"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -66,7 +68,7 @@ const SettingLayout = () => {
|
|||||||
className="px-5"
|
className="px-5"
|
||||||
>
|
>
|
||||||
<ShieldCheck size={14} />
|
<ShieldCheck size={14} />
|
||||||
<div className="ml-1">{t("ca")}</div>
|
<div className="ml-1">{t("settings.ca.tab")}</div>
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value={tabValue}>
|
<TabsContent value={tabValue}>
|
||||||
|
@ -16,10 +16,12 @@ import {
|
|||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
AlertDialogCancel,
|
AlertDialogCancel,
|
||||||
AlertDialogContent, AlertDialogDescription, AlertDialogFooter,
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger
|
AlertDialogTrigger,
|
||||||
} from "@/components/ui/alert-dialog.tsx";
|
} from "@/components/ui/alert-dialog.tsx";
|
||||||
|
|
||||||
const Access = () => {
|
const Access = () => {
|
||||||
@ -56,9 +58,9 @@ const Access = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="">
|
<div className="">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="text-muted-foreground">{t("access.management")}</div>
|
<div className="text-muted-foreground">{t("access.page.title")}</div>
|
||||||
{tab != "access_group" ? (
|
{tab != "access_group" ? (
|
||||||
<AccessEdit trigger={<Button>{t("access.add")}</Button>} op="add" />
|
<AccessEdit trigger={<Button>{t("access.authorization.add")}</Button>} op="add" />
|
||||||
) : (
|
) : (
|
||||||
<AccessGroupEdit trigger={<Button>{t("access.group.add")}</Button>} />
|
<AccessGroupEdit trigger={<Button>{t("access.group.add")}</Button>} />
|
||||||
)}
|
)}
|
||||||
@ -76,7 +78,7 @@ const Access = () => {
|
|||||||
handleTabItemClick("access");
|
handleTabItemClick("access");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("access.management")}
|
{t("access.authorization.tab")}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="access_group"
|
value="access_group"
|
||||||
@ -84,7 +86,7 @@ const Access = () => {
|
|||||||
handleTabItemClick("access_group");
|
handleTabItemClick("access_group");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("access.group.management")}
|
{t("access.group.tab")}
|
||||||
</TabsTrigger>
|
</TabsTrigger>
|
||||||
</TabsList>
|
</TabsList>
|
||||||
<TabsContent value="access">
|
<TabsContent value="access">
|
||||||
@ -95,10 +97,10 @@ const Access = () => {
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="text-center text-sm text-muted-foreground mt-3">
|
<div className="text-center text-sm text-muted-foreground mt-3">
|
||||||
{t("access.empty")}
|
{t("access.authorization.nodata")}
|
||||||
</div>
|
</div>
|
||||||
<AccessEdit
|
<AccessEdit
|
||||||
trigger={<Button>{t("access.add")}</Button>}
|
trigger={<Button>{t("access.authorization.add")}</Button>}
|
||||||
op="add"
|
op="add"
|
||||||
className="mt-3"
|
className="mt-3"
|
||||||
/>
|
/>
|
||||||
@ -106,15 +108,12 @@ const Access = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
||||||
<div className="w-48">{t("name")}</div>
|
<div className="w-48">{t("common.text.name")}</div>
|
||||||
<div className="w-48">{t("access.type")}</div>
|
<div className="w-48">{t("common.text.provider")}</div>
|
||||||
|
|
||||||
<div className="w-60">{t("create.time")}</div>
|
<div className="w-60">{t("common.text.created_at")}</div>
|
||||||
<div className="w-60">{t("update.time")}</div>
|
<div className="w-60">{t("common.text.updated_at")}</div>
|
||||||
<div className="grow">{t("operation")}</div>
|
<div className="grow">{t("common.text.operations")}</div>
|
||||||
</div>
|
|
||||||
<div className="sm:hidden flex text-sm text-muted-foreground">
|
|
||||||
{t("access.list")}
|
|
||||||
</div>
|
</div>
|
||||||
{accesses
|
{accesses
|
||||||
.filter((item) => {
|
.filter((item) => {
|
||||||
@ -140,18 +139,16 @@ const Access = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:w-60 w-full pt-1 sm:pt-0 flex items-center">
|
<div className="sm:w-60 w-full pt-1 sm:pt-0 flex items-center">
|
||||||
{t("created.in")}{" "}
|
|
||||||
{access.created && convertZulu2Beijing(access.created)}
|
{access.created && convertZulu2Beijing(access.created)}
|
||||||
</div>
|
</div>
|
||||||
<div className="sm:w-60 w-full pt-1 sm:pt-0 flex items-center">
|
<div className="sm:w-60 w-full pt-1 sm:pt-0 flex items-center">
|
||||||
{t("updated.in")}{" "}
|
|
||||||
{access.updated && convertZulu2Beijing(access.updated)}
|
{access.updated && convertZulu2Beijing(access.updated)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center grow justify-start pt-1 sm:pt-0">
|
<div className="flex items-center grow justify-start pt-1 sm:pt-0">
|
||||||
<AccessEdit
|
<AccessEdit
|
||||||
trigger={
|
trigger={
|
||||||
<Button variant={"link"} className="p-0">
|
<Button variant={"link"} className="p-0">
|
||||||
{t("edit")}
|
{t("common.edit")}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
op="edit"
|
op="edit"
|
||||||
@ -159,40 +156,40 @@ const Access = () => {
|
|||||||
/>
|
/>
|
||||||
<Separator orientation="vertical" className="h-4 mx-2" />
|
<Separator orientation="vertical" className="h-4 mx-2" />
|
||||||
<AccessEdit
|
<AccessEdit
|
||||||
trigger={
|
trigger={
|
||||||
<Button variant={"link"} className="p-0">
|
<Button variant={"link"} className="p-0">
|
||||||
{t("copy")}
|
{t("common.copy")}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
op="copy"
|
op="copy"
|
||||||
data={access}
|
data={access}
|
||||||
/>
|
/>
|
||||||
<Separator orientation="vertical" className="h-4 mx-2" />
|
<Separator orientation="vertical" className="h-4 mx-2" />
|
||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button variant={"link"} size={"sm"}>
|
<Button variant={"link"} className="p-0">
|
||||||
{t('delete')}
|
{t("common.delete")}
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
<AlertDialogTitle className="dark:text-gray-200">
|
<AlertDialogTitle className="dark:text-gray-200">
|
||||||
{t('access.group.delete')}
|
{t("access.authorization.delete")}
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
{t('access.delete.confirm')}
|
{t("access.authorization.delete.confirm")}
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel className="dark:text-gray-200">
|
<AlertDialogCancel className="dark:text-gray-200">
|
||||||
{t('cancel')}
|
{t("common.cancel")}
|
||||||
</AlertDialogCancel>
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleDelete(access);
|
handleDelete(access);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('confirm')}
|
{t("common.confirm")}
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
|
@ -57,7 +57,7 @@ const Dashboard = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="text-muted-foreground">{t("dashboard")}</div>
|
<div className="text-muted-foreground">{t("dashboard.page.title")}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex mt-10 gap-5 flex-col flex-wrap md:flex-row">
|
<div className="flex mt-10 gap-5 flex-col flex-wrap md:flex-row">
|
||||||
<div className="w-full md:w-[250px] 3xl:w-[300px] flex items-center rounded-md p-3 shadow-lg border">
|
<div className="w-full md:w-[250px] 3xl:w-[300px] flex items-center rounded-md p-3 shadow-lg border">
|
||||||
@ -66,7 +66,7 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-muted-foreground font-semibold">
|
<div className="text-muted-foreground font-semibold">
|
||||||
{t("dashboard.all")}
|
{t("dashboard.statistics.all")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-baseline">
|
<div className="flex items-baseline">
|
||||||
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
||||||
@ -79,7 +79,7 @@ const Dashboard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
||||||
{t("dashboard.unit")}
|
{t("dashboard.statistics.unit")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -91,7 +91,7 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-muted-foreground font-semibold">
|
<div className="text-muted-foreground font-semibold">
|
||||||
{t("dashboard.near.expired")}
|
{t("dashboard.statistics.near_expired")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-baseline">
|
<div className="flex items-baseline">
|
||||||
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
||||||
@ -104,7 +104,7 @@ const Dashboard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
||||||
{t("dashboard.unit")}
|
{t("dashboard.statistics.unit")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -120,7 +120,7 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-muted-foreground font-semibold">
|
<div className="text-muted-foreground font-semibold">
|
||||||
{t("dashboard.enabled")}
|
{t("dashboard.statistics.enabled")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-baseline">
|
<div className="flex items-baseline">
|
||||||
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
||||||
@ -133,7 +133,7 @@ const Dashboard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
||||||
{t("dashboard.unit")}
|
{t("dashboard.statistics.unit")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -145,7 +145,7 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-muted-foreground font-semibold">
|
<div className="text-muted-foreground font-semibold">
|
||||||
{t("dashboard.not.enabled")}
|
{t("dashboard.statistics.disabled")}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-baseline">
|
<div className="flex items-baseline">
|
||||||
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
<div className="text-3xl text-stone-700 dark:text-stone-200">
|
||||||
@ -161,28 +161,32 @@ const Dashboard = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
<div className="ml-1 text-stone-700 dark:text-stone-200">
|
||||||
{t("dashboard.unit")}
|
{t("dashboard.statistics.unit")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="my-4">
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className="text-muted-foreground mt-5 text-sm">
|
<div className="text-muted-foreground mt-5 text-sm">
|
||||||
{t("deployment.log.name")}
|
{t("dashboard.history")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{deployments?.length == 0 ? (
|
{deployments?.length == 0 ? (
|
||||||
<>
|
<>
|
||||||
<Alert className="max-w-[40em] mt-10">
|
<Alert className="max-w-[40em] mt-10">
|
||||||
<AlertTitle>{t("no.data")}</AlertTitle>
|
<AlertTitle>{t("common.text.nodata")}</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
<div className="flex items-center mt-5">
|
<div className="flex items-center mt-5">
|
||||||
<div>
|
<div>
|
||||||
<Smile className="text-yellow-400" size={36} />
|
<Smile className="text-yellow-400" size={36} />
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-2"> {t("deployment.log.empty")}</div>
|
<div className="ml-2"> {t("history.nodata")}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex justify-end">
|
<div className="mt-2 flex justify-end">
|
||||||
<Button
|
<Button
|
||||||
@ -199,18 +203,15 @@ const Dashboard = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
||||||
<div className="w-48">{t("domain")}</div>
|
<div className="w-48">{t("history.props.domain")}</div>
|
||||||
|
|
||||||
<div className="w-24">{t("deployment.log.status")}</div>
|
<div className="w-24">{t("history.props.status")}</div>
|
||||||
<div className="w-56">{t("deployment.log.stage")}</div>
|
<div className="w-56">{t("history.props.stage")}</div>
|
||||||
<div className="w-56 sm:ml-2 text-center">
|
<div className="w-56 sm:ml-2 text-center">
|
||||||
{t("deployment.log.last.execution.time")}
|
{t("history.props.last_execution_time")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grow">{t("operation")}</div>
|
<div className="grow">{t("common.text.operations")}</div>
|
||||||
</div>
|
|
||||||
<div className="sm:hidden flex text-sm text-muted-foreground">
|
|
||||||
{t("deployment.log.name")}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{deployments?.map((deployment) => (
|
{deployments?.map((deployment) => (
|
||||||
@ -244,14 +245,14 @@ const Dashboard = () => {
|
|||||||
<Sheet>
|
<Sheet>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button variant={"link"} className="p-0">
|
<Button variant={"link"} className="p-0">
|
||||||
{t("deployment.log.detail.button.text")}
|
{t("history.log")}
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="sm:max-w-5xl">
|
<SheetContent className="sm:max-w-5xl">
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>
|
<SheetTitle>
|
||||||
{deployment.expand.domain?.domain}-{deployment.id}
|
{deployment.expand.domain?.domain}-{deployment.id}
|
||||||
{t("deployment.log.detail")}
|
{t("history.log")}
|
||||||
</SheetTitle>
|
</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<div className="bg-gray-950 text-stone-100 p-5 text-sm h-[80dvh]">
|
<div className="bg-gray-950 text-stone-100 p-5 text-sm h-[80dvh]">
|
||||||
|
@ -77,11 +77,11 @@ const Edit = () => {
|
|||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
domain: z.string().min(1, {
|
domain: z.string().min(1, {
|
||||||
message: "domain.not.empty.verify.message",
|
message: "common.errmsg.domain_invalid",
|
||||||
}),
|
}),
|
||||||
email: z.string().email("email.valid.message").optional(),
|
email: z.string().email("common.errmsg.email_invalid").optional(),
|
||||||
access: z.string().regex(/^[a-zA-Z0-9]+$/, {
|
access: z.string().regex(/^[a-zA-Z0-9]+$/, {
|
||||||
message: "domain.management.edit.dns.access.not.empty.message",
|
message: "domain.application.form.access.errmsg.empty",
|
||||||
}),
|
}),
|
||||||
nameservers: z.string().optional(),
|
nameservers: z.string().optional(),
|
||||||
timeout: z.number().optional(),
|
timeout: z.number().optional(),
|
||||||
@ -106,7 +106,6 @@ const Edit = () => {
|
|||||||
domain: domain.domain,
|
domain: domain.domain,
|
||||||
email: domain.applyConfig?.email,
|
email: domain.applyConfig?.email,
|
||||||
access: domain.applyConfig?.access,
|
access: domain.applyConfig?.access,
|
||||||
|
|
||||||
nameservers: domain.applyConfig?.nameservers,
|
nameservers: domain.applyConfig?.nameservers,
|
||||||
timeout: domain.applyConfig?.timeout,
|
timeout: domain.applyConfig?.timeout,
|
||||||
});
|
});
|
||||||
@ -133,13 +132,13 @@ const Edit = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await save(req);
|
const resp = await save(req);
|
||||||
let description = t("domain.management.edit.succeed.tips");
|
let description = t("domain.application.form.domain.changed.message");
|
||||||
if (req.id == "") {
|
if (req.id == "") {
|
||||||
description = t("domain.management.add.succeed.tips");
|
description = t("domain.application.form.domain.added.message");
|
||||||
}
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t("succeed"),
|
title: t("common.save.succeeded.message"),
|
||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -168,13 +167,13 @@ const Edit = () => {
|
|||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const resp = await save(req);
|
const resp = await save(req);
|
||||||
let description = t("domain.management.edit.succeed.tips");
|
let description = t("domain.application.form.domain.changed.message");
|
||||||
if (req.id == "") {
|
if (req.id == "") {
|
||||||
description = t("domain.management.add.succeed.tips");
|
description = t("domain.application.form.domain.added.message");
|
||||||
}
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: t("succeed"),
|
title: t("common.save.succeeded.message"),
|
||||||
description,
|
description,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -205,7 +204,7 @@ const Edit = () => {
|
|||||||
<BreadcrumbList>
|
<BreadcrumbList>
|
||||||
<BreadcrumbItem>
|
<BreadcrumbItem>
|
||||||
<BreadcrumbLink href="#/domains">
|
<BreadcrumbLink href="#/domains">
|
||||||
{t("domain.management.name")}
|
{t("domain.page.title")}
|
||||||
</BreadcrumbLink>
|
</BreadcrumbLink>
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
<BreadcrumbSeparator />
|
<BreadcrumbSeparator />
|
||||||
@ -229,7 +228,7 @@ const Edit = () => {
|
|||||||
setTab("apply");
|
setTab("apply");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("apply.setting")}
|
{t("domain.application.tab")}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -239,8 +238,8 @@ const Edit = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!domain?.id) {
|
if (!domain?.id) {
|
||||||
toast({
|
toast({
|
||||||
title: t("domain.management.edit.deploy.error"),
|
title: t("domain.application.unsaved.message"),
|
||||||
description: t("domain.management.edit.deploy.error"),
|
description: t("domain.application.unsaved.message"),
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@ -248,7 +247,7 @@ const Edit = () => {
|
|||||||
setTab("deploy");
|
setTab("deploy");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("deploy.setting")}
|
{t("domain.deployment.tab")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
@ -278,7 +277,6 @@ const Edit = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@ -291,14 +289,15 @@ const Edit = () => {
|
|||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="flex w-full justify-between">
|
<FormLabel className="flex w-full justify-between">
|
||||||
<div>
|
<div>
|
||||||
{t("email") +
|
{t("domain.application.form.email.label") +
|
||||||
t("domain.management.edit.email.description")}
|
" " +
|
||||||
|
t("domain.application.form.email.tips")}
|
||||||
</div>
|
</div>
|
||||||
<EmailsEdit
|
<EmailsEdit
|
||||||
trigger={
|
trigger={
|
||||||
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
||||||
<Plus size={14} />
|
<Plus size={14} />
|
||||||
{t("add")}
|
{t("common.add")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -314,13 +313,15 @@ const Edit = () => {
|
|||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"domain.management.edit.email.not.empty.message"
|
"domain.application.form.email.errmsg.empty"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>{t("email.list")}</SelectLabel>
|
<SelectLabel>
|
||||||
|
{t("domain.application.form.email.list")}
|
||||||
|
</SelectLabel>
|
||||||
{(emails.content as EmailsSetting).emails.map(
|
{(emails.content as EmailsSetting).emails.map(
|
||||||
(item) => (
|
(item) => (
|
||||||
<SelectItem key={item} value={item}>
|
<SelectItem key={item} value={item}>
|
||||||
@ -344,14 +345,12 @@ const Edit = () => {
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="flex w-full justify-between">
|
<FormLabel className="flex w-full justify-between">
|
||||||
<div>
|
<div>{t("domain.application.form.access.label")}</div>
|
||||||
{t("domain.management.edit.dns.access.label")}
|
|
||||||
</div>
|
|
||||||
<AccessEdit
|
<AccessEdit
|
||||||
trigger={
|
trigger={
|
||||||
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
||||||
<Plus size={14} />
|
<Plus size={14} />
|
||||||
{t("add")}
|
{t("common.add")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
op="add"
|
op="add"
|
||||||
@ -368,14 +367,14 @@ const Edit = () => {
|
|||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue
|
<SelectValue
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"domain.management.edit.access.not.empty.message"
|
"domain.application.form.access.placeholder"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>
|
<SelectLabel>
|
||||||
{t("domain.management.edit.access.label")}
|
{t("domain.application.form.access.list")}
|
||||||
</SelectLabel>
|
</SelectLabel>
|
||||||
{accesses
|
{accesses
|
||||||
.filter((item) => item.usage != "deploy")
|
.filter((item) => item.usage != "deploy")
|
||||||
@ -410,12 +409,14 @@ const Edit = () => {
|
|||||||
name="timeout"
|
name="timeout"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("timeout")}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("domain.application.form.timeout.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"domain.management.edit.timeout.placeholder"
|
"ddomain.application.form.timeout.placeholder"
|
||||||
)}
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
value={field.value}
|
value={field.value}
|
||||||
@ -454,7 +455,7 @@ const Edit = () => {
|
|||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">
|
<Button type="submit">
|
||||||
{domain?.id ? t("save") : t("next")}
|
{domain?.id ? t("common.save") : t("common.next")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -129,15 +129,15 @@ const Home = () => {
|
|||||||
await save(domain);
|
await save(domain);
|
||||||
|
|
||||||
toast.toast({
|
toast.toast({
|
||||||
title: t("operation.succeed"),
|
title: t("domain.deploy.started.message"),
|
||||||
description: t("domain.management.start.deploy.succeed.tips"),
|
description: t("domain.deploy.started.tips"),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.toast({
|
toast.toast({
|
||||||
title: t("domain.management.execution.failed"),
|
title: t("domain.deploy.failed.message"),
|
||||||
description: (
|
description: (
|
||||||
// 这里的 text 只是占位作用,实际文案在 src/i18n/locales/[lang].json
|
// 这里的 text 只是占位作用,实际文案在 src/i18n/locales/[lang].json
|
||||||
<Trans i18nKey="domain.management.execution.failed.tips">
|
<Trans i18nKey="domain.deploy.failed.tips">
|
||||||
text1
|
text1
|
||||||
<Link
|
<Link
|
||||||
to={`/history?domain=${domain.id}`}
|
to={`/history?domain=${domain.id}`}
|
||||||
@ -178,9 +178,7 @@ const Home = () => {
|
|||||||
<div className="">
|
<div className="">
|
||||||
<Toaster />
|
<Toaster />
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">{t("domain.page.title")}</div>
|
||||||
{t("domain.management.name")}
|
|
||||||
</div>
|
|
||||||
<Button onClick={handleCreateClick}>{t("domain.add")}</Button>
|
<Button onClick={handleCreateClick}>{t("domain.add")}</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -192,7 +190,7 @@ const Home = () => {
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="text-center text-sm text-muted-foreground mt-3">
|
<div className="text-center text-sm text-muted-foreground mt-3">
|
||||||
{t("domain.management.empty")}
|
{t("domain.nodata")}
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={handleCreateClick} className="mt-3">
|
<Button onClick={handleCreateClick} className="mt-3">
|
||||||
{t("domain.add")}
|
{t("domain.add")}
|
||||||
@ -202,22 +200,19 @@ const Home = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
||||||
<div className="w-36">{t("domain")}</div>
|
<div className="w-36">{t("common.text.domain")}</div>
|
||||||
<div className="w-40">{t("domain.management.expiry.date")}</div>
|
<div className="w-40">{t("domain.props.expiry")}</div>
|
||||||
<div className="w-32">
|
<div className="w-32">
|
||||||
{t("domain.management.last.execution.status")}
|
{t("domain.props.last_execution_status")}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-64">
|
<div className="w-64">
|
||||||
{t("domain.management.last.execution.stage")}
|
{t("domain.props.last_execution_stage")}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-40 sm:ml-2">
|
<div className="w-40 sm:ml-2">
|
||||||
{t("domain.management.last.execution.time")}
|
{t("domain.props.last_execution_time")}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-24">{t("domain.management.enable")}</div>
|
<div className="w-24">{t("domain.props.enable")}</div>
|
||||||
<div className="grow">{t("operation")}</div>
|
<div className="grow">{t("common.text.operations")}</div>
|
||||||
</div>
|
|
||||||
<div className="sm:hidden flex text-sm text-muted-foreground">
|
|
||||||
{t("domain")}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{domains.map((domain) => (
|
{domains.map((domain) => (
|
||||||
@ -238,10 +233,10 @@ const Home = () => {
|
|||||||
{domain.expiredAt ? (
|
{domain.expiredAt ? (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
{t("domain.management.expiry.date1", { date: 90 })}
|
{t("domain.props.expiry.date1", { date: 90 })}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{t("domain.management.expiry.date2", {
|
{t("domain.props.expiry.date2", {
|
||||||
date: getDate(domain.expiredAt),
|
date: getDate(domain.expiredAt),
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@ -288,7 +283,9 @@ const Home = () => {
|
|||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<div className="border rounded-sm px-3 bg-background text-muted-foreground text-xs">
|
<div className="border rounded-sm px-3 bg-background text-muted-foreground text-xs">
|
||||||
{domain.enabled ? t("disable") : t("enable")}
|
{domain.enabled
|
||||||
|
? t("domain.props.enable.disabled")
|
||||||
|
: t("domain.props.enable.enabled")}
|
||||||
</div>
|
</div>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -300,7 +297,7 @@ const Home = () => {
|
|||||||
className="p-0"
|
className="p-0"
|
||||||
onClick={() => handleHistoryClick(domain.id ?? "")}
|
onClick={() => handleHistoryClick(domain.id ?? "")}
|
||||||
>
|
>
|
||||||
{t("deployment.log.name")}
|
{t("domain.history")}
|
||||||
</Button>
|
</Button>
|
||||||
<Show when={domain.enabled ? true : false}>
|
<Show when={domain.enabled ? true : false}>
|
||||||
<Separator orientation="vertical" className="h-4 mx-2" />
|
<Separator orientation="vertical" className="h-4 mx-2" />
|
||||||
@ -309,7 +306,7 @@ const Home = () => {
|
|||||||
className="p-0"
|
className="p-0"
|
||||||
onClick={() => handleRightNowClick(domain)}
|
onClick={() => handleRightNowClick(domain)}
|
||||||
>
|
>
|
||||||
{t("domain.management.start.deploying")}
|
{t("domain.deploy")}
|
||||||
</Button>
|
</Button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
@ -326,7 +323,7 @@ const Home = () => {
|
|||||||
className="p-0"
|
className="p-0"
|
||||||
onClick={() => handleForceClick(domain)}
|
onClick={() => handleForceClick(domain)}
|
||||||
>
|
>
|
||||||
{t("domain.management.forced.deployment")}
|
{t("domain.deploy_forced")}
|
||||||
</Button>
|
</Button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
@ -337,7 +334,7 @@ const Home = () => {
|
|||||||
className="p-0"
|
className="p-0"
|
||||||
onClick={() => handleDownloadClick(domain)}
|
onClick={() => handleDownloadClick(domain)}
|
||||||
>
|
>
|
||||||
{t("download")}
|
{t("common.download")}
|
||||||
</Button>
|
</Button>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
@ -347,7 +344,7 @@ const Home = () => {
|
|||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button variant={"link"} className="p-0">
|
<Button variant={"link"} className="p-0">
|
||||||
{t("delete")}
|
{t("common.delete")}
|
||||||
</Button>
|
</Button>
|
||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
@ -356,17 +353,19 @@ const Home = () => {
|
|||||||
{t("domain.delete")}
|
{t("domain.delete")}
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
{t("domain.management.delete.confirm")}
|
{t("domain.delete.confirm")}
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel>{t("cancel")}</AlertDialogCancel>
|
<AlertDialogCancel>
|
||||||
|
{t("common.cancel")}
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleDeleteClick(domain.id ?? "");
|
handleDeleteClick(domain.id ?? "");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("confirm")}
|
{t("common.confirm")}
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
@ -378,7 +377,7 @@ const Home = () => {
|
|||||||
className="p-0"
|
className="p-0"
|
||||||
onClick={() => handleEditClick(domain.id ?? "")}
|
onClick={() => handleEditClick(domain.id ?? "")}
|
||||||
>
|
>
|
||||||
{t("edit")}
|
{t("common.edit")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -40,17 +40,17 @@ const History = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollArea className="h-[80vh] overflow-hidden">
|
<ScrollArea className="h-[80vh] overflow-hidden">
|
||||||
<div className="text-muted-foreground">{t("deployment.log.name")}</div>
|
<div className="text-muted-foreground">{t("history.page.title")}</div>
|
||||||
{!deployments?.length ? (
|
{!deployments?.length ? (
|
||||||
<>
|
<>
|
||||||
<Alert className="max-w-[40em] mx-auto mt-20">
|
<Alert className="max-w-[40em] mx-auto mt-20">
|
||||||
<AlertTitle>{t("no.data")}</AlertTitle>
|
<AlertTitle>{t("common.text.nodata")}</AlertTitle>
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
<div className="flex items-center mt-5">
|
<div className="flex items-center mt-5">
|
||||||
<div>
|
<div>
|
||||||
<Smile className="text-yellow-400" size={36} />
|
<Smile className="text-yellow-400" size={36} />
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-2"> {t("deployment.log.empty")}</div>
|
<div className="ml-2"> {t("history.nodata")}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex justify-end">
|
<div className="mt-2 flex justify-end">
|
||||||
<Button
|
<Button
|
||||||
@ -67,18 +67,15 @@ const History = () => {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
<div className="hidden sm:flex sm:flex-row text-muted-foreground text-sm border-b dark:border-stone-500 sm:p-2 mt-5">
|
||||||
<div className="w-48">{t("domain")}</div>
|
<div className="w-48">{t("history.props.domain")}</div>
|
||||||
|
|
||||||
<div className="w-24">{t("deployment.log.status")}</div>
|
<div className="w-24">{t("history.props.status")}</div>
|
||||||
<div className="w-56">{t("deployment.log.stage")}</div>
|
<div className="w-56">{t("history.props.stage")}</div>
|
||||||
<div className="w-56 sm:ml-2 text-center">
|
<div className="w-56 sm:ml-2 text-center">
|
||||||
{t("deployment.log.last.execution.time")}
|
{t("history.props.last_execution_time")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grow">{t("operation")}</div>
|
<div className="grow">{t("common.text.operations")}</div>
|
||||||
</div>
|
|
||||||
<div className="sm:hidden flex text-sm text-muted-foreground">
|
|
||||||
{t("deployment.log.name")}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{deployments?.map((deployment) => (
|
{deployments?.map((deployment) => (
|
||||||
@ -112,14 +109,14 @@ const History = () => {
|
|||||||
<Sheet>
|
<Sheet>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button variant={"link"} className="p-0">
|
<Button variant={"link"} className="p-0">
|
||||||
{t("deployment.log.detail.button.text")}
|
{t("history.log")}
|
||||||
</Button>
|
</Button>
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="sm:max-w-5xl">
|
<SheetContent className="sm:max-w-5xl">
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>
|
<SheetTitle>
|
||||||
{deployment.expand.domain?.domain}-{deployment.id}
|
{deployment.expand.domain?.domain}-{deployment.id}
|
||||||
{t("deployment.log.detail")}
|
{t("history.log")}
|
||||||
</SheetTitle>
|
</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<div className="bg-gray-950 text-stone-100 p-5 text-sm h-[80dvh]">
|
<div className="bg-gray-950 text-stone-100 p-5 text-sm h-[80dvh]">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
@ -19,15 +19,15 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
|||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
username: z.string().email({
|
username: z.string().email({
|
||||||
message: "login.username.no.empty.message",
|
message: "login.username.errmsg.invalid",
|
||||||
}),
|
}),
|
||||||
password: z.string().min(10, {
|
password: z.string().min(10, {
|
||||||
message: "login.password.length.message",
|
message: "login.password.errmsg.invalid",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
@ -65,9 +65,9 @@ const Login = () => {
|
|||||||
name="username"
|
name="username"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('username')}</FormLabel>
|
<FormLabel>{t("login.username.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="email" {...field} />
|
<Input placeholder={t("login.username.placeholder")} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -80,9 +80,9 @@ const Login = () => {
|
|||||||
name="password"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('password')}</FormLabel>
|
<FormLabel>{t("login.password.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="password" {...field} type="password" />
|
<Input placeholder={t("login.password.placeholder")} {...field} type="password" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -90,7 +90,7 @@ const Login = () => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('login.submit')}</Button>
|
<Button type="submit">{t("login.submit")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -20,7 +20,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
email: z.string().email("setting.account.email.valid.message"),
|
email: z.string().email("settings.account.email.errmsg.invalid"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const Account = () => {
|
const Account = () => {
|
||||||
@ -45,8 +45,8 @@ const Account = () => {
|
|||||||
|
|
||||||
getPb().authStore.clear();
|
getPb().authStore.clear();
|
||||||
toast({
|
toast({
|
||||||
title: t("setting.account.email.change.succeed"),
|
title: t("settings.account.email.changed.message"),
|
||||||
description: t("setting.account.log.back.in"),
|
description: t("settings.account.relogin.message"),
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
@ -54,7 +54,7 @@ const Account = () => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
const message = getErrMessage(e);
|
const message = getErrMessage(e);
|
||||||
toast({
|
toast({
|
||||||
title: t("setting.account.email.change.failed"),
|
title: t("settings.account.email.failed.message"),
|
||||||
description: message,
|
description: message,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
@ -74,10 +74,10 @@ const Account = () => {
|
|||||||
name="email"
|
name="email"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('email')}</FormLabel>
|
<FormLabel>{t("settings.account.email.label")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('setting.email.placeholder')}
|
placeholder={t("settings.account.email.placeholder")}
|
||||||
{...field}
|
{...field}
|
||||||
type="email"
|
type="email"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -94,10 +94,10 @@ const Account = () => {
|
|||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
{changed ? (
|
{changed ? (
|
||||||
<Button type="submit">{t('setting.submit')}</Button>
|
<Button type="submit">{t("common.update")}</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button type="submit" disabled variant={"secondary"}>
|
<Button type="submit" disabled variant={"secondary"}>
|
||||||
{t('setting.submit')}
|
{t("common.update")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,7 +20,9 @@ const Notify = () => {
|
|||||||
<div className="border rounded-sm p-5 shadow-lg">
|
<div className="border rounded-sm p-5 shadow-lg">
|
||||||
<Accordion type={"multiple"} className="dark:text-stone-200">
|
<Accordion type={"multiple"} className="dark:text-stone-200">
|
||||||
<AccordionItem value="item-1" className="dark:border-stone-200">
|
<AccordionItem value="item-1" className="dark:border-stone-200">
|
||||||
<AccordionTrigger>{t('template')}</AccordionTrigger>
|
<AccordionTrigger>
|
||||||
|
{t("settings.notification.template.label")}
|
||||||
|
</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<NotifyTemplate />
|
<NotifyTemplate />
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
@ -30,21 +32,21 @@ const Notify = () => {
|
|||||||
<div className="border rounded-md p-5 mt-7 shadow-lg">
|
<div className="border rounded-md p-5 mt-7 shadow-lg">
|
||||||
<Accordion type={"single"} className="dark:text-stone-200">
|
<Accordion type={"single"} className="dark:text-stone-200">
|
||||||
<AccordionItem value="item-2" className="dark:border-stone-200">
|
<AccordionItem value="item-2" className="dark:border-stone-200">
|
||||||
<AccordionTrigger>{t('ding.talk')}</AccordionTrigger>
|
<AccordionTrigger>{t("common.provider.dingtalk")}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<DingTalk />
|
<DingTalk />
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem value="item-4" className="dark:border-stone-200">
|
<AccordionItem value="item-4" className="dark:border-stone-200">
|
||||||
<AccordionTrigger>{t('telegram')}</AccordionTrigger>
|
<AccordionTrigger>{t("common.provider.telegram")}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<Telegram />
|
<Telegram />
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
|
|
||||||
<AccordionItem value="item-5" className="dark:border-stone-200">
|
<AccordionItem value="item-5" className="dark:border-stone-200">
|
||||||
<AccordionTrigger>{t('webhook')}</AccordionTrigger>
|
<AccordionTrigger>{t("common.provider.webhook")}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<Webhook />
|
<Webhook />
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
@ -21,17 +21,17 @@ import { z } from "zod";
|
|||||||
const formSchema = z
|
const formSchema = z
|
||||||
.object({
|
.object({
|
||||||
oldPassword: z.string().min(10, {
|
oldPassword: z.string().min(10, {
|
||||||
message: "setting.password.length.message",
|
message: "settings.password.password.errmsg.length",
|
||||||
}),
|
}),
|
||||||
newPassword: z.string().min(10, {
|
newPassword: z.string().min(10, {
|
||||||
message: "setting.password.length.message",
|
message: "settings.password.password.errmsg.length",
|
||||||
}),
|
}),
|
||||||
confirmPassword: z.string().min(10, {
|
confirmPassword: z.string().min(10, {
|
||||||
message: "setting.password.length.message",
|
message: "settings.password.password.errmsg.length",
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
.refine((data) => data.newPassword === data.confirmPassword, {
|
.refine((data) => data.newPassword === data.confirmPassword, {
|
||||||
message: "setting.password.not.match",
|
message: "settings.password.password.errmsg.not_matched",
|
||||||
path: ["confirmPassword"],
|
path: ["confirmPassword"],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -68,8 +68,8 @@ const Password = () => {
|
|||||||
|
|
||||||
getPb().authStore.clear();
|
getPb().authStore.clear();
|
||||||
toast({
|
toast({
|
||||||
title: t('setting.password.change.succeed'),
|
title: t("settings.password.changed.message"),
|
||||||
description: t("setting.account.log.back.in"),
|
description: t("settings.account.relogin.message"),
|
||||||
});
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
@ -77,7 +77,7 @@ const Password = () => {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
const message = getErrMessage(e);
|
const message = getErrMessage(e);
|
||||||
toast({
|
toast({
|
||||||
title: t('setting.password.change.failed'),
|
title: t("settings.password.failed.message"),
|
||||||
description: message,
|
description: message,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
@ -97,9 +97,17 @@ const Password = () => {
|
|||||||
name="oldPassword"
|
name="oldPassword"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('setting.password.current.password')}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("settings.password.current_password.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder={t('setting.password.current.password')} {...field} type="password" />
|
<Input
|
||||||
|
placeholder={t(
|
||||||
|
"settings.password.current_password.placeholder"
|
||||||
|
)}
|
||||||
|
{...field}
|
||||||
|
type="password"
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@ -112,10 +120,14 @@ const Password = () => {
|
|||||||
name="newPassword"
|
name="newPassword"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('setting.password.new.password')}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("settings.password.new_password.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="newPassword"
|
placeholder={t(
|
||||||
|
"settings.password.new_password.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
@ -131,10 +143,14 @@ const Password = () => {
|
|||||||
name="confirmPassword"
|
name="confirmPassword"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('setting.password.confirm.password')}</FormLabel>
|
<FormLabel>
|
||||||
|
{t("settings.password.confirm_password.label")}
|
||||||
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="confirmPassword"
|
placeholder={t(
|
||||||
|
"settings.password.confirm_password.placeholder"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
@ -145,7 +161,7 @@ const Password = () => {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t('setting.submit')}</Button>
|
<Button type="submit">{t("common.update")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -35,7 +35,7 @@ const SSLProvider = () => {
|
|||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
provider: z.enum(["letsencrypt", "zerossl"], {
|
provider: z.enum(["letsencrypt", "zerossl"], {
|
||||||
message: t("setting.ca.not.empty"),
|
message: t("settings.ca.provider.errmsg.empty"),
|
||||||
}),
|
}),
|
||||||
eabKid: z.string().optional(),
|
eabKid: z.string().optional(),
|
||||||
eabHmacKey: z.string().optional(),
|
eabHmacKey: z.string().optional(),
|
||||||
@ -89,12 +89,12 @@ const SSLProvider = () => {
|
|||||||
if (values.provider === "zerossl") {
|
if (values.provider === "zerossl") {
|
||||||
if (!values.eabKid) {
|
if (!values.eabKid) {
|
||||||
form.setError("eabKid", {
|
form.setError("eabKid", {
|
||||||
message: t("setting.ca.eab_kid_hmac_key.not.empty"),
|
message: t("settings.ca.eab_kid_hmac_key.errmsg.empty"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!values.eabHmacKey) {
|
if (!values.eabHmacKey) {
|
||||||
form.setError("eabHmacKey", {
|
form.setError("eabHmacKey", {
|
||||||
message: t("setting.ca.eab_kid_hmac_key.not.empty"),
|
message: t("settings.ca.eab_kid_hmac_key.errmsg.empty"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!values.eabKid || !values.eabHmacKey) {
|
if (!values.eabKid || !values.eabHmacKey) {
|
||||||
@ -120,13 +120,13 @@ const SSLProvider = () => {
|
|||||||
try {
|
try {
|
||||||
await update(setting);
|
await update(setting);
|
||||||
toast({
|
toast({
|
||||||
title: t("update.succeed"),
|
title: t("common.update.succeeded.message"),
|
||||||
description: t("update.succeed"),
|
description: t("common.update.succeeded.message"),
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const message = getErrMessage(e);
|
const message = getErrMessage(e);
|
||||||
toast({
|
toast({
|
||||||
title: t("update.failed"),
|
title: t("common.update.failed.message"),
|
||||||
description: message,
|
description: message,
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
@ -146,7 +146,7 @@ const SSLProvider = () => {
|
|||||||
name="provider"
|
name="provider"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t("ca")}</FormLabel>
|
<FormLabel>{t("common.text.ca")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
{...field}
|
{...field}
|
||||||
@ -202,7 +202,7 @@ const SSLProvider = () => {
|
|||||||
<FormLabel>EAB_KID</FormLabel>
|
<FormLabel>EAB_KID</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("setting.ca.eab_kid.not.empty")}
|
placeholder={t("settings.ca.eab_kid.errmsg.empty")}
|
||||||
{...field}
|
{...field}
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
@ -221,7 +221,9 @@ const SSLProvider = () => {
|
|||||||
<FormLabel>EAB_HMAC_KEY</FormLabel>
|
<FormLabel>EAB_HMAC_KEY</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t("setting.ca.eab_hmac_key.not.empty")}
|
placeholder={t(
|
||||||
|
"settings.ca.eab_hmac_key.errmsg.empty"
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
@ -238,7 +240,7 @@ const SSLProvider = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">{t("setting.submit")}</Button>
|
<Button type="submit">{t("common.update")}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user