Merge branch 'main' into feat-ssh-jumpserver

This commit is contained in:
RHQYZ
2025-05-20 21:42:38 +08:00
committed by GitHub
163 changed files with 5497 additions and 945 deletions

View File

@@ -12,6 +12,7 @@ import { ACCESS_PROVIDERS, ACCESS_USAGES, type AccessProvider } from "@/domain/p
import { useAntdForm, useAntdFormName } from "@/hooks";
import AccessForm1PanelConfig from "./AccessForm1PanelConfig";
import AccessFormACMECAConfig from "./AccessFormACMECAConfig";
import AccessFormACMEHttpReqConfig from "./AccessFormACMEHttpReqConfig";
import AccessFormAliyunConfig from "./AccessFormAliyunConfig";
import AccessFormAWSConfig from "./AccessFormAWSConfig";
@@ -19,6 +20,7 @@ import AccessFormAzureConfig from "./AccessFormAzureConfig";
import AccessFormBaiduCloudConfig from "./AccessFormBaiduCloudConfig";
import AccessFormBaishanConfig from "./AccessFormBaishanConfig";
import AccessFormBaotaPanelConfig from "./AccessFormBaotaPanelConfig";
import AccessFormBaotaWAFConfig from "./AccessFormBaotaWAFConfig";
import AccessFormBunnyConfig from "./AccessFormBunnyConfig";
import AccessFormBytePlusConfig from "./AccessFormBytePlusConfig";
import AccessFormCacheFlyConfig from "./AccessFormCacheFlyConfig";
@@ -33,6 +35,7 @@ import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig";
import AccessFormDynv6Config from "./AccessFormDynv6Config";
import AccessFormEdgioConfig from "./AccessFormEdgioConfig";
import AccessFormEmailConfig from "./AccessFormEmailConfig";
import AccessFormFlexCDNConfig from "./AccessFormFlexCDNConfig";
import AccessFormGcoreConfig from "./AccessFormGcoreConfig";
import AccessFormGnameConfig from "./AccessFormGnameConfig";
import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig";
@@ -42,6 +45,7 @@ import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig";
import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig";
import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig";
import AccessFormLarkBotConfig from "./AccessFormLarkBotConfig";
import AccessFormLeCDNConfig from "./AccessFormLeCDNConfig";
import AccessFormMattermostConfig from "./AccessFormMattermostConfig";
import AccessFormNamecheapConfig from "./AccessFormNamecheapConfig";
import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig";
@@ -54,6 +58,7 @@ import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig";
import AccessFormProxmoxVEConfig from "./AccessFormProxmoxVEConfig";
import AccessFormQiniuConfig from "./AccessFormQiniuConfig";
import AccessFormRainYunConfig from "./AccessFormRainYunConfig";
import AccessFormRatPanelConfig from "./AccessFormRatPanelConfig";
import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig";
import AccessFormSSHConfig from "./AccessFormSSHConfig";
import AccessFormSSLComConfig from "./AccessFormSSLComConfig";
@@ -176,6 +181,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
switch (fieldProvider) {
case ACCESS_PROVIDERS["1PANEL"]:
return <AccessForm1PanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ACMECA:
return <AccessFormACMECAConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ACMEHTTPREQ:
return <AccessFormACMEHttpReqConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.ALIYUN:
@@ -190,6 +197,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormBaishanConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAOTAPANEL:
return <AccessFormBaotaPanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAOTAWAF:
return <AccessFormBaotaWAFConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BUNNY:
return <AccessFormBunnyConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BYTEPLUS:
@@ -214,6 +223,12 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormDogeCloudConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.DYNV6:
return <AccessFormDynv6Config {...nestedFormProps} />;
case ACCESS_PROVIDERS.EDGIO:
return <AccessFormEdgioConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EMAIL:
return <AccessFormEmailConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.FLEXCDN:
return <AccessFormFlexCDNConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GCORE:
return <AccessFormGcoreConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GNAME:
@@ -224,10 +239,6 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormGoEdgeConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.GOOGLETRUSTSERVICES:
return <AccessFormGoogleTrustServicesConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EDGIO:
return <AccessFormEdgioConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.EMAIL:
return <AccessFormEmailConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.HUAWEICLOUD:
return <AccessFormHuaweiCloudConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.JDCLOUD:
@@ -236,6 +247,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormKubernetesConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.LARKBOT:
return <AccessFormLarkBotConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.LECDN:
return <AccessFormLeCDNConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.MATTERMOST:
return <AccessFormMattermostConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.NAMECHEAP:
@@ -260,6 +273,8 @@ const AccessForm = forwardRef<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormQiniuConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.RAINYUN:
return <AccessFormRainYunConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.RATPANEL:
return <AccessFormRatPanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SAFELINE:
return <AccessFormSafeLineConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.SSH:

View File

@@ -1,5 +1,5 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { Form, type FormInstance, Input, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
@@ -18,6 +18,7 @@ export type AccessForm1PanelConfigProps = {
const initFormModel = (): AccessForm1PanelConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:20410/",
apiVersion: "v1",
apiKey: "",
};
};
@@ -27,6 +28,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiVersion: z.string().nonempty(t("access.form.1panel_api_version.placeholder")),
apiKey: z
.string()
.min(1, t("access.form.1panel_api_key.placeholder"))
@@ -53,6 +55,10 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal
<Input placeholder={t("access.form.1panel_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiVersion" label={t("access.form.1panel_api_version.label")} rules={[formRule]}>
<Select options={["v1", "v2"].map((s) => ({ label: s, value: s }))} placeholder={t("access.form.1panel_api_version.placeholder")} />
</Form.Item>
<Form.Item
name="apiKey"
label={t("access.form.1panel_api_key.label")}

View File

@@ -0,0 +1,77 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForACMECA } from "@/domain/access";
type AccessFormACMECAConfigFieldValues = Nullish<AccessConfigForACMECA>;
export type AccessFormACMECAConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormACMECAConfigFieldValues;
onValuesChange?: (values: AccessFormACMECAConfigFieldValues) => void;
};
const initFormModel = (): AccessFormACMECAConfigFieldValues => {
return {
endpoint: "https://example.com/acme/directory",
};
};
const AccessFormACMECAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormACMECAConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
endpoint: z.string().url(t("common.errmsg.url_invalid")),
eabKid: z.string().trim().nullish(),
eabHmacKey: z.string().trim().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="endpoint"
label={t("access.form.acmeca_endpoint.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_endpoint.tooltip") }}></span>}
>
<Input placeholder={t("access.form.acmeca_endpoint.placeholder")} />
</Form.Item>
<Form.Item
name="eabKid"
label={t("access.form.acmeca_eab_kid.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_eab_kid.tooltip") }}></span>}
>
<Input allowClear autoComplete="new-password" placeholder={t("access.form.acmeca_eab_kid.placeholder")} />
</Form.Item>
<Form.Item
name="eabHmacKey"
label={t("access.form.acmeca_eab_hmac_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmeca_eab_hmac_key.tooltip") }}></span>}
>
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.acmeca_eab_hmac_key.placeholder")} />
</Form.Item>
</Form>
);
};
export default AccessFormACMECAConfig;

View File

@@ -84,7 +84,7 @@ const AccessFormACMEHttpReqConfig = ({ form: formInst, formName, disabled, initi
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmehttpreq_username.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.acmehttpreq_username.placeholder")} />
<Input allowClear autoComplete="new-password" placeholder={t("access.form.acmehttpreq_username.placeholder")} />
</Form.Item>
<Form.Item
@@ -93,7 +93,7 @@ const AccessFormACMEHttpReqConfig = ({ form: formInst, formName, disabled, initi
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.acmehttpreq_password.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.acmehttpreq_password.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.acmehttpreq_password.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -27,11 +27,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiKey: z
.string()
.min(1, t("access.form.baotapanel_api_key.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
apiKey: z.string().nonempty(t("access.form.baotapanel_api_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@@ -0,0 +1,71 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForBaotaWAF } from "@/domain/access";
type AccessFormBaotaWAFConfigFieldValues = Nullish<AccessConfigForBaotaWAF>;
export type AccessFormBaotaWAFConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormBaotaWAFConfigFieldValues;
onValuesChange?: (values: AccessFormBaotaWAFConfigFieldValues) => void;
};
const initFormModel = (): AccessFormBaotaWAFConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8379/",
apiKey: "",
};
};
const AccessFormBaotaWAFConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormBaotaWAFConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
apiKey: z.string().nonempty(t("access.form.baotawaf_api_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.baotawaf_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.baotawaf_api_url.placeholder")} />
</Form.Item>
<Form.Item
name="apiKey"
label={t("access.form.baotawaf_api_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotawaf_api_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.baotawaf_api_key.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.baotawaf_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.baotawaf_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.baotawaf_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormBaotaWAFConfig;

View File

@@ -66,7 +66,7 @@ const AccessFormCloudflareConfig = ({ form: formInst, formName, disabled, initia
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.cloudflare_zone_api_token.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.cloudflare_zone_api_token.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.cloudflare_zone_api_token.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -0,0 +1,90 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForFlexCDN } from "@/domain/access";
type AccessFormFlexCDNConfigFieldValues = Nullish<AccessConfigForFlexCDN>;
export type AccessFormFlexCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormFlexCDNConfigFieldValues;
onValuesChange?: (values: AccessFormFlexCDNConfigFieldValues) => void;
};
const initFormModel = (): AccessFormFlexCDNConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8000/",
apiRole: "user",
accessKeyId: "",
accessKey: "",
};
};
const AccessFormFlexCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormFlexCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.flexcdn_api_role.placeholder"),
}),
accessKeyId: z.string().nonempty(t("access.form.flexcdn_access_key_id.placeholder")).trim(),
accessKey: z.string().nonempty(t("access.form.flexcdn_access_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.flexcdn_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.flexcdn_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiRole" label={t("access.form.flexcdn_api_role.label")} rules={[formRule]}>
<Radio.Group options={["user", "admin"].map((s) => ({ label: t(`access.form.flexcdn_api_role.option.${s}.label`), value: s }))} />
</Form.Item>
<Form.Item
name="accessKeyId"
label={t("access.form.flexcdn_access_key_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.flexcdn_access_key_id.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.flexcdn_access_key_id.placeholder")} />
</Form.Item>
<Form.Item
name="accessKey"
label={t("access.form.flexcdn_access_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.flexcdn_access_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.flexcdn_access_key.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.flexcdn_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.flexcdn_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.flexcdn_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormFlexCDNConfig;

View File

@@ -32,16 +32,8 @@ const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialVal
role: z.union([z.literal("user"), z.literal("admin")], {
message: t("access.form.goedge_api_role.placeholder"),
}),
accessKeyId: z
.string()
.min(1, t("access.form.goedge_access_key_id.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
accessKey: z
.string()
.min(1, t("access.form.goedge_access_key.placeholder"))
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
accessKeyId: z.string().nonempty(t("access.form.goedge_access_key_id.placeholder")).trim(),
accessKey: z.string().nonempty(t("access.form.goedge_access_key.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);

View File

@@ -0,0 +1,85 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Radio, Select, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForLeCDN } from "@/domain/access";
type AccessFormLeCDNConfigFieldValues = Nullish<AccessConfigForLeCDN>;
export type AccessFormLeCDNConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormLeCDNConfigFieldValues;
onValuesChange?: (values: AccessFormLeCDNConfigFieldValues) => void;
};
const initFormModel = (): AccessFormLeCDNConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:5090/",
apiVersion: "v3",
apiRole: "user",
username: "",
password: "",
};
};
const AccessFormLeCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormLeCDNConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
role: z.union([z.literal("client"), z.literal("master")], {
message: t("access.form.lecdn_api_role.placeholder"),
}),
username: z.string().nonempty(t("access.form.lecdn_username.placeholder")).trim(),
password: z.string().nonempty(t("access.form.lecdn_password.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.lecdn_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.lecdn_api_url.placeholder")} />
</Form.Item>
<Form.Item name="apiVersion" label={t("access.form.lecdn_api_version.label")} rules={[formRule]}>
<Select options={["v3"].map((s) => ({ label: s, value: s }))} placeholder={t("access.form.lecdn_api_version.placeholder")} />
</Form.Item>
<Form.Item name="apiRole" label={t("access.form.lecdn_api_role.label")} rules={[formRule]}>
<Radio.Group options={["user", "master"].map((s) => ({ label: t(`access.form.lecdn_api_role.option.${s}.label`), value: s }))} />
</Form.Item>
<Form.Item name="username" label={t("access.form.lecdn_username.label")} rules={[formRule]}>
<Input autoComplete="new-password" placeholder={t("access.form.lecdn_username.placeholder")} />
</Form.Item>
<Form.Item name="password" label={t("access.form.lecdn_password.label")} rules={[formRule]}>
<Input.Password autoComplete="new-password" placeholder={t("access.form.lecdn_password.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.lecdn_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.lecdn_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.lecdn_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormLeCDNConfig;

View File

@@ -65,7 +65,7 @@ const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initial
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.proxmoxve_api_token_secret.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token_secret.placeholder")} />
<Input.Password allowClear autoComplete="new-password" placeholder={t("access.form.proxmoxve_api_token_secret.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.proxmoxve_allow_insecure_conns.label")} rules={[formRule]}>

View File

@@ -0,0 +1,82 @@
import { useTranslation } from "react-i18next";
import { Form, type FormInstance, Input, Switch } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { type AccessConfigForRatPanel } from "@/domain/access";
type AccessFormRatPanelConfigFieldValues = Nullish<AccessConfigForRatPanel>;
export type AccessFormRatPanelConfigProps = {
form: FormInstance;
formName: string;
disabled?: boolean;
initialValues?: AccessFormRatPanelConfigFieldValues;
onValuesChange?: (values: AccessFormRatPanelConfigFieldValues) => void;
};
const initFormModel = (): AccessFormRatPanelConfigFieldValues => {
return {
apiUrl: "http://<your-host-addr>:8888/",
accessTokenId: 1,
accessToken: "",
};
};
const AccessFormRatPanelConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormRatPanelConfigProps) => {
const { t } = useTranslation();
const formSchema = z.object({
apiUrl: z.string().url(t("common.errmsg.url_invalid")),
accessTokenId: z.preprocess((v) => Number(v), z.number().positive(t("access.form.ratpanel_access_token_id.placeholder"))),
accessToken: z.string().nonempty(t("access.form.ratpanel_access_token.placeholder")).trim(),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item name="apiUrl" label={t("access.form.ratpanel_api_url.label")} rules={[formRule]}>
<Input placeholder={t("access.form.ratpanel_api_url.placeholder")} />
</Form.Item>
<Form.Item
name="accessTokenId"
label={t("access.form.ratpanel_access_token_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ratpanel_access_token_id.tooltip") }}></span>}
>
<Input type="number" placeholder={t("access.form.ratpanel_access_token_id.placeholder")} />
</Form.Item>
<Form.Item
name="accessToken"
label={t("access.form.ratpanel_access_token.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ratpanel_access_token.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.ratpanel_access_token.placeholder")} />
</Form.Item>
<Form.Item name="allowInsecureConnections" label={t("access.form.ratpanel_allow_insecure_conns.label")} rules={[formRule]}>
<Switch
checkedChildren={t("access.form.ratpanel_allow_insecure_conns.switch.on")}
unCheckedChildren={t("access.form.ratpanel_allow_insecure_conns.switch.off")}
/>
</Form.Item>
</Form>
);
};
export default AccessFormRatPanelConfig;

View File

@@ -81,7 +81,7 @@ const AccessFormUCloudConfig = ({ form: formInst, formName, disabled, initialVal
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ucloud_project_id.tooltip") }}></span>}
>
<Input autoComplete="new-password" placeholder={t("access.form.ucloud_project_id.placeholder")} />
<Input allowClear autoComplete="new-password" placeholder={t("access.form.ucloud_project_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -66,7 +66,7 @@ const AccessFormVercelConfig = ({ form: formInst, formName, disabled, initialVal
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.vercel_team_id.tooltip") }}></span>}
>
<Input placeholder={t("access.form.vercel_team_id.placeholder")} />
<Input allowClear placeholder={t("access.form.vercel_team_id.placeholder")} />
</Form.Item>
</Form>
);

View File

@@ -67,7 +67,6 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
}
return true;
}, t("access.form.webhook_headers.errmsg.invalid")),
allowInsecureConnections: z.boolean().nullish(),
defaultDataForDeployment: z
.string()
.nullish()
@@ -96,11 +95,12 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
return false;
}
}, t("access.form.webhook_default_data.errmsg.json_invalid")),
allowInsecureConnections: z.boolean().nullish(),
});
const formRule = createSchemaFieldRule(formSchema);
const handleWebhookHeadersBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
let value = e.target.value;
const handleWebhookHeadersBlur = () => {
let value = formInst.getFieldValue("headers");
value = value.trim();
value = value.replace(/(?<!\r)\n/g, "\r\n");
formInst.setFieldValue("headers", value);
@@ -279,7 +279,13 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.webhook_headers.tooltip") }}></span>}
>
<Input.TextArea autoSize={{ minRows: 3, maxRows: 10 }} placeholder={t("access.form.webhook_headers.placeholder")} onBlur={handleWebhookHeadersBlur} />
<CodeInput
height="auto"
minHeight="64px"
maxHeight="256px"
placeholder={t("access.form.webhook_headers.placeholder")}
onBlur={handleWebhookHeadersBlur}
/>
</Form.Item>
<Show when={!usage || usage === "deployment"}>