mirror of https://github.com/usual2970/certimate
feat: i18n transformation completed
parent
e820e5599b
commit
0d0fcfccf3
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -29,12 +30,13 @@ const AccessAliyunForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
accessKeyId: z.string().min(1).max(64),
|
accessKeyId: z.string().min(1, 'access.form.access.key.id.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
accessSecretId: z.string().min(1).max(64),
|
accessSecretId: z.string().min(1, 'access.form.access.key.secret.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: AliyunConfig = {
|
let config: AliyunConfig = {
|
||||||
|
@ -47,7 +49,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,
|
||||||
|
@ -111,9 +113,9 @@ const AccessAliyunForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -126,7 +128,7 @@ const AccessAliyunForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -141,7 +143,7 @@ const AccessAliyunForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -156,9 +158,9 @@ const AccessAliyunForm = ({
|
||||||
name="accessKeyId"
|
name="accessKeyId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>AccessKeyId</FormLabel>
|
<FormLabel>{t('access.form.access.key.id')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入AccessKeyId" {...field} />
|
<Input placeholder={t('access.form.access.key.id.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -171,9 +173,9 @@ const AccessAliyunForm = ({
|
||||||
name="accessSecretId"
|
name="accessSecretId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>AccessKeySecret</FormLabel>
|
<FormLabel>{t('access.form.access.key.secret')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入AccessKeySecret" {...field} />
|
<Input placeholder={t('access.form.access.key.secret.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -184,7 +186,7 @@ const AccessAliyunForm = ({
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -28,11 +29,12 @@ const AccessCloudflareForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
dnsApiToken: z.string().min(1).max(64),
|
dnsApiToken: z.string().min(1, 'access.form.cloud.dns.api.token.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: CloudflareConfig = {
|
let config: CloudflareConfig = {
|
||||||
|
@ -44,7 +46,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,
|
||||||
},
|
},
|
||||||
|
@ -106,9 +108,9 @@ const AccessCloudflareForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -121,7 +123,7 @@ const AccessCloudflareForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -136,7 +138,7 @@ const AccessCloudflareForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -151,9 +153,9 @@ const AccessCloudflareForm = ({
|
||||||
name="dnsApiToken"
|
name="dnsApiToken"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>CLOUD_DNS_API_TOKEN</FormLabel>
|
<FormLabel>{t('access.form.cloud.dns.api.token')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入CLOUD_DNS_API_TOKEN" {...field} />
|
<Input placeholder={t('access.form.cloud.dns.api.token.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -162,7 +164,7 @@ const AccessCloudflareForm = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import AccessTencentForm from "./AccessTencentForm";
|
import AccessTencentForm from "./AccessTencentForm";
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ export function AccessEdit({
|
||||||
className,
|
className,
|
||||||
}: TargetConfigEditProps) {
|
}: TargetConfigEditProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const typeKeys = Array.from(accessTypeMap.keys());
|
const typeKeys = Array.from(accessTypeMap.keys());
|
||||||
|
|
||||||
|
@ -146,25 +148,24 @@ export function AccessEdit({
|
||||||
</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>{op == "add" ? "添加" : "编辑"}授权</DialogTitle>
|
<DialogTitle>{op == "add" ? t('access.add') : t('access.edit')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ScrollArea className="max-h-[80vh]">
|
<ScrollArea className="max-h-[80vh]">
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
<Label>服务商</Label>
|
<Label>{t('access.type')}</Label>
|
||||||
|
|
||||||
<Select
|
<Select
|
||||||
onValueChange={(val) => {
|
onValueChange={(val) => {
|
||||||
console.log(val);
|
|
||||||
setConfigType(val);
|
setConfigType(val);
|
||||||
}}
|
}}
|
||||||
defaultValue={configType}
|
defaultValue={configType}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="mt-3">
|
<SelectTrigger className="mt-3">
|
||||||
<SelectValue placeholder="请选择服务商" />
|
<SelectValue placeholder={t('access.type.not.empty')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>服务商</SelectLabel>
|
<SelectLabel>{t('access.type')}</SelectLabel>
|
||||||
{typeKeys.map((key) => (
|
{typeKeys.map((key) => (
|
||||||
<SelectItem value={key} key={key}>
|
<SelectItem value={key} key={key}>
|
||||||
<div
|
<div
|
||||||
|
@ -177,7 +178,7 @@ export function AccessEdit({
|
||||||
src={accessTypeMap.get(key)?.[1]}
|
src={accessTypeMap.get(key)?.[1]}
|
||||||
className="h-6 w-6"
|
className="h-6 w-6"
|
||||||
/>
|
/>
|
||||||
<div>{accessTypeMap.get(key)?.[0]}</div>
|
<div>{t(accessTypeMap.get(key)?.[0] || '')}</div>
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -33,12 +34,13 @@ const AccessGodaddyFrom = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
apiKey: z.string().min(1).max(64),
|
apiKey: z.string().min(1, 'access.form.go.daddy.api.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
apiSecret: z.string().min(1).max(64),
|
apiSecret: z.string().min(1, 'access.form.go.daddy.api.secret.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: GodaddyConfig = {
|
let config: GodaddyConfig = {
|
||||||
|
@ -51,7 +53,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,
|
||||||
|
@ -115,9 +117,9 @@ const AccessGodaddyFrom = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -130,7 +132,7 @@ const AccessGodaddyFrom = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -145,7 +147,7 @@ const AccessGodaddyFrom = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -160,9 +162,9 @@ const AccessGodaddyFrom = ({
|
||||||
name="apiKey"
|
name="apiKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>GODADDY_API_KEY</FormLabel>
|
<FormLabel>{t('access.form.go.daddy.api.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入GODADDY_API_KEY" {...field} />
|
<Input placeholder={t('access.form.go.daddy.api.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -175,9 +177,9 @@ const AccessGodaddyFrom = ({
|
||||||
name="apiSecret"
|
name="apiSecret"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>GODADDY_API_SECRET</FormLabel>
|
<FormLabel>{t('access.form.go.daddy.api.secret')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入GODADDY_API_SECRET" {...field} />
|
<Input placeholder={t('access.form.go.daddy.api.secret.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -186,7 +188,7 @@ const AccessGodaddyFrom = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { update } from "@/repository/access_group";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
import { PbErrorData } from "@/domain/base";
|
import { PbErrorData } from "@/domain/base";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
type AccessGroupEditProps = {
|
type AccessGroupEditProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -35,9 +36,10 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
||||||
const { reloadAccessGroups } = useConfig();
|
const { reloadAccessGroups } = useConfig();
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.group.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
|
@ -78,14 +80,13 @@ 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>添加分组</DialogTitle>
|
<DialogTitle>{t('access.group.add')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
console.log(e);
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
form.handleSubmit(onSubmit)(e);
|
form.handleSubmit(onSubmit)(e);
|
||||||
}}
|
}}
|
||||||
|
@ -96,9 +97,9 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>组名</FormLabel>
|
<FormLabel>{t('access.group.name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入组名" {...field} type="text" />
|
<Input placeholder={t('access.group.name.not.empty')} {...field} type="text" />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -107,7 +108,7 @@ const AccessGroupEdit = ({ className, trigger }: AccessGroupEditProps) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { Group } from "lucide-react";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const AccessGroupList = () => {
|
const AccessGroupList = () => {
|
||||||
const {
|
const {
|
||||||
|
@ -39,8 +40,7 @@ const AccessGroupList = () => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
const handleRemoveClick = async (id: string) => {
|
const handleRemoveClick = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
|
@ -48,7 +48,7 @@ const AccessGroupList = () => {
|
||||||
reloadAccessGroups();
|
reloadAccessGroups();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast({
|
toast({
|
||||||
title: "删除失败",
|
title: t('delete.failed'),
|
||||||
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')}
|
||||||
</div>
|
</div>
|
||||||
<AccessGroupEdit
|
<AccessGroupEdit
|
||||||
trigger={<Button>新增授权组</Button>}
|
trigger={<Button>{t('access.group.add')}</Button>}
|
||||||
className="mt-3"
|
className="mt-3"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -86,9 +86,7 @@ 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 })}
|
||||||
{accessGroup.expand ? accessGroup.expand.access.length : 0}
|
|
||||||
个部署授权配置
|
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="min-h-[180px]">
|
<CardContent className="min-h-[180px]">
|
||||||
|
@ -123,7 +121,7 @@ const AccessGroupList = () => {
|
||||||
<Group size={40} />
|
<Group size={40} />
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-2">
|
<div className="ml-2">
|
||||||
暂无部署授权配置,请添加后开始使用吧
|
{t('access.group.empty')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -151,7 +149,7 @@ const AccessGroupList = () => {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
所有授权
|
{t('access.all')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
@ -159,14 +157,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')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
@ -175,21 +173,21 @@ const AccessGroupList = () => {
|
||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button variant={"destructive"} size={"sm"}>
|
<Button variant={"destructive"} size={"sm"}>
|
||||||
删除
|
{t('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')}
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
确定要删除部署授权组吗?
|
{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')}
|
||||||
</AlertDialogCancel>
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -198,7 +196,7 @@ const AccessGroupList = () => {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
确认
|
{t('confirm')}
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -28,11 +29,12 @@ const AccessNamesiloForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
apiKey: z.string().min(1).max(64),
|
apiKey: z.string().min(1, 'access.form.namesilo.api.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: NamesiloConfig = {
|
let config: NamesiloConfig = {
|
||||||
|
@ -44,14 +46,13 @@ 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
||||||
console.log(data);
|
|
||||||
const req: Access = {
|
const req: Access = {
|
||||||
id: data.id as string,
|
id: data.id as string,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
|
@ -106,9 +107,9 @@ const AccessNamesiloForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -121,7 +122,7 @@ const AccessNamesiloForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -136,7 +137,7 @@ const AccessNamesiloForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -151,9 +152,9 @@ const AccessNamesiloForm = ({
|
||||||
name="apiKey"
|
name="apiKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>NAMESILO_API_KEY</FormLabel>
|
<FormLabel>{t('access.form.namesilo.api.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入NAMESILO_API_KEY" {...field} />
|
<Input placeholder={t('access.form.namesilo.api.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -162,7 +163,7 @@ const AccessNamesiloForm = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -29,12 +30,13 @@ const AccessQiniuForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
accessKey: z.string().min(1).max(64),
|
accessKey: z.string().min(1, 'access.form.access.key.not.empty').max(64),
|
||||||
secretKey: z.string().min(1).max(64),
|
secretKey: z.string().min(1, 'access.form.secret.key.not.empty').max(64),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: QiniuConfig = {
|
let config: QiniuConfig = {
|
||||||
|
@ -47,7 +49,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,
|
||||||
|
@ -111,9 +113,9 @@ const AccessQiniuForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -126,7 +128,7 @@ const AccessQiniuForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -141,7 +143,7 @@ const AccessQiniuForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -156,9 +158,9 @@ const AccessQiniuForm = ({
|
||||||
name="accessKey"
|
name="accessKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>AccessKey</FormLabel>
|
<FormLabel>{t('access.form.access.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入AccessKey" {...field} />
|
<Input placeholder={t('access.form.access.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -171,9 +173,9 @@ const AccessQiniuForm = ({
|
||||||
name="secretKey"
|
name="secretKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>SecretKey</FormLabel>
|
<FormLabel>{t('access.form.secret.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入SecretKey" {...field} />
|
<Input placeholder={t('access.form.secret.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -184,7 +186,7 @@ const AccessQiniuForm = ({
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { ClientResponseError } from "pocketbase";
|
||||||
import { PbErrorData } from "@/domain/base";
|
import { PbErrorData } from "@/domain/base";
|
||||||
import { readFileContent } from "@/lib/file";
|
import { readFileContent } from "@/lib/file";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
@ -53,6 +54,7 @@ const AccessSSHForm = ({
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
const [fileName, setFileName] = useState("");
|
const [fileName, setFileName] = useState("");
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const originGroup = data ? (data.group ? data.group : "") : "";
|
const originGroup = data ? (data.group ? data.group : "") : "";
|
||||||
|
|
||||||
|
@ -62,25 +64,25 @@ const AccessSSHForm = ({
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.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: "请输入正确的域名或IP",
|
message: "zod.rule.ssh.host",
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
group: z.string().optional(),
|
group: z.string().optional(),
|
||||||
port: z.string().min(1).max(5),
|
port: z.string().min(1, 'access.form.ssh.port.not.empty').max(5, t('zod.rule.string.max', { max: 5 })),
|
||||||
username: z.string().min(1).max(64),
|
username: z.string().min(1, 'username.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
password: z.string().min(0).max(64),
|
password: z.string().min(0, 'password.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
key: z.string().min(0).max(20480),
|
key: z.string().min(0, 'access.form.ssh.key.not.empty').max(20480, t('zod.rule.string.max', { max: 20480 })),
|
||||||
keyFile: z.any().optional(),
|
keyFile: z.any().optional(),
|
||||||
command: z.string().min(1).max(2048),
|
command: z.string().min(1, 'access.form.ssh.command.not.empty').max(2048, t('zod.rule.string.max', { max: 2048 })),
|
||||||
certPath: z.string().min(0).max(2048),
|
certPath: z.string().min(0, 'access.form.ssh.cert.path.not.empty').max(2048, t('zod.rule.string.max', { max: 2048 })),
|
||||||
keyPath: z.string().min(0).max(2048),
|
keyPath: z.string().min(0, 'access.form.ssh.key.path.not.empty').max(2048, t('zod.rule.string.max', { max: 2048 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: SSHConfig = {
|
let config: SSHConfig = {
|
||||||
|
@ -100,7 +102,7 @@ const AccessSSHForm = ({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
id: data?.id,
|
id: data?.id,
|
||||||
name: data?.name,
|
name: data?.name || '',
|
||||||
configType: "ssh",
|
configType: "ssh",
|
||||||
group: data?.group,
|
group: data?.group,
|
||||||
host: config.host,
|
host: config.host,
|
||||||
|
@ -219,9 +221,9 @@ const AccessSSHForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -235,12 +237,12 @@ const AccessSSHForm = ({
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel className="w-full flex justify-between">
|
<FormLabel className="w-full flex justify-between">
|
||||||
<div>授权配置组(用于将一个域名证书部署到多个 ssh 主机)</div>
|
<div>{t('access.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')}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -255,7 +257,7 @@ const AccessSSHForm = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="请选择分组" />
|
<SelectValue placeholder={t('access.group.not.empty')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="emptyId">
|
<SelectItem value="emptyId">
|
||||||
|
@ -295,7 +297,7 @@ const AccessSSHForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -310,7 +312,7 @@ const AccessSSHForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -325,9 +327,9 @@ const AccessSSHForm = ({
|
||||||
name="host"
|
name="host"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="grow">
|
<FormItem className="grow">
|
||||||
<FormLabel>服务器HOST</FormLabel>
|
<FormLabel>{t('access.form.ssh.host')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入Host" {...field} />
|
<Input placeholder={t('access.form.ssh.host.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -340,10 +342,10 @@ const AccessSSHForm = ({
|
||||||
name="port"
|
name="port"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>SSH端口</FormLabel>
|
<FormLabel>{t('access.form.ssh.port')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入Port"
|
placeholder={t('access.form.ssh.port.not.empty')}
|
||||||
{...field}
|
{...field}
|
||||||
type="number"
|
type="number"
|
||||||
/>
|
/>
|
||||||
|
@ -360,9 +362,9 @@ const AccessSSHForm = ({
|
||||||
name="username"
|
name="username"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>用户名</FormLabel>
|
<FormLabel>{t('username')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入用户名" {...field} />
|
<Input placeholder={t('username.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -375,10 +377,10 @@ const AccessSSHForm = ({
|
||||||
name="password"
|
name="password"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>密码</FormLabel>
|
<FormLabel>{t('password')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入密码"
|
placeholder={t('password.not.empty')}
|
||||||
{...field}
|
{...field}
|
||||||
type="password"
|
type="password"
|
||||||
/>
|
/>
|
||||||
|
@ -394,9 +396,9 @@ const AccessSSHForm = ({
|
||||||
name="key"
|
name="key"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem hidden>
|
<FormItem hidden>
|
||||||
<FormLabel>Key(使用证书登录)</FormLabel>
|
<FormLabel>{t('access.form.ssh.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入Key" {...field} />
|
<Input placeholder={t('access.form.ssh.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -409,7 +411,7 @@ const AccessSSHForm = ({
|
||||||
name="keyFile"
|
name="keyFile"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Key(使用证书登录)</FormLabel>
|
<FormLabel>{t('access.form.ssh.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
|
@ -419,10 +421,10 @@ const AccessSSHForm = ({
|
||||||
className="w-48"
|
className="w-48"
|
||||||
onClick={handleSelectFileClick}
|
onClick={handleSelectFileClick}
|
||||||
>
|
>
|
||||||
{fileName ? fileName : "请选择文件"}
|
{fileName ? fileName : t('access.form.ssh.key.file.not.empty')}
|
||||||
</Button>
|
</Button>
|
||||||
<Input
|
<Input
|
||||||
placeholder="请输入Key"
|
placeholder={t('access.form.ssh.key.not.empty')}
|
||||||
{...field}
|
{...field}
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
className="hidden"
|
className="hidden"
|
||||||
|
@ -443,9 +445,9 @@ const AccessSSHForm = ({
|
||||||
name="certPath"
|
name="certPath"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>证书上传路径</FormLabel>
|
<FormLabel>{t('access.form.ssh.cert.path')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入证书上传路径" {...field} />
|
<Input placeholder={t('access.form.ssh.cert.path.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -458,9 +460,9 @@ const AccessSSHForm = ({
|
||||||
name="keyPath"
|
name="keyPath"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>私钥上传路径</FormLabel>
|
<FormLabel>{t('access.form.ssh.key.path')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入私钥上传路径" {...field} />
|
<Input placeholder={t('access.form.ssh.key.path.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -473,9 +475,9 @@ const AccessSSHForm = ({
|
||||||
name="command"
|
name="command"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Command</FormLabel>
|
<FormLabel>{t('access.form.ssh.command')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea placeholder="请输入要执行的命令" {...field} />
|
<Textarea placeholder={t('access.form.ssh.command.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -486,7 +488,7 @@ const AccessSSHForm = ({
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -28,12 +29,13 @@ const AccessTencentForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
secretId: z.string().min(1).max(64),
|
secretId: z.string().min(1, 'access.form.secret.id.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
secretKey: z.string().min(1).max(64),
|
secretKey: z.string().min(1, 'access.form.secret.key.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: TencentConfig = {
|
let config: TencentConfig = {
|
||||||
|
@ -46,7 +48,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,
|
||||||
|
@ -108,9 +110,9 @@ const AccessTencentForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -123,7 +125,7 @@ const AccessTencentForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -138,7 +140,7 @@ const AccessTencentForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -153,9 +155,9 @@ const AccessTencentForm = ({
|
||||||
name="secretId"
|
name="secretId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>SecretId</FormLabel>
|
<FormLabel>{t('access.form.secret.id')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入SecretId" {...field} />
|
<Input placeholder={t('access.form.secret.id.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -168,9 +170,9 @@ const AccessTencentForm = ({
|
||||||
name="secretKey"
|
name="secretKey"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>SecretKey</FormLabel>
|
<FormLabel>{t('access.form.secret.key')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入SecretKey" {...field} />
|
<Input placeholder={t('access.form.secret.key.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -179,7 +181,7 @@ const AccessTencentForm = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
|
@ -28,11 +29,12 @@ const WebhookForm = ({
|
||||||
onAfterReq: () => void;
|
onAfterReq: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { addAccess, updateAccess } = useConfig();
|
const { addAccess, updateAccess } = useConfig();
|
||||||
|
const { t } = useTranslation();
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
id: z.string().optional(),
|
id: z.string().optional(),
|
||||||
name: z.string().min(1).max(64),
|
name: z.string().min(1, 'access.form.name.not.empty').max(64, t('zod.rule.string.max', { max: 64 })),
|
||||||
configType: accessFormType,
|
configType: accessFormType,
|
||||||
url: z.string().url(),
|
url: z.string().url('zod.rule.url'),
|
||||||
});
|
});
|
||||||
|
|
||||||
let config: WebhookConfig = {
|
let config: WebhookConfig = {
|
||||||
|
@ -44,14 +46,13 @@ 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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
const onSubmit = async (data: z.infer<typeof formSchema>) => {
|
||||||
console.log(data);
|
|
||||||
const req: Access = {
|
const req: Access = {
|
||||||
id: data.id as string,
|
id: data.id as string,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
|
@ -106,9 +107,9 @@ const WebhookForm = ({
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>名称</FormLabel>
|
<FormLabel>{t('name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入授权名称" {...field} />
|
<Input placeholder={t('access.form.name.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -121,7 +122,7 @@ const WebhookForm = ({
|
||||||
name="id"
|
name="id"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -136,7 +137,7 @@ const WebhookForm = ({
|
||||||
name="configType"
|
name="configType"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="hidden">
|
<FormItem className="hidden">
|
||||||
<FormLabel>配置类型</FormLabel>
|
<FormLabel>{t('access.form.config.field')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
@ -151,9 +152,9 @@ const WebhookForm = ({
|
||||||
name="url"
|
name="url"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Webhook Url</FormLabel>
|
<FormLabel>{t('access.form.webhook.url')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input placeholder="请输入Webhook Url" {...field} />
|
<Input placeholder={t('access.form.webhook.url.not.empty')} {...field} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
|
@ -162,7 +163,7 @@ const WebhookForm = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button type="submit">保存</Button>
|
<Button type="submit">{t('save')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -102,7 +102,7 @@ const DingTalk = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
placeholder="加签的签名"
|
placeholder={t('access.form.ding.access.token.placeholder')}
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
value={dingtalk.data.secret}
|
value={dingtalk.data.secret}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
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([
|
||||||
["tencent", ["腾讯云", "/imgs/providers/tencent.svg"]],
|
["tencent", ["tencent", "/imgs/providers/tencent.svg"]],
|
||||||
["aliyun", ["阿里云", "/imgs/providers/aliyun.svg"]],
|
["aliyun", ["aliyun", "/imgs/providers/aliyun.svg"]],
|
||||||
["cloudflare", ["Cloudflare", "/imgs/providers/cloudflare.svg"]],
|
["cloudflare", ["cloudflare", "/imgs/providers/cloudflare.svg"]],
|
||||||
["namesilo", ["Namesilo", "/imgs/providers/namesilo.svg"]],
|
["namesilo", ["namesilo", "/imgs/providers/namesilo.svg"]],
|
||||||
["godaddy", ["GoDaddy", "/imgs/providers/godaddy.svg"]],
|
["godaddy", ["go.daddy", "/imgs/providers/godaddy.svg"]],
|
||||||
["qiniu", ["七牛云", "/imgs/providers/qiniu.svg"]],
|
["qiniu", ["qiniu", "/imgs/providers/qiniu.svg"]],
|
||||||
["ssh", ["SSH部署", "/imgs/providers/ssh.svg"]],
|
["ssh", ["ssh", "/imgs/providers/ssh.svg"]],
|
||||||
["webhook", ["Webhook", "/imgs/providers/webhook.svg"]],
|
["webhook", ["webhook", "/imgs/providers/webhook.svg"]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const getProviderInfo = (t: string) => {
|
export const getProviderInfo = (t: string) => {
|
||||||
|
@ -26,7 +26,7 @@ export const accessFormType = z.union(
|
||||||
z.literal("namesilo"),
|
z.literal("namesilo"),
|
||||||
z.literal("godaddy"),
|
z.literal("godaddy"),
|
||||||
],
|
],
|
||||||
{ message: "请选择云服务商" }
|
{ message: "access.not.empty" }
|
||||||
);
|
);
|
||||||
|
|
||||||
type AccessUsage = "apply" | "deploy" | "all";
|
type AccessUsage = "apply" | "deploy" | "all";
|
||||||
|
|
|
@ -40,13 +40,13 @@ 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", ["阿里云-CDN", "/imgs/providers/aliyun.svg"]],
|
["aliyun-cdn", ["aliyun.cdn", "/imgs/providers/aliyun.svg"]],
|
||||||
["aliyun-oss", ["阿里云-OSS", "/imgs/providers/aliyun.svg"]],
|
["aliyun-oss", ["aliyun.oss", "/imgs/providers/aliyun.svg"]],
|
||||||
["aliyun-dcdn", ["阿里云-DCDN", "/imgs/providers/aliyun.svg"]],
|
["aliyun-dcdn", ["aliyun.dcdn", "/imgs/providers/aliyun.svg"]],
|
||||||
["tencent-cdn", ["腾讯云-CDN", "/imgs/providers/tencent.svg"]],
|
["tencent-cdn", ["tencent.cdn", "/imgs/providers/tencent.svg"]],
|
||||||
["ssh", ["SSH部署", "/imgs/providers/ssh.svg"]],
|
["ssh", ["ssh", "/imgs/providers/ssh.svg"]],
|
||||||
["qiniu-cdn", ["七牛云-CDN", "/imgs/providers/qiniu.svg"]],
|
["qiniu-cdn", ["qiniu.cdn", "/imgs/providers/qiniu.svg"]],
|
||||||
["webhook", ["Webhook", "/imgs/providers/webhook.svg"]],
|
["webhook", ["webhook", "/imgs/providers/webhook.svg"]],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const targetTypeKeys = Array.from(targetTypeMap.keys());
|
export const targetTypeKeys = Array.from(targetTypeMap.keys());
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
"username": "username",
|
"username": "username",
|
||||||
|
"username.not.empty": "username.not.empty",
|
||||||
"password": "password",
|
"password": "password",
|
||||||
|
"password.not.empty": "password.not.empty",
|
||||||
"email": "email",
|
"email": "email",
|
||||||
"logout": "logout",
|
"logout": "logout",
|
||||||
"setting": "setting",
|
"setting": "setting",
|
||||||
|
@ -21,11 +23,37 @@
|
||||||
"succeed": "succeed",
|
"succeed": "succeed",
|
||||||
"add": "add",
|
"add": "add",
|
||||||
"document": "document",
|
"document": "document",
|
||||||
|
"variables": "variables",
|
||||||
|
"dns": "dns",
|
||||||
|
"name": "name",
|
||||||
|
"create.time": "create.time",
|
||||||
|
"update.time": "update.time",
|
||||||
|
"created.in": "created.in",
|
||||||
|
"updated.in": "updated.in",
|
||||||
"basic.setting": "basic.setting",
|
"basic.setting": "basic.setting",
|
||||||
"advanced.setting": "advanced.setting",
|
"advanced.setting": "advanced.setting",
|
||||||
"operation.succeed": "operation.succeed",
|
"operation.succeed": "operation.succeed",
|
||||||
"save.succeed": "save.succeed",
|
"save.succeed": "save.succeed",
|
||||||
"save.failed": "save.failed",
|
"save.failed": "save.failed",
|
||||||
|
"delete.failed": "delete.failed",
|
||||||
|
"ding.talk": "ding.talk",
|
||||||
|
"telegram": "telegram",
|
||||||
|
"webhook": "webhook",
|
||||||
|
"tencent": "tencent",
|
||||||
|
"tencent.cdn": "tencent.cdn",
|
||||||
|
"aliyun": "aliyun",
|
||||||
|
"aliyun.cdn": "aliyun.cdn",
|
||||||
|
"aliyun.oss": "aliyun.oss",
|
||||||
|
"aliyun.dcdn": "aliyun.dcdn",
|
||||||
|
"qiniu": "qiniu",
|
||||||
|
"qiniu.cdn": "qiniu.cdn",
|
||||||
|
"cloudflare": "cloudflare",
|
||||||
|
"namesilo": "namesilo",
|
||||||
|
"go.daddy": "go.daddy",
|
||||||
|
"ssh": "ssh",
|
||||||
|
"zod.rule.string.max": "zod.rule.string.max",
|
||||||
|
"zod.rule.url": "zod.rule.url",
|
||||||
|
"zod.rule.ssh.host": "zod.rule.ssh.host",
|
||||||
"login.submit": "login.submit",
|
"login.submit": "login.submit",
|
||||||
"login.username.no.empty.message": "login.username.no.empty.message",
|
"login.username.no.empty.message": "login.username.no.empty.message",
|
||||||
"login.password.length.message": "login.password.length.message",
|
"login.password.length.message": "login.password.length.message",
|
||||||
|
@ -68,13 +96,23 @@
|
||||||
"domain.management.forced.deployment": "domain.management.forced.deployment",
|
"domain.management.forced.deployment": "domain.management.forced.deployment",
|
||||||
"domain.management.delete.confirm": "domain.management.delete.confirm",
|
"domain.management.delete.confirm": "domain.management.delete.confirm",
|
||||||
"domain.management.edit.title": "domain.management.edit.title",
|
"domain.management.edit.title": "domain.management.edit.title",
|
||||||
"domain.management.edit.dns.label": "domain.management.edit.dns.label",
|
"domain.management.edit.dns.access.label": "domain.management.edit.dns.access.label",
|
||||||
"domain.management.edit.dns.verify.tips": "domain.management.edit.dns.verify.tips",
|
"domain.management.edit.dns.access.not.empty.message": "domain.management.edit.dns.access.not.empty.message",
|
||||||
"domain.management.edit.target.type.verify.tips": "domain.management.edit.target.type.verify.tips",
|
"domain.management.edit.access.label": "domain.management.edit.access.label",
|
||||||
|
"domain.management.edit.access.not.empty.message": "domain.management.edit.access.not.empty.message",
|
||||||
|
"domain.management.edit.target.type": "domain.management.edit.target.type",
|
||||||
|
"domain.management.edit.target.type.not.empty.message": "domain.management.edit.target.type.not.empty.message",
|
||||||
"domain.management.edit.succeed.tips": "domain.management.edit.succeed.tips",
|
"domain.management.edit.succeed.tips": "domain.management.edit.succeed.tips",
|
||||||
|
"domain.management.edit.target.access": "domain.management.edit.target.access",
|
||||||
|
"domain.management.edit.target.access.content.label": "domain.management.edit.target.access.content.label",
|
||||||
|
"domain.management.edit.target.access.not.empty.message": "domain.management.edit.target.access.not.empty.message",
|
||||||
"domain.management.edit.target.access.verify.msg": "domain.management.edit.target.access.verify.msg",
|
"domain.management.edit.target.access.verify.msg": "domain.management.edit.target.access.verify.msg",
|
||||||
|
"domain.management.edit.group.label": "domain.management.edit.group.label",
|
||||||
|
"domain.management.edit.group.not.empty.message": "domain.management.edit.group.not.empty.message",
|
||||||
"domain.management.edit.email.not.empty.message": "domain.management.edit.email.not.empty.message",
|
"domain.management.edit.email.not.empty.message": "domain.management.edit.email.not.empty.message",
|
||||||
"domain.management.edit.email.description": "domain.management.edit.email.description",
|
"domain.management.edit.email.description": "domain.management.edit.email.description",
|
||||||
|
"domain.management.edit.variables.placeholder": "domain.management.edit.variables.placeholder",
|
||||||
|
"domain.management.edit.dns.placeholder": "domain.management.edit.dns.placeholder",
|
||||||
"domain.management.add.succeed.tips": "domain.management.add.succeed.tips",
|
"domain.management.add.succeed.tips": "domain.management.add.succeed.tips",
|
||||||
"email.add": "email.add",
|
"email.add": "email.add",
|
||||||
"email.list": "email.list",
|
"email.list": "email.list",
|
||||||
|
@ -104,5 +142,61 @@
|
||||||
"setting.notify.config.save.failed.url.not.valid": "setting.notify.config.save.failed.url.not.valid",
|
"setting.notify.config.save.failed.url.not.valid": "setting.notify.config.save.failed.url.not.valid",
|
||||||
"deploy.progress.check": "deploy.progress.check",
|
"deploy.progress.check": "deploy.progress.check",
|
||||||
"deploy.progress.apply": "deploy.progress.apply",
|
"deploy.progress.apply": "deploy.progress.apply",
|
||||||
"deploy.progress.deploy": "deploy.progress.deploy"
|
"deploy.progress.deploy": "deploy.progress.deploy",
|
||||||
|
"access.management": "access.management",
|
||||||
|
"access.add": "access.add",
|
||||||
|
"access.edit": "access.edit",
|
||||||
|
"access.all": "access.all",
|
||||||
|
"access.list": "access.list",
|
||||||
|
"access.type": "access.type",
|
||||||
|
"access.type.not.empty": "access.type.not.empty",
|
||||||
|
"access.not.empty": "access.not.empty",
|
||||||
|
"access.empty": "access.empty",
|
||||||
|
"access.group.management": "access.group.management",
|
||||||
|
"access.group.add": "access.group.add",
|
||||||
|
"access.group.not.empty": "access.group.not.empty",
|
||||||
|
"access.group.name": "access.group.name",
|
||||||
|
"access.group.name.not.empty": "access.group.name.not.empty",
|
||||||
|
"access.group.delete": "access.group.delete",
|
||||||
|
"access.group.delete.confirm": "access.group.delete.confirm",
|
||||||
|
"access.group.domain.empty": "access.group.domain.empty",
|
||||||
|
"access.group.empty": "access.group.empty",
|
||||||
|
"access.group.total": "access.group.total",
|
||||||
|
"access.form.name.not.empty": "access.form.name.not.empty",
|
||||||
|
"access.form.config.field": "access.form.config.field",
|
||||||
|
"access.form.access.key.id": "access.form.access.key.id",
|
||||||
|
"access.form.access.key.id.not.empty": "access.form.access.key.id.not.empty",
|
||||||
|
"access.form.access.key.secret": "access.form.access.key.secret",
|
||||||
|
"access.form.access.key.secret.not.empty": "access.form.access.key.secret.not.empty",
|
||||||
|
"access.form.cloud.dns.api.token": "access.form.cloud.dns.api.token",
|
||||||
|
"access.form.cloud.dns.api.token.not.empty": "access.form.cloud.dns.api.token.not.empty",
|
||||||
|
"access.form.go.daddy.api.key": "access.form.go.daddy.api.key",
|
||||||
|
"access.form.go.daddy.api.key.not.empty": "access.form.go.daddy.api.key.not.empty",
|
||||||
|
"access.form.go.daddy.api.secret": "access.form.go.daddy.api.secret",
|
||||||
|
"access.form.go.daddy.api.secret.not.empty": "access.form.go.daddy.api.secret.not.empty",
|
||||||
|
"access.form.namesilo.api.key": "access.form.namesilo.api.key",
|
||||||
|
"access.form.namesilo.api.key.not.empty": "access.form.namesilo.api.key.not.empty",
|
||||||
|
"access.form.secret.id": "access.form.secret.id",
|
||||||
|
"access.form.secret.id.not.empty": "access.form.secret.id.not.empty",
|
||||||
|
"access.form.secret.key": "access.form.secret.key",
|
||||||
|
"access.form.secret.key.not.empty": "access.form.secret.key.not.empty",
|
||||||
|
"access.form.access.key": "access.form.access.key",
|
||||||
|
"access.form.access.key.not.empty": "access.form.access.key.not.empty",
|
||||||
|
"access.form.webhook.url": "access.form.webhook.url",
|
||||||
|
"access.form.webhook.url.not.empty": "access.form.webhook.url.not.empty",
|
||||||
|
"access.form.ssh.group.label": "access.form.ssh.group.label",
|
||||||
|
"access.form.ssh.host": "access.form.ssh.host",
|
||||||
|
"access.form.ssh.host.not.empty": "access.form.ssh.host.not.empty",
|
||||||
|
"access.form.ssh.port": "access.form.ssh.port",
|
||||||
|
"access.form.ssh.port.not.empty": "access.form.ssh.port.not.empty",
|
||||||
|
"access.form.ssh.key": "access.form.ssh.key",
|
||||||
|
"access.form.ssh.key.not.empty": "access.form.ssh.key.not.empty",
|
||||||
|
"access.form.ssh.key.file.not.empty": "access.form.ssh.key.file.not.empty",
|
||||||
|
"access.form.ssh.cert.path": "access.form.ssh.cert.path",
|
||||||
|
"access.form.ssh.cert.path.not.empty": "access.form.ssh.cert.path.not.empty",
|
||||||
|
"access.form.ssh.key.path": "access.form.ssh.key.path",
|
||||||
|
"access.form.ssh.key.path.not.empty": "access.form.ssh.key.path.not.empty",
|
||||||
|
"access.form.ssh.command": "access.form.ssh.command",
|
||||||
|
"access.form.ssh.command.not.empty": "access.form.ssh.command.not.empty",
|
||||||
|
"access.form.ding.access.token.placeholder": "access.form.ding.access.token.placeholder"
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
"username": "用户名",
|
"username": "用户名",
|
||||||
|
"username.not.empty": "请输入用户名",
|
||||||
"password": "密码",
|
"password": "密码",
|
||||||
|
"password.not.empty": "请输入密码",
|
||||||
"email": "邮箱",
|
"email": "邮箱",
|
||||||
"logout": "退出登录",
|
"logout": "退出登录",
|
||||||
"setting": "设置",
|
"setting": "设置",
|
||||||
|
@ -33,6 +35,25 @@
|
||||||
"operation.succeed": "操作成功",
|
"operation.succeed": "操作成功",
|
||||||
"save.succeed": "保存成功",
|
"save.succeed": "保存成功",
|
||||||
"save.failed": "保存失败",
|
"save.failed": "保存失败",
|
||||||
|
"delete.failed": "删除失败",
|
||||||
|
"ding.talk": "钉钉",
|
||||||
|
"telegram": "Telegram",
|
||||||
|
"webhook": "Webhook",
|
||||||
|
"tencent": "腾讯云",
|
||||||
|
"tencent.cdn": "腾讯云-CDN",
|
||||||
|
"aliyun": "阿里云",
|
||||||
|
"aliyun.cdn": "阿里云-CDN",
|
||||||
|
"aliyun.oss": "阿里云-OSS",
|
||||||
|
"aliyun.dcdn": "阿里云-DCDN",
|
||||||
|
"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.submit": "登录",
|
||||||
"login.username.no.empty.message": "请输入正确的邮箱地址",
|
"login.username.no.empty.message": "请输入正确的邮箱地址",
|
||||||
"login.password.length.message": "密码至少10个字符",
|
"login.password.length.message": "密码至少10个字符",
|
||||||
|
@ -124,9 +145,58 @@
|
||||||
"deploy.progress.deploy": "部署",
|
"deploy.progress.deploy": "部署",
|
||||||
"access.management": "授权管理",
|
"access.management": "授权管理",
|
||||||
"access.add": "添加授权",
|
"access.add": "添加授权",
|
||||||
|
"access.edit": "编辑授权",
|
||||||
|
"access.all": "所有授权",
|
||||||
"access.list": "授权列表",
|
"access.list": "授权列表",
|
||||||
"access.type": "服务商",
|
"access.type": "服务商",
|
||||||
|
"access.type.not.empty": "请选择服务商",
|
||||||
|
"access.not.empty": "请选择云服务商",
|
||||||
"access.empty": "请添加授权开始部署证书吧。",
|
"access.empty": "请添加授权开始部署证书吧。",
|
||||||
"access.group.management": "授权组管理",
|
"access.group.management": "授权组管理",
|
||||||
"access.group.add": "添加授权组"
|
"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.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.command": "Command",
|
||||||
|
"access.form.ssh.command.not.empty": "请输入要执行的命令",
|
||||||
|
"access.form.ding.access.token.placeholder": "加签的签名"
|
||||||
}
|
}
|
|
@ -125,7 +125,7 @@ const Access = () => {
|
||||||
src={accessTypeMap.get(access.configType)?.[1]}
|
src={accessTypeMap.get(access.configType)?.[1]}
|
||||||
className="w-6"
|
className="w-6"
|
||||||
/>
|
/>
|
||||||
<div>{accessTypeMap.get(access.configType)?.[0]}</div>
|
<div>{t(accessTypeMap.get(access.configType)?.[0] || '')}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="sm:w-52 w-full pt-1 sm:pt-0 flex items-center">
|
<div className="sm:w-52 w-full pt-1 sm:pt-0 flex items-center">
|
||||||
|
|
|
@ -373,7 +373,7 @@ const Edit = () => {
|
||||||
className="w-6"
|
className="w-6"
|
||||||
src={targetTypeMap.get(key)?.[1]}
|
src={targetTypeMap.get(key)?.[1]}
|
||||||
/>
|
/>
|
||||||
<div>{targetTypeMap.get(key)?.[0]}</div>
|
<div>{t(targetTypeMap.get(key)?.[0] || '')}</div>
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -30,21 +30,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>钉钉</AccordionTrigger>
|
<AccordionTrigger>{t('ding.talk')}</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>Telegram</AccordionTrigger>
|
<AccordionTrigger>{t('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>Webhook</AccordionTrigger>
|
<AccordionTrigger>{t('webhook')}</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
<Webhook />
|
<Webhook />
|
||||||
</AccordionContent>
|
</AccordionContent>
|
||||||
|
|
Loading…
Reference in New Issue