diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx index 75d7649165..ec435ff248 100644 --- a/web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx @@ -83,7 +83,7 @@ const EmailConfigureModal = ({ body, debug: debugMode, }) - }, [subject, body, onConfirm]) + }, [recipients, subject, body, debugMode, onConfirm]) return ( = ({ const { t } = useTranslation() const [isHovering, setIsHovering] = React.useState(false) const [showEmailModal, setShowEmailModal] = React.useState(false) + const [showTestEmailModal, setShowTestEmailModal] = React.useState(false) const handleEnableStatusChange = (enabled: boolean) => { onChange({ @@ -73,13 +75,13 @@ const DeliveryMethodItem: React.FC = ({ )}
{method.type}
- {method.type === DeliveryMethodType.Email && method.config?.debug && DEBUG} + {method.type === DeliveryMethodType.Email && method.config?.debug && DEBUG}
{method.type === DeliveryMethodType.Email && method.config && ( <> - setShowEmailModal(true)}> + setShowTestEmailModal(true)}> setShowEmailModal(true)}> @@ -130,6 +132,19 @@ const DeliveryMethodItem: React.FC = ({ }} /> )} + {showTestEmailModal && ( + setShowTestEmailModal(false)} + onConfirm={(data) => { + handleConfigChange(data) + setShowTestEmailModal(false) + }} + /> + )} ) } diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-input.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-input.tsx index 166ca6a36b..e0d0123df8 100644 --- a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-input.tsx +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-input.tsx @@ -20,6 +20,7 @@ type Props = { onDelete: (recipient: RecipientItem) => void onSelect: (value: any) => void onAdd: (email: string) => void + disabled?: boolean } const EmailInput = ({ @@ -29,6 +30,7 @@ const EmailInput = ({ onDelete, onSelect, onAdd, + disabled = false, }: Props) => { const { t } = useTranslation() const inputRef = useRef(null) @@ -50,6 +52,7 @@ const EmailInput = ({ }, [selectedEmails, t, isFocus]) const setInputFocus = () => { + if (disabled) return setIsFocus(true) const input = inputRef.current?.children[0] as HTMLInputElement input?.focus() @@ -104,7 +107,11 @@ const EmailInput = ({ return (
{selectedEmails.map(item => ( @@ -113,41 +120,44 @@ const EmailInput = ({ email={email} data={item as unknown as Member} onDelete={onDelete} + disabled={disabled} /> ))} - - - setIsFocus(true)} - onBlur={() => setIsFocus(false)} - value={searchKey} - onChange={handleValueChange} - onKeyDown={handleKeyDown} - /> - - - - - + {!disabled && ( + + + setIsFocus(true)} + onBlur={() => setIsFocus(false)} + value={searchKey} + onChange={handleValueChange} + onKeyDown={handleKeyDown} + /> + + + + + + )}
) diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx index 8a0acfc70a..47c9a45c86 100644 --- a/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/recipient/email-item.tsx @@ -8,6 +8,7 @@ import Avatar from '@/app/components/base/avatar' type Props = { email: string data: Member + disabled?: boolean onDelete: (recipient: RecipientItem) => void } @@ -16,6 +17,7 @@ const EmailItem = ({ email, data, onDelete, + disabled = false, }: Props) => { const { t } = useTranslation() @@ -29,10 +31,12 @@ const EmailItem = ({ {email === data.email ? data.name : data.email} {email === data.email && {t('common.members.you')}}
- onDelete(data as unknown as RecipientItem)} - /> + {!disabled && ( + onDelete(data as unknown as RecipientItem)} + /> + )}
) } diff --git a/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx b/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx new file mode 100644 index 0000000000..0435ea4383 --- /dev/null +++ b/web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx @@ -0,0 +1,230 @@ +import { memo, useCallback, useState } from 'react' +import useSWR from 'swr' +import { Trans, useTranslation } from 'react-i18next' +import { useAppContext } from '@/context/app-context' +import { RiArrowRightSFill, RiCloseLine } from '@remixicon/react' +import Modal from '@/app/components/base/modal' +import Button from '@/app/components/base/button' +import Divider from '@/app/components/base/divider' +import EmailInput from './recipient/email-input' +import type { EmailConfig } from '../../types' +import type { + Node, + NodeOutPutVar, +} from '@/app/components/workflow/types' +import { fetchMembers } from '@/service/common' +import { noop } from 'lodash-es' +import cn from '@/utils/classnames' + +const i18nPrefix = 'workflow.nodes.humanInput' + +type EmailConfigureModalProps = { + isShow: boolean + onClose: () => void + onConfirm: (data: any) => void + config?: EmailConfig + nodesOutputVars?: NodeOutPutVar[] + availableNodes?: Node[] +} + +const EmailSenderModal = ({ + isShow, + onClose, + onConfirm, + config, + nodesOutputVars = [], + availableNodes = [], +}: EmailConfigureModalProps) => { + const { t } = useTranslation() + const { userProfile, currentWorkspace } = useAppContext() + + const debugEnabled = !!config?.debug + const onlyWholeTeam = config?.recipients?.whole_workspace && (!config?.recipients?.items || config?.recipients?.items.length === 0) + const onlySpecificUsers = !config?.recipients?.whole_workspace && config?.recipients?.items && config?.recipients?.items.length > 0 + const combinedRecipients = config?.recipients?.whole_workspace && config?.recipients?.items && config?.recipients?.items.length > 0 + + const { data: members } = useSWR( + { + url: '/workspaces/current/members', + params: {}, + }, + fetchMembers, + ) + const accounts = members?.accounts || [] + + const [collapsed, setCollapsed] = useState(true) + const [done, setDone] = useState(false) + + const handleConfirm = useCallback(() => { + // TODO send api + setDone(true) + }, [onConfirm]) + + if (done) { + return ( + +
+
{t(`${i18nPrefix}.deliveryMethod.emailSender.done`)}
+ {debugEnabled && ( +
+ }} + values={{ email: userProfile.email }} + /> +
+ )} + {!debugEnabled && onlyWholeTeam && ( +
+ }} + values={{ team: currentWorkspace.name.replace(/'/g, '’') }} + /> +
+ )} + {!debugEnabled && onlySpecificUsers && ( +
{t(`${i18nPrefix}.deliveryMethod.emailSender.wholeTeamDone3`)}
+ )} + {!debugEnabled && combinedRecipients && ( +
+ }} + values={{ team: currentWorkspace.name.replace(/'/g, '’') }} + /> +
+ )} +
+ {(onlySpecificUsers || combinedRecipients) && ( +
+ +
+ )} +
+ +
+
+ ) + } + + return ( + +
+ +
+
+
{t(`${i18nPrefix}.deliveryMethod.emailSender.title`)}
+ {debugEnabled && ( + <> +
{t(`${i18nPrefix}.deliveryMethod.emailSender.debugModeTip`)}
+
+ }} + values={{ email: userProfile.email }} + /> +
+ + )} + {!debugEnabled && onlyWholeTeam && ( +
+ }} + values={{ team: currentWorkspace.name.replace(/'/g, '’') }} + /> +
+ )} + {!debugEnabled && onlySpecificUsers && ( +
{t(`${i18nPrefix}.deliveryMethod.emailSender.wholeTeamTip3`)}
+ )} + {!debugEnabled && combinedRecipients && ( +
+ }} + values={{ team: currentWorkspace.name.replace(/'/g, '’') }} + /> +
+ )} +
+ {(onlySpecificUsers || combinedRecipients) && ( + <> +
+ +
+
+ }} + /> +
+ + )} + {/* vars */} +
+ +
+
+
setCollapsed(!collapsed)}> +
{t(`${i18nPrefix}.deliveryMethod.emailSender.vars`)}
+
{t(`${i18nPrefix}.deliveryMethod.emailSender.optional`)}
+ +
+
{t(`${i18nPrefix}.deliveryMethod.emailSender.varsTip`)}
+ {!collapsed && ( +
+ {/* form TODO */} +
+ )} +
+
+ + +
+
+ ) +} + +export default memo(EmailSenderModal) diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index b500744b12..365d49eceb 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -963,6 +963,24 @@ const translation = { debugModeTip1: 'During debug mode, emails will only be sent to your account email {{email}}.', debugModeTip2: 'The production environment is not affected.', }, + emailSender: { + title: 'Test Email Sender', + debugModeTip: 'Debug mode is enabled.', + debugModeTip2: 'Email will be sent to {{email}}.', + wholeTeamTip1: 'Email will be sent to {{team}} members and the following email addresses:', + wholeTeamTip2: 'Email will be sent to {{team}} members.', + wholeTeamTip3: 'Email will be sent to the following email addresses:', + tip: 'It is recommended to enable Debug Mode for testing email delivery.', + vars: 'Variables in Form Content', + optional: '(optional)', + varsTip: 'Fill in form variables to emulate what recipients actually see.', + send: 'Send Email', + done: 'Email Sent', + debugDone: 'A test email has been sent to {{email}}. Please check your inbox.', + wholeTeamDone1: 'Email will be sent to {{team}} members and the following email addresses:', + wholeTeamDone2: 'Email will be sent to {{team}} members.', + wholeTeamDone3: 'Email will be sent to the following email addresses:', + }, }, formContent: { title: 'Form Content', diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index 6779825cfb..369c197f92 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -963,6 +963,24 @@ const translation = { debugModeTip1: '在调试模式下,电子邮件将仅发送到您的帐户电子邮件 {{email}}。', debugModeTip2: '生产环境不受影响。', }, + emailSender: { + title: '测试邮件发送器', + debugModeTip: '调试模式已启用。', + debugModeTip2: '邮件将发送到 {{email}}。', + wholeTeamTip1: '邮件将发送给 {{team}} 成员和以下邮件地址:', + wholeTeamTip2: '邮件将发送给 {{team}} 成员。', + wholeTeamTip3: '邮件将发送到以下邮件地址:', + tip: '建议为测试邮件发送启用 调试模式。', + vars: '表单内容中的变量', + optional: '(可选)', + varsTip: '填写表单变量以模拟收件人实际看到的内容。', + send: '发送邮件', + done: '邮件已发送', + debugDone: '测试邮件已发送到 {{email}}。请检查您的收件箱。', + wholeTeamDone1: '邮件将发送给 {{team}} 成员和以下邮件地址:', + wholeTeamDone2: '邮件将发送给 {{team}} 成员。', + wholeTeamDone3: '邮件将发送到以下邮件地址:', + }, }, formContent: { title: '表单内容',