feat: improve workflow node configuration
This commit is contained in:
@@ -12,32 +12,32 @@ import DeployProviderPicker from "@/components/provider/DeployProviderPicker";
|
||||
import DeployProviderSelect from "@/components/provider/DeployProviderSelect";
|
||||
import { ACCESS_USAGES, DEPLOY_PROVIDERS, accessProvidersMap, deployProvidersMap } from "@/domain/provider";
|
||||
import { type WorkflowNode, type WorkflowNodeConfigForDeploy } from "@/domain/workflow";
|
||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||
import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
|
||||
import DeployNodeConfigFormAliyunALBFields from "./DeployNodeConfigFormAliyunALBFields";
|
||||
import DeployNodeConfigFormAliyunCDNFields from "./DeployNodeConfigFormAliyunCDNFields";
|
||||
import DeployNodeConfigFormAliyunCLBFields from "./DeployNodeConfigFormAliyunCLBFields";
|
||||
import DeployNodeConfigFormAliyunDCDNFields from "./DeployNodeConfigFormAliyunDCDNFields";
|
||||
import DeployNodeConfigFormAliyunNLBFields from "./DeployNodeConfigFormAliyunNLBFields";
|
||||
import DeployNodeConfigFormAliyunOSSFields from "./DeployNodeConfigFormAliyunOSSFields";
|
||||
import DeployNodeConfigFormBaiduCloudCDNFields from "./DeployNodeConfigFormBaiduCloudCDNFields";
|
||||
import DeployNodeConfigFormBytePlusCDNFields from "./DeployNodeConfigFormBytePlusCDNFields";
|
||||
import DeployNodeConfigFormDogeCloudCDNFields from "./DeployNodeConfigFormDogeCloudCDNFields";
|
||||
import DeployNodeConfigFormHuaweiCloudCDNFields from "./DeployNodeConfigFormHuaweiCloudCDNFields";
|
||||
import DeployNodeConfigFormHuaweiCloudELBFields from "./DeployNodeConfigFormHuaweiCloudELBFields";
|
||||
import DeployNodeConfigFormKubernetesSecretFields from "./DeployNodeConfigFormKubernetesSecretFields";
|
||||
import DeployNodeConfigFormLocalFields from "./DeployNodeConfigFormLocalFields";
|
||||
import DeployNodeConfigFormQiniuCDNFields from "./DeployNodeConfigFormQiniuCDNFields";
|
||||
import DeployNodeConfigFormSSHFields from "./DeployNodeConfigFormSSHFields";
|
||||
import DeployNodeConfigFormTencentCloudCDNFields from "./DeployNodeConfigFormTencentCloudCDNFields";
|
||||
import DeployNodeConfigFormTencentCloudCLBFields from "./DeployNodeConfigFormTencentCloudCLBFields";
|
||||
import DeployNodeConfigFormTencentCloudCOSFields from "./DeployNodeConfigFormTencentCloudCOSFields";
|
||||
import DeployNodeConfigFormTencentCloudECDNFields from "./DeployNodeConfigFormTencentCloudECDNFields";
|
||||
import DeployNodeConfigFormTencentCloudEOFields from "./DeployNodeConfigFormTencentCloudEOFields";
|
||||
import DeployNodeConfigFormVolcEngineCDNFields from "./DeployNodeConfigFormVolcEngineCDNFields";
|
||||
import DeployNodeConfigFormVolcEngineLiveFields from "./DeployNodeConfigFormVolcEngineLiveFields";
|
||||
import DeployNodeConfigFormWebhookFields from "./DeployNodeConfigFormWebhookFields";
|
||||
import DeployNodeConfigFormAliyunALBConfig from "./DeployNodeConfigFormAliyunALBConfig";
|
||||
import DeployNodeConfigFormAliyunCDNConfig from "./DeployNodeConfigFormAliyunCDNConfig";
|
||||
import DeployNodeConfigFormAliyunCLBConfig from "./DeployNodeConfigFormAliyunCLBConfig";
|
||||
import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDCDNConfig";
|
||||
import DeployNodeConfigFormAliyunNLBConfig from "./DeployNodeConfigFormAliyunNLBConfig";
|
||||
import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSSConfig";
|
||||
import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig";
|
||||
import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig";
|
||||
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
|
||||
import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig";
|
||||
import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig";
|
||||
import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig";
|
||||
import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig";
|
||||
import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig";
|
||||
import DeployNodeConfigFormSSHConfig from "./DeployNodeConfigFormSSHConfig.tsx";
|
||||
import DeployNodeConfigFormTencentCloudCDNConfig from "./DeployNodeConfigFormTencentCloudCDNConfig.tsx";
|
||||
import DeployNodeConfigFormTencentCloudCLBConfig from "./DeployNodeConfigFormTencentCloudCLBConfig.tsx";
|
||||
import DeployNodeConfigFormTencentCloudCOSConfig from "./DeployNodeConfigFormTencentCloudCOSConfig.tsx";
|
||||
import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx";
|
||||
import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx";
|
||||
import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx";
|
||||
import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx";
|
||||
import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx";
|
||||
|
||||
type DeployNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForDeploy>;
|
||||
|
||||
@@ -74,75 +74,86 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
}, [nodeId]);
|
||||
|
||||
const formSchema = z.object({
|
||||
certificate: z
|
||||
.string({ message: t("workflow_node.deploy.form.certificate.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.certificate.placeholder")),
|
||||
provider: z.string({ message: t("workflow_node.deploy.form.provider.placeholder") }).nonempty(t("workflow_node.deploy.form.provider.placeholder")),
|
||||
providerAccessId: z
|
||||
.string({ message: t("workflow_node.deploy.form.provider_access.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.provider_access.placeholder")),
|
||||
certificate: z
|
||||
.string({ message: t("workflow_node.deploy.form.certificate.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.certificate.placeholder")),
|
||||
providerConfig: z.any(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigForm",
|
||||
initialValues: initialValues ?? initFormModel(),
|
||||
});
|
||||
|
||||
const fieldProvider = Form.useWatch("provider", { form: formInst, preserve: true });
|
||||
|
||||
const formFieldsEl = useMemo(() => {
|
||||
const [nestedFormInst] = Form.useForm();
|
||||
const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "workflowNodeDeployConfigFormProviderConfigForm" });
|
||||
const nestedFormEl = useMemo(() => {
|
||||
const nestedFormProps = {
|
||||
form: nestedFormInst,
|
||||
formName: nestedFormName,
|
||||
disabled: disabled,
|
||||
initialValues: initialValues?.providerConfig,
|
||||
};
|
||||
|
||||
/*
|
||||
注意:如果追加新的子组件,请保持以 ASCII 排序。
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
注意:如果追加新的子组件,请保持以 ASCII 排序。
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProvider) {
|
||||
case DEPLOY_PROVIDERS.ALIYUN_ALB:
|
||||
return <DeployNodeConfigFormAliyunALBFields />;
|
||||
return <DeployNodeConfigFormAliyunALBConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.ALIYUN_CLB:
|
||||
return <DeployNodeConfigFormAliyunCLBFields />;
|
||||
return <DeployNodeConfigFormAliyunCLBConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.ALIYUN_CDN:
|
||||
return <DeployNodeConfigFormAliyunCDNFields />;
|
||||
return <DeployNodeConfigFormAliyunCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.ALIYUN_DCDN:
|
||||
return <DeployNodeConfigFormAliyunDCDNFields />;
|
||||
return <DeployNodeConfigFormAliyunDCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.ALIYUN_NLB:
|
||||
return <DeployNodeConfigFormAliyunNLBFields />;
|
||||
return <DeployNodeConfigFormAliyunNLBConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.ALIYUN_OSS:
|
||||
return <DeployNodeConfigFormAliyunOSSFields />;
|
||||
return <DeployNodeConfigFormAliyunOSSConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN:
|
||||
return <DeployNodeConfigFormBaiduCloudCDNFields />;
|
||||
return <DeployNodeConfigFormBaiduCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.BYTEPLUS_CDN:
|
||||
return <DeployNodeConfigFormBytePlusCDNFields />;
|
||||
return <DeployNodeConfigFormBytePlusCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.DOGECLOUD_CDN:
|
||||
return <DeployNodeConfigFormDogeCloudCDNFields />;
|
||||
return <DeployNodeConfigFormDogeCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.HUAWEICLOUD_CDN:
|
||||
return <DeployNodeConfigFormHuaweiCloudCDNFields />;
|
||||
return <DeployNodeConfigFormHuaweiCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.HUAWEICLOUD_ELB:
|
||||
return <DeployNodeConfigFormHuaweiCloudELBFields />;
|
||||
return <DeployNodeConfigFormHuaweiCloudELBConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.KUBERNETES_SECRET:
|
||||
return <DeployNodeConfigFormKubernetesSecretFields />;
|
||||
return <DeployNodeConfigFormKubernetesSecretConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.LOCAL:
|
||||
return <DeployNodeConfigFormLocalFields />;
|
||||
return <DeployNodeConfigFormLocalConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.QINIU_CDN:
|
||||
return <DeployNodeConfigFormQiniuCDNFields />;
|
||||
return <DeployNodeConfigFormQiniuCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.SSH:
|
||||
return <DeployNodeConfigFormSSHFields />;
|
||||
return <DeployNodeConfigFormSSHConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.TENCENTCLOUD_CDN:
|
||||
return <DeployNodeConfigFormTencentCloudCDNFields />;
|
||||
return <DeployNodeConfigFormTencentCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.TENCENTCLOUD_CLB:
|
||||
return <DeployNodeConfigFormTencentCloudCLBFields />;
|
||||
return <DeployNodeConfigFormTencentCloudCLBConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.TENCENTCLOUD_COS:
|
||||
return <DeployNodeConfigFormTencentCloudCOSFields />;
|
||||
return <DeployNodeConfigFormTencentCloudCOSConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.TENCENTCLOUD_ECDN:
|
||||
return <DeployNodeConfigFormTencentCloudECDNFields />;
|
||||
return <DeployNodeConfigFormTencentCloudECDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.TENCENTCLOUD_EO:
|
||||
return <DeployNodeConfigFormTencentCloudEOFields />;
|
||||
return <DeployNodeConfigFormTencentCloudEOConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.VOLCENGINE_CDN:
|
||||
return <DeployNodeConfigFormVolcEngineCDNFields />;
|
||||
return <DeployNodeConfigFormVolcEngineCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.VOLCENGINE_LIVE:
|
||||
return <DeployNodeConfigFormVolcEngineLiveFields />;
|
||||
return <DeployNodeConfigFormVolcEngineLiveConfig {...nestedFormProps} />;
|
||||
case DEPLOY_PROVIDERS.WEBHOOK:
|
||||
return <DeployNodeConfigFormWebhookFields />;
|
||||
return <DeployNodeConfigFormWebhookConfig {...nestedFormProps} />;
|
||||
}
|
||||
}, [fieldProvider]);
|
||||
}, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]);
|
||||
|
||||
const handleProviderPick = (value: string) => {
|
||||
formInst.setFieldValue("provider", value);
|
||||
@@ -175,6 +186,13 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormProviderChange = (name: string) => {
|
||||
if (name === nestedFormName) {
|
||||
formInst.setFieldValue("providerConfig", nestedFormInst.getFieldsValue());
|
||||
onValuesChange?.(formInst.getFieldsValue(true));
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values as DeployNodeConfigFormFieldValues);
|
||||
};
|
||||
@@ -188,101 +206,105 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return formInst.resetFields(fields);
|
||||
},
|
||||
validateFields: (nameList, config) => {
|
||||
return formInst.validateFields(nameList, config);
|
||||
const t1 = formInst.validateFields(nameList, config);
|
||||
const t2 = nestedFormInst.validateFields(undefined, config);
|
||||
return Promise.all([t1, t2]).then(() => t1);
|
||||
},
|
||||
} as DeployNodeConfigFormInstance;
|
||||
});
|
||||
|
||||
return (
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Show when={!!fieldProvider} fallback={<DeployProviderPicker onSelect={handleProviderPick} />}>
|
||||
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
|
||||
<DeployProviderSelect
|
||||
allowClear
|
||||
disabled
|
||||
placeholder={t("workflow_node.deploy.form.provider.placeholder")}
|
||||
showSearch
|
||||
onSelect={handleProviderSelect}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
<span>{t("workflow_node.deploy.form.provider_access.label")}</span>
|
||||
<Tooltip title={t("workflow_node.deploy.form.provider_access.tooltip")}>
|
||||
<Typography.Text className="ms-1" type="secondary">
|
||||
<QuestionCircleOutlinedIcon />
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<AccessEditModal
|
||||
data={{ provider: deployProvidersMap.get(fieldProvider!)?.provider }}
|
||||
preset="add"
|
||||
trigger={
|
||||
<Button size="small" type="link">
|
||||
<PlusOutlinedIcon />
|
||||
{t("workflow_node.deploy.form.provider_access.button")}
|
||||
</Button>
|
||||
}
|
||||
afterSubmit={(record) => {
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
if (ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.DEPLOY === provider?.usage) {
|
||||
formInst.setFieldValue("providerAccessId", record.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<Form.Item name="providerAccessId" rules={[formRule]}>
|
||||
<AccessSelect
|
||||
placeholder={t("workflow_node.deploy.form.provider_access.placeholder")}
|
||||
filter={(record) => {
|
||||
if (fieldProvider) {
|
||||
return deployProvidersMap.get(fieldProvider)?.provider === record.provider;
|
||||
}
|
||||
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
||||
}}
|
||||
<Form.Provider onFormChange={handleFormProviderChange}>
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Show when={!!fieldProvider} fallback={<DeployProviderPicker onSelect={handleProviderPick} />}>
|
||||
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
|
||||
<DeployProviderSelect
|
||||
allowClear
|
||||
disabled
|
||||
placeholder={t("workflow_node.deploy.form.provider.placeholder")}
|
||||
showSearch
|
||||
onSelect={handleProviderSelect}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="certificate"
|
||||
label={t("workflow_node.deploy.form.certificate.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.certificate.tooltip") }}></span>}
|
||||
>
|
||||
<Select
|
||||
options={previousNodes.map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
options: item.outputs?.map((output) => {
|
||||
return {
|
||||
label: `${item.name} - ${output.label}`,
|
||||
value: `${item.id}#${output.name}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
})}
|
||||
placeholder={t("workflow_node.deploy.form.certificate.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item className="mb-0">
|
||||
<label className="mb-1 block">
|
||||
<div className="flex w-full items-center justify-between gap-4">
|
||||
<div className="max-w-full grow truncate">
|
||||
<span>{t("workflow_node.deploy.form.provider_access.label")}</span>
|
||||
<Tooltip title={t("workflow_node.deploy.form.provider_access.tooltip")}>
|
||||
<Typography.Text className="ms-1" type="secondary">
|
||||
<QuestionCircleOutlinedIcon />
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<AccessEditModal
|
||||
data={{ provider: deployProvidersMap.get(fieldProvider!)?.provider }}
|
||||
preset="add"
|
||||
trigger={
|
||||
<Button size="small" type="link">
|
||||
<PlusOutlinedIcon />
|
||||
{t("workflow_node.deploy.form.provider_access.button")}
|
||||
</Button>
|
||||
}
|
||||
afterSubmit={(record) => {
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
if (ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.DEPLOY === provider?.usage) {
|
||||
formInst.setFieldValue("providerAccessId", record.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<Form.Item name="providerAccessId" rules={[formRule]}>
|
||||
<AccessSelect
|
||||
placeholder={t("workflow_node.deploy.form.provider_access.placeholder")}
|
||||
filter={(record) => {
|
||||
if (fieldProvider) {
|
||||
return deployProvidersMap.get(fieldProvider)?.provider === record.provider;
|
||||
}
|
||||
|
||||
<Divider className="my-1">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.deploy.form.params_config.label")}
|
||||
</Typography.Text>
|
||||
</Divider>
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
{formFieldsEl}
|
||||
</Show>
|
||||
</Form>
|
||||
<Form.Item
|
||||
name="certificate"
|
||||
label={t("workflow_node.deploy.form.certificate.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.certificate.tooltip") }}></span>}
|
||||
>
|
||||
<Select
|
||||
options={previousNodes.map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
options: item.outputs?.map((output) => {
|
||||
return {
|
||||
label: `${item.name} - ${output.label}`,
|
||||
value: `${item.id}#${output.name}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
})}
|
||||
placeholder={t("workflow_node.deploy.form.certificate.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Divider className="my-1">
|
||||
<Typography.Text className="text-xs font-normal" type="secondary">
|
||||
{t("workflow_node.deploy.form.params_config.label")}
|
||||
</Typography.Text>
|
||||
</Divider>
|
||||
</Show>
|
||||
</Form>
|
||||
|
||||
<Show when={!!fieldProvider}>{nestedFormEl}</Show>
|
||||
</Form.Provider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user