mirror of
https://github.com/certimate-go/certimate.git
synced 2026-06-30 21:05:12 +08:00
feat(ui): save and continue button in drawer forms
This commit is contained in:
parent
69d528292d
commit
2cd5a1c630
@ -1,8 +1,8 @@
|
||||
import { startTransition, useCallback, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { IconX } from "@tabler/icons-react";
|
||||
import { IconChevronDown, IconX } from "@tabler/icons-react";
|
||||
import { useControllableValue, useGetState } from "ahooks";
|
||||
import { App, Button, Drawer, Flex, Form } from "antd";
|
||||
import { App, Button, Drawer, Dropdown, Flex, Form, Space } from "antd";
|
||||
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import AccessProviderPicker from "@/components/provider/AccessProviderPicker";
|
||||
@ -55,19 +55,7 @@ const AccessEditDrawer = ({ afterSubmit, mode, data, loading, trigger, usage, ..
|
||||
const [formPending, setFormPending] = useState(false);
|
||||
const [formChanged, setFormChanged] = useState(false);
|
||||
|
||||
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
|
||||
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
|
||||
const handleProviderPick = (value: string) => {
|
||||
formInst.setFieldValue("provider", value);
|
||||
};
|
||||
|
||||
const handleFormChange = () => {
|
||||
setFormChanged(true);
|
||||
};
|
||||
|
||||
const handleOkClick = async () => {
|
||||
const submitForm = async () => {
|
||||
let formValues: AccessModel;
|
||||
|
||||
setFormPending(true);
|
||||
@ -108,7 +96,6 @@ const AccessEditDrawer = ({ afterSubmit, mode, data, loading, trigger, usage, ..
|
||||
}
|
||||
|
||||
afterSubmit?.(formValues);
|
||||
setOpen(false);
|
||||
} catch (err) {
|
||||
notification.error({ title: t("common.text.request_error"), description: getErrMsg(err) });
|
||||
|
||||
@ -118,6 +105,27 @@ const AccessEditDrawer = ({ afterSubmit, mode, data, loading, trigger, usage, ..
|
||||
}
|
||||
};
|
||||
|
||||
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
|
||||
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
|
||||
const handleProviderPick = (value: string) => {
|
||||
formInst.setFieldValue("provider", value);
|
||||
};
|
||||
|
||||
const handleFormChange = () => {
|
||||
setFormChanged(true);
|
||||
};
|
||||
|
||||
const handleOkClick = async () => {
|
||||
await submitForm();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleOkAndContinueClick = async () => {
|
||||
await submitForm();
|
||||
};
|
||||
|
||||
const handleCancelClick = () => {
|
||||
if (formPending) return;
|
||||
|
||||
@ -157,7 +165,7 @@ const AccessEditDrawer = ({ afterSubmit, mode, data, loading, trigger, usage, ..
|
||||
fieldProvider ? (
|
||||
<Flex className="px-2" justify="space-between">
|
||||
{usage === "notification" ? (
|
||||
<Button disabled={mode !== "modify" || formChanged} loading={isTesting} onClick={handleTestPushClick}>
|
||||
<Button className="max-sm:invisible" disabled={mode !== "modify" || formChanged} loading={isTesting} onClick={handleTestPushClick}>
|
||||
{t("access.action.test_push.button")}
|
||||
</Button>
|
||||
) : (
|
||||
@ -167,9 +175,28 @@ const AccessEditDrawer = ({ afterSubmit, mode, data, loading, trigger, usage, ..
|
||||
<Button disabled={isTesting} onClick={handleCancelClick}>
|
||||
{t("common.button.cancel")}
|
||||
</Button>
|
||||
<Button disabled={isTesting} loading={formPending} type="primary" onClick={handleOkClick}>
|
||||
{mode === "modify" ? t("common.button.save") : t("common.button.submit")}
|
||||
</Button>
|
||||
<Space.Compact>
|
||||
<Button disabled={isTesting} loading={formPending} type="primary" onClick={handleOkClick}>
|
||||
{mode === "modify" ? t("common.button.save") : t("common.button.submit")}
|
||||
</Button>
|
||||
<Show when={mode === "modify"}>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "save_and_continue",
|
||||
label: t("common.button.save_and_continue"),
|
||||
onClick: handleOkAndContinueClick,
|
||||
},
|
||||
],
|
||||
}}
|
||||
placement="bottomRight"
|
||||
trigger={["click"]}
|
||||
>
|
||||
<Button disabled={formPending || isTesting} icon={<IconChevronDown size="1.25em" />} type="primary" />
|
||||
</Dropdown>
|
||||
</Show>
|
||||
</Space.Compact>
|
||||
</Flex>
|
||||
</Flex>
|
||||
) : (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { CopyToClipboard } from "react-copy-to-clipboard";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { IconChevronDown, IconClipboard, IconThumbUp } from "@tabler/icons-react";
|
||||
import { IconClipboard, IconDownload, IconThumbUp } from "@tabler/icons-react";
|
||||
import { App, Button, Dropdown, Form, Input, Tag, Tooltip } from "antd";
|
||||
import dayjs from "dayjs";
|
||||
import { saveAs } from "file-saver";
|
||||
@ -117,7 +117,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
|
||||
}}
|
||||
trigger={["click", "hover"]}
|
||||
>
|
||||
<Button icon={<IconChevronDown size="1.25em" />} iconPlacement="end" type="primary">
|
||||
<Button icon={<IconDownload size="1.25em" />} type="primary">
|
||||
{t("common.button.download")}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { type FlowNodeEntity, useClientContext, useRefresh } from "@flowgram.ai/fixed-layout-editor";
|
||||
import { IconEye, IconEyeOff, IconX } from "@tabler/icons-react";
|
||||
import { IconChevronDown, IconEye, IconEyeOff, IconX } from "@tabler/icons-react";
|
||||
import { useControllableValue } from "ahooks";
|
||||
import { Anchor, type AnchorProps, App, Button, Drawer, Flex, type FormInstance, Tooltip, Typography } from "antd";
|
||||
import { Anchor, type AnchorProps, App, Button, Drawer, Dropdown, Flex, type FormInstance, Space, Tooltip, Typography } from "antd";
|
||||
import { isEqual } from "radash";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
@ -43,6 +43,31 @@ export const NodeConfigDrawer = ({ children, afterClose, anchor, footer = true,
|
||||
|
||||
const [formPending, setFormPending] = useState(false);
|
||||
|
||||
const submitForm = async () => {
|
||||
let formValues: Record<string, unknown>;
|
||||
|
||||
setFormPending(true);
|
||||
try {
|
||||
formValues = await formInst.validateFields();
|
||||
} catch (err) {
|
||||
message.warning(t("common.errmsg.form_invalid"));
|
||||
|
||||
setFormPending(false);
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
node.form!.setValueIn("config", formValues);
|
||||
node.form!.validate();
|
||||
} catch (err) {
|
||||
notification.error({ title: t("common.text.request_error"), description: getErrMsg(err) });
|
||||
|
||||
throw err;
|
||||
} finally {
|
||||
setFormPending(false);
|
||||
}
|
||||
};
|
||||
|
||||
const nodeRegistry = node?.getNodeRegistry<NodeRegistry>();
|
||||
const NodeIcon = nodeRegistry?.meta?.icon;
|
||||
const renderNodeIcon = () =>
|
||||
@ -80,30 +105,17 @@ export const NodeConfigDrawer = ({ children, afterClose, anchor, footer = true,
|
||||
return;
|
||||
}
|
||||
|
||||
let formValues: Record<string, unknown>;
|
||||
|
||||
setFormPending(true);
|
||||
try {
|
||||
formValues = await formInst.validateFields();
|
||||
} catch (err) {
|
||||
message.warning(t("common.errmsg.form_invalid"));
|
||||
|
||||
setFormPending(false);
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
node.form!.setValueIn("config", formValues);
|
||||
node.form!.validate();
|
||||
await submitForm();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleOkAndContinueClick = async () => {
|
||||
if (node == null) {
|
||||
setOpen(false);
|
||||
} catch (err) {
|
||||
notification.error({ title: t("common.text.request_error"), description: getErrMsg(err) });
|
||||
|
||||
throw err;
|
||||
} finally {
|
||||
setFormPending(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await submitForm();
|
||||
};
|
||||
|
||||
const handleCancelClick = () => {
|
||||
@ -170,9 +182,26 @@ export const NodeConfigDrawer = ({ children, afterClose, anchor, footer = true,
|
||||
footer ? (
|
||||
<Flex className="px-2" justify="end" gap="small">
|
||||
<Button onClick={handleCancelClick}>{t("common.button.cancel")}</Button>
|
||||
<Button loading={formPending} type="primary" onClick={handleOkClick}>
|
||||
{t("common.button.save")}
|
||||
</Button>
|
||||
<Space.Compact>
|
||||
<Button loading={formPending} type="primary" onClick={handleOkClick}>
|
||||
{t("common.button.save")}
|
||||
</Button>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "save_and_continue",
|
||||
label: t("common.button.save_and_continue"),
|
||||
onClick: handleOkAndContinueClick,
|
||||
},
|
||||
],
|
||||
}}
|
||||
placement="bottomRight"
|
||||
trigger={["click"]}
|
||||
>
|
||||
<Button disabled={formPending} icon={<IconChevronDown size="1.25em" />} type="primary" />
|
||||
</Dropdown>
|
||||
</Space.Compact>
|
||||
</Flex>
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
"access.action.delete.modal.content": "Are you sure want to delete this credential? <br>This action cannot be undone.",
|
||||
"access.action.batch_delete.modal.title": "Delete credentials",
|
||||
"access.action.batch_delete.modal.content": "Are you sure want to delete these {{count}} selected credentials? <br>This action cannot be undone.",
|
||||
"access.action.test_push.button": "Test push",
|
||||
"access.action.test_push.button": "Send test push",
|
||||
|
||||
"access.props.name": "Name",
|
||||
"access.props.provider.usage.dns": "DNS",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"common.button.reload": "Reload",
|
||||
"common.button.reset": "Reset",
|
||||
"common.button.save": "Save changes",
|
||||
"common.button.save_and_continue": "Save and continue",
|
||||
"common.button.submit": "Submit",
|
||||
"common.button.view": "View",
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
"access.action.delete.modal.content": "确定要删除该授权吗?<br>注意此操作不可撤销,请谨慎操作。",
|
||||
"access.action.batch_delete.modal.title": "删除授权",
|
||||
"access.action.batch_delete.modal.content": "确定要删除这 {{count}} 个被选中的授权吗?<br>注意此操作不可撤销,请谨慎操作。",
|
||||
"access.action.test_push.button": "通知测试",
|
||||
"access.action.test_push.button": "发送测试通知",
|
||||
|
||||
"access.props.name": "名称",
|
||||
"access.props.provider.usage.dns": "DNS 提供商",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"common.button.reload": "重新加载",
|
||||
"common.button.reset": "重置",
|
||||
"common.button.save": "保存更改",
|
||||
"common.button.save_and_continue": "保存并继续",
|
||||
"common.button.submit": "提交",
|
||||
"common.button.view": "查看",
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user