diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index abbce8b4..72e100db 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -1,7 +1,12 @@ import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router"; -import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons"; +import { + CloseOutlined as CloseOutlinedIcon, + PlusOutlined as PlusOutlinedIcon, + QuestionCircleOutlined as QuestionCircleOutlinedIcon, + RightOutlined as RightOutlinedIcon, +} from "@ant-design/icons"; import { useControllableValue } from "ahooks"; import { AutoComplete, @@ -589,8 +594,7 @@ const ApplyNodeConfigForm = forwardRef void }) => { - const { emails, fetchEmails } = useContactEmailsStore(); - const emailsToOptions = () => emails.map((email) => ({ label: email, value: email })); + const { emails, fetchEmails, removeEmail } = useContactEmailsStore(); useEffect(() => { fetchEmails(); }, []); @@ -601,24 +605,49 @@ const EmailInput = memo( trigger: "onChange", }); - const [options, setOptions] = useState([]); - useEffect(() => { - setOptions(emailsToOptions()); - }, [emails]); + const [inputValue, setInputValue] = useState(); + + const renderOptionLabel = (email: string, removable: boolean = false) => ( +
+ {email} + {removable && ( +
+ ); + + const options = useMemo(() => { + const temp = emails.map((email) => ({ + label: renderOptionLabel(email, true), + value: email, + })); + + if (!!inputValue && temp.every((option) => option.value !== inputValue)) { + temp.unshift({ + label: renderOptionLabel(inputValue), + value: inputValue, + }); + } + + return temp; + }, [emails, inputValue]); const handleChange = (value: string) => { setValue(value); }; - const handleSearch = (text: string) => { - const temp = emailsToOptions(); - if (text?.trim()) { - if (temp.every((option) => option.label !== text)) { - temp.unshift({ label: text, value: text }); - } - } - - setOptions(temp); + const handleSearch = (value: string) => { + setInputValue(value?.trim()); }; return ( diff --git a/ui/src/stores/contact/index.ts b/ui/src/stores/contact/index.ts index a17e18bd..ae8e25d2 100644 --- a/ui/src/stores/contact/index.ts +++ b/ui/src/stores/contact/index.ts @@ -60,6 +60,7 @@ export const useContactEmailsStore = create((set, get) => { if (draft.includes(email)) return; draft.push(email); draft.sort(); + return draft; }); get().setEmails(emails); }, @@ -68,6 +69,7 @@ export const useContactEmailsStore = create((set, get) => { const emails = produce(get().emails, (draft) => { draft = draft.filter((e) => e !== email); draft.sort(); + return draft; }); get().setEmails(emails); },