add tip modal for email type

This commit is contained in:
JzoNg 2026-01-19 16:40:54 +08:00
parent e3a22e5027
commit 5e644315e4
9 changed files with 113 additions and 17 deletions

View File

@ -20,5 +20,5 @@ export const useConfigsMap = () => {
fileUploadConfig,
},
}
}, [pipelineId])
}, [fileUploadConfig, pipelineId])
}

View File

@ -18,7 +18,7 @@ const i18nPrefix = 'nodes.humanInput'
type EmailConfigureModalProps = {
isShow: boolean
onClose: () => void
onConfirm: (data: any) => void
onConfirm: (data: EmailConfig) => void
config?: EmailConfig
}

View File

@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
import Tooltip from '@/app/components/base/tooltip'
import MethodItem from './method-item'
import MethodSelector from './method-selector'
import UpgradeModal from './upgrade-modal'
const i18nPrefix = 'nodes.humanInput'
@ -52,6 +53,14 @@ const DeliveryMethodForm: React.FC<Props> = ({
onChange(newMethods)
}
const [showUpgradeModal, setShowUpgradeModal] = React.useState(false)
const handleShowUpgradeModal = () => {
setShowUpgradeModal(true)
}
const handleCloseUpgradeModal = () => {
setShowUpgradeModal(false)
}
return (
<div className="px-4 py-2">
<div className="mb-1 flex items-center justify-between">
@ -66,6 +75,7 @@ const DeliveryMethodForm: React.FC<Props> = ({
<MethodSelector
data={value}
onAdd={handleMethodAdd}
onShowUpgradeTip={handleShowUpgradeModal}
/>
</div>
)}
@ -75,11 +85,11 @@ const DeliveryMethodForm: React.FC<Props> = ({
)}
{value.length > 0 && (
<div className="space-y-1">
{value.map((method, index) => (
{value.map(method => (
<MethodItem
nodeId={nodeId}
method={method}
key={index}
key={method.id}
onChange={handleMethodChange}
onDelete={handleMethodDelete}
nodesOutputVars={nodesOutputVars}
@ -90,6 +100,12 @@ const DeliveryMethodForm: React.FC<Props> = ({
))}
</div>
)}
{showUpgradeModal && (
<UpgradeModal
isShow={showUpgradeModal}
onClose={handleCloseUpgradeModal}
/>
)}
</div>
)
}

View File

@ -61,7 +61,7 @@ const DeliveryMethodItem: FC<DeliveryMethodItemProps> = ({
})
}
const handleConfigChange = (config: any) => {
const handleConfigChange = (config: EmailConfig) => {
onChange({
...method,
config,

View File

@ -29,11 +29,13 @@ const i18nPrefix = 'nodes.humanInput'
type MethodSelectorProps = {
data: DeliveryMethod[]
onAdd: (method: DeliveryMethod) => void
onShowUpgradeTip: () => void
}
const MethodSelector: FC<MethodSelectorProps> = ({
data,
onAdd,
onShowUpgradeTip,
}) => {
const { t } = useTranslation()
const [open, doSetOpen] = useState(false)
@ -102,10 +104,14 @@ const MethodSelector: FC<MethodSelectorProps> = ({
<div
className={cn(
'relative flex cursor-pointer items-center gap-1 rounded-lg p-1 pl-3 hover:bg-state-base-hover',
(emailDeliveryInfo.noPermission || emailDeliveryInfo.added) && 'cursor-not-allowed bg-transparent hover:bg-transparent',
emailDeliveryInfo.added && 'cursor-not-allowed bg-transparent hover:bg-transparent',
)}
onClick={() => {
if (emailDeliveryInfo.noPermission || emailDeliveryInfo.added)
if (emailDeliveryInfo.noPermission) {
onShowUpgradeTip()
return
}
if (emailDeliveryInfo.added)
return
onAdd({
id: uuid4(),
@ -117,21 +123,18 @@ const MethodSelector: FC<MethodSelectorProps> = ({
<div
className={cn(
'rounded-[4px] border border-divider-regular bg-components-icon-bg-blue-solid p-1',
(emailDeliveryInfo.noPermission || emailDeliveryInfo.added) && 'opacity-50',
emailDeliveryInfo.added && 'opacity-50',
)}
>
<RiMailSendFill className="h-4 w-4 text-text-primary-on-surface" />
</div>
<div className={cn('p-1', (emailDeliveryInfo.noPermission || emailDeliveryInfo.added) && 'opacity-50')}>
<div className={cn('p-1', emailDeliveryInfo.added && 'opacity-50')}>
<div className="system-sm-medium mb-0.5 truncate text-text-primary">{t(`${i18nPrefix}.deliveryMethod.types.email.title`, { ns: 'workflow' })}</div>
<div className="system-xs-regular truncate text-text-tertiary">{t(`${i18nPrefix}.deliveryMethod.types.email.description`, { ns: 'workflow' })}</div>
</div>
{emailDeliveryInfo.added && (
<div className="system-xs-regular absolute right-[12px] top-[13px] text-text-tertiary">{t(`${i18nPrefix}.deliveryMethod.added`, { ns: 'workflow' })}</div>
)}
{emailDeliveryInfo.noPermission && (
<div className="system-xs-regular absolute right-[12px] top-[13px] text-text-tertiary">Upgrade</div>
)}
</div>
{/* Slack */}
<div

View File

@ -0,0 +1,76 @@
import {
RiMailSendFill,
} from '@remixicon/react'
import { noop } from 'es-toolkit/compat'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import { SparklesSoft } from '@/app/components/base/icons/src/public/common'
import Modal from '@/app/components/base/modal'
import PremiumBadge from '@/app/components/base/premium-badge'
import { useModalContextSelector } from '@/context/modal-context'
import { cn } from '@/utils/classnames'
type UpgradeModalProps = {
isShow: boolean
onClose: () => void
}
const UpgradeModal: React.FC<UpgradeModalProps> = ({
isShow,
onClose,
}) => {
const { t } = useTranslation()
const setShowPricingModal = useModalContextSelector(s => s.setShowPricingModal)
return (
<Modal
isShow={isShow}
onClose={noop}
className="relative !w-[580px] !max-w-[580px] !p-8"
>
<div className="pb-6">
<div
className={cn(
'mb-6 inline-flex rounded-xl border border-divider-regular bg-util-colors-blue-brand-blue-brand-500 p-2',
)}
>
<RiMailSendFill className="h-6 w-6 text-text-primary-on-surface" />
</div>
<p
className="title-3xl-semi-bold bg-[linear-gradient(271deg,_var(--components-input-border-active-prompt-1,_#155AEF)_-12.85%,_var(--components-input-border-active-prompt-2,_#0BA5EC)_95.4%)] bg-clip-text text-transparent"
>
{t('nodes.humanInput.deliveryMethod.upgradeTip', { ns: 'workflow' })}
</p>
<p className="system-md-regular mt-2 text-text-tertiary">
{t('nodes.humanInput.deliveryMethod.upgradeTipContent', { ns: 'workflow' })}
</p>
</div>
<div className="flex justify-end pt-5">
<Button
className="w-[72px]"
onClick={onClose}
>
{t('nodes.humanInput.deliveryMethod.upgradeTipHide', { ns: 'workflow' })}
</Button>
<PremiumBadge
size="custom"
color="blue"
allowHover={true}
className="ml-3 h-8 w-[93px]"
onClick={() => {
setShowPricingModal()
}}
>
<SparklesSoft className="flex h-3.5 w-3.5 items-center py-[1px] pl-[3px] text-components-premium-badge-indigo-text-stop-0" />
<div className="system-sm-medium">
<span className="p-1">
{t('upgradeBtn.encourageShort', { ns: 'billing' })}
</span>
</div>
</PremiumBadge>
</div>
</Modal>
)
}
export default UpgradeModal

View File

@ -2566,11 +2566,6 @@
"count": 1
}
},
"app/components/rag-pipeline/hooks/use-configs-map.ts": {
"react-hooks/preserve-manual-memoization": {
"count": 1
}
},
"app/components/rag-pipeline/hooks/use-input-fields.ts": {
"ts/no-explicit-any": {
"count": 2

View File

@ -557,6 +557,9 @@
"nodes.humanInput.deliveryMethod.types.teams.title": "Teams",
"nodes.humanInput.deliveryMethod.types.webapp.description": "Display to end-user in webapp",
"nodes.humanInput.deliveryMethod.types.webapp.title": "Webapp",
"nodes.humanInput.deliveryMethod.upgradeTip": "Unlock Email delivery for Human Input",
"nodes.humanInput.deliveryMethod.upgradeTipContent": "Send confirmation requests via email before agents take action — useful for publishing and approval workflows.",
"nodes.humanInput.deliveryMethod.upgradeTipHide": "Dismiss",
"nodes.humanInput.editor.previewTip": "In preview mode, action buttons are not functional.",
"nodes.humanInput.errorMsg.duplicateActionId": "Duplicate action ID found in user actions",
"nodes.humanInput.errorMsg.emptyActionId": "Action ID cannot be empty",

View File

@ -557,6 +557,9 @@
"nodes.humanInput.deliveryMethod.types.teams.title": "Teams",
"nodes.humanInput.deliveryMethod.types.webapp.description": "在 Web 应用中显示给最终用户",
"nodes.humanInput.deliveryMethod.types.webapp.title": "Webapp",
"nodes.humanInput.deliveryMethod.upgradeTip": "解锁人类输入的电子邮件发送功能",
"nodes.humanInput.deliveryMethod.upgradeTipContent": "在 Agent 采取行动之前,通过电子邮件发送确认请求——适用于发布和审批工作流。",
"nodes.humanInput.deliveryMethod.upgradeTipHide": "关闭",
"nodes.humanInput.editor.previewTip": "在预览模式下,操作按钮无法使用。",
"nodes.humanInput.errorMsg.duplicateActionId": "用户操作中存在重复的操作 ID",
"nodes.humanInput.errorMsg.emptyActionId": "操作 ID 不能为空",