| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 | 
							- 'use client'
 - import type { FC } from 'react'
 - import React, { useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import produce from 'immer'
 - import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types'
 - import cn from '@/utils/classnames'
 - import Drawer from '@/app/components/base/drawer-plus'
 - import Input from '@/app/components/base/input'
 - import Textarea from '@/app/components/base/textarea'
 - import Button from '@/app/components/base/button'
 - import Toast from '@/app/components/base/toast'
 - import EmojiPicker from '@/app/components/base/emoji-picker'
 - import AppIcon from '@/app/components/base/app-icon'
 - import MethodSelector from '@/app/components/tools/workflow-tool/method-selector'
 - import LabelSelector from '@/app/components/tools/labels/selector'
 - import ConfirmModal from '@/app/components/tools/workflow-tool/confirm-modal'
 - import Tooltip from '@/app/components/base/tooltip'
 - 
 - type Props = {
 -   isAdd?: boolean
 -   payload: any
 -   onHide: () => void
 -   onRemove?: () => void
 -   onCreate?: (payload: WorkflowToolProviderRequest & { workflow_app_id: string }) => void
 -   onSave?: (payload: WorkflowToolProviderRequest & Partial<{
 -     workflow_app_id: string
 -     workflow_tool_id: string
 -   }>) => void
 - }
 - // Add and Edit
 - const WorkflowToolAsModal: FC<Props> = ({
 -   isAdd,
 -   payload,
 -   onHide,
 -   onRemove,
 -   onSave,
 -   onCreate,
 - }) => {
 -   const { t } = useTranslation()
 - 
 -   const [showEmojiPicker, setShowEmojiPicker] = useState<Boolean>(false)
 -   const [emoji, setEmoji] = useState<Emoji>(payload.icon)
 -   const [label, setLabel] = useState<string>(payload.label)
 -   const [name, setName] = useState(payload.name)
 -   const [description, setDescription] = useState(payload.description)
 -   const [parameters, setParameters] = useState<WorkflowToolProviderParameter[]>(payload.parameters)
 -   const handleParameterChange = (key: string, value: string, index: number) => {
 -     const newData = produce(parameters, (draft: WorkflowToolProviderParameter[]) => {
 -       if (key === 'description')
 -         draft[index].description = value
 -       else
 -         draft[index].form = value
 -     })
 -     setParameters(newData)
 -   }
 -   const [labels, setLabels] = useState<string[]>(payload.labels)
 -   const handleLabelSelect = (value: string[]) => {
 -     setLabels(value)
 -   }
 -   const [privacyPolicy, setPrivacyPolicy] = useState(payload.privacy_policy)
 -   const [showModal, setShowModal] = useState(false)
 - 
 -   const isNameValid = (name: string) => {
 -     // when the user has not input anything, no need for a warning
 -     if (name === '')
 -       return true
 - 
 -     return /^[a-zA-Z0-9_]+$/.test(name)
 -   }
 - 
 -   const onConfirm = () => {
 -     let errorMessage = ''
 -     if (!label)
 -       errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.name') })
 - 
 -     if (!name)
 -       errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.nameForToolCall') })
 - 
 -     if (!isNameValid(name))
 -       errorMessage = t('tools.createTool.nameForToolCall') + t('tools.createTool.nameForToolCallTip')
 - 
 -     if (errorMessage) {
 -       Toast.notify({
 -         type: 'error',
 -         message: errorMessage,
 -       })
 -       return
 -     }
 - 
 -     const requestParams = {
 -       name,
 -       description,
 -       icon: emoji,
 -       label,
 -       parameters: parameters.map(item => ({
 -         name: item.name,
 -         description: item.description,
 -         form: item.form,
 -       })),
 -       labels,
 -       privacy_policy: privacyPolicy,
 -     }
 -     if (!isAdd) {
 -       onSave?.({
 -         ...requestParams,
 -         workflow_tool_id: payload.workflow_tool_id,
 -       })
 -     }
 -     else {
 -       onCreate?.({
 -         ...requestParams,
 -         workflow_app_id: payload.workflow_app_id,
 -       })
 -     }
 -   }
 - 
 -   return (
 -     <>
 -       <Drawer
 -         isShow
 -         onHide={onHide}
 -         title={t('workflow.common.workflowAsTool')!}
 -         panelClassName='mt-2 !w-[640px]'
 -         maxWidthClassName='!max-w-[640px]'
 -         height='calc(100vh - 16px)'
 -         headerClassName='!border-b-black/5'
 -         body={
 -           <div className='flex flex-col h-full'>
 -             <div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'>
 -               {/* name & icon */}
 -               <div>
 -                 <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div>
 -                 <div className='flex items-center justify-between gap-3'>
 -                   <AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' iconType='emoji' icon={emoji.content} background={emoji.background} />
 -                   <Input
 -                     className='grow h-10'
 -                     placeholder={t('tools.createTool.toolNamePlaceHolder')!}
 -                     value={label}
 -                     onChange={e => setLabel(e.target.value)}
 -                   />
 -                 </div>
 -               </div>
 -               {/* name for tool call */}
 -               <div>
 -                 <div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'>
 -                   {t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span>
 -                   <Tooltip
 -                     popupContent={
 -                       <div className='w-[180px]'>
 -                         {t('tools.createTool.nameForToolCallPlaceHolder')}
 -                       </div>
 -                     }
 -                   />
 -                 </div>
 -                 <Input
 -                   className='h-10'
 -                   placeholder={t('tools.createTool.nameForToolCallPlaceHolder')!}
 -                   value={name}
 -                   onChange={e => setName(e.target.value)}
 -                 />
 -                 {!isNameValid(name) && (
 -                   <div className='text-xs leading-[18px] text-red-500'>{t('tools.createTool.nameForToolCallTip')}</div>
 -                 )}
 -               </div>
 -               {/* description */}
 -               <div>
 -                 <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.description')}</div>
 -                 <Textarea
 -                   placeholder={t('tools.createTool.descriptionPlaceholder') || ''}
 -                   value={description}
 -                   onChange={e => setDescription(e.target.value)}
 -                 />
 -               </div>
 -               {/* Tool Input  */}
 -               <div>
 -                 <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.toolInput.title')}</div>
 -                 <div className='rounded-lg border border-gray-200 w-full overflow-x-auto'>
 -                   <table className='w-full leading-[18px] text-xs text-gray-700 font-normal'>
 -                     <thead className='text-gray-500 uppercase'>
 -                       <tr className='border-b border-gray-200'>
 -                         <th className="p-2 pl-3 font-medium w-[156px]">{t('tools.createTool.toolInput.name')}</th>
 -                         <th className="p-2 pl-3 font-medium w-[102px]">{t('tools.createTool.toolInput.method')}</th>
 -                         <th className="p-2 pl-3 font-medium">{t('tools.createTool.toolInput.description')}</th>
 -                       </tr>
 -                     </thead>
 -                     <tbody>
 -                       {parameters.map((item, index) => (
 -                         <tr key={index} className='border-b last:border-0 border-gray-200'>
 -                           <td className="p-2 pl-3 max-w-[156px]">
 -                             <div className='text-[13px] leading-[18px]'>
 -                               <div title={item.name} className='flex'>
 -                                 <span className='font-medium text-gray-900 truncate'>{item.name}</span>
 -                                 <span className='shrink-0 pl-1 text-[#ec4a0a] text-xs leading-[18px]'>{item.required ? t('tools.createTool.toolInput.required') : ''}</span>
 -                               </div>
 -                               <div className='text-gray-500'>{item.type}</div>
 -                             </div>
 -                           </td>
 -                           <td>
 -                             {item.name === '__image' && (
 -                               <div className={cn(
 -                                 'flex items-center gap-1 min-h-[56px] px-3 py-2 h-9 bg-white cursor-default',
 -                               )}>
 -                                 <div className={cn('grow text-[13px] leading-[18px] text-gray-700 truncate')}>
 -                                   {t('tools.createTool.toolInput.methodParameter')}
 -                                 </div>
 -                               </div>
 -                             )}
 -                             {item.name !== '__image' && (
 -                               <MethodSelector value={item.form} onChange={value => handleParameterChange('form', value, index)} />
 -                             )}
 -                           </td>
 -                           <td className="p-2 pl-3 text-gray-500 w-[236px]">
 -                             <input
 -                               type='text'
 -                               className='grow text-gray-700 text-[13px] leading-[18px] font-normal bg-white outline-none appearance-none caret-primary-600 placeholder:text-gray-300'
 -                               placeholder={t('tools.createTool.toolInput.descriptionPlaceholder')!}
 -                               value={item.description}
 -                               onChange={e => handleParameterChange('description', e.target.value, index)}
 -                             />
 -                           </td>
 -                         </tr>
 -                       ))}
 -                     </tbody>
 -                   </table>
 -                 </div>
 -               </div>
 -               {/* Tags */}
 -               <div>
 -                 <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.toolInput.label')}</div>
 -                 <LabelSelector value={labels} onChange={handleLabelSelect} />
 -               </div>
 -               {/* Privacy Policy */}
 -               <div>
 -                 <div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.privacyPolicy')}</div>
 -                 <Input
 -                   className='h-10'
 -                   value={privacyPolicy}
 -                   onChange={e => setPrivacyPolicy(e.target.value)}
 -                   placeholder={t('tools.createTool.privacyPolicyPlaceholder') || ''} />
 -               </div>
 -             </div>
 -             <div className={cn((!isAdd && onRemove) ? 'justify-between' : 'justify-end', 'mt-2 shrink-0 flex py-4 px-6 rounded-b-[10px] bg-gray-50 border-t border-black/5')} >
 -               {!isAdd && onRemove && (
 -                 <Button onClick={onRemove} className='text-red-500 border-red-50 hover:border-red-500'>{t('common.operation.delete')}</Button>
 -               )}
 -               <div className='flex space-x-2 '>
 -                 <Button onClick={onHide}>{t('common.operation.cancel')}</Button>
 -                 <Button variant='primary' onClick={() => {
 -                   if (isAdd)
 -                     onConfirm()
 -                   else
 -                     setShowModal(true)
 -                 }}>{t('common.operation.save')}</Button>
 -               </div>
 -             </div>
 -           </div>
 -         }
 -         isShowMask={true}
 -         clickOutsideNotOpen={true}
 -       />
 -       {showEmojiPicker && <EmojiPicker
 -         onSelect={(icon, icon_background) => {
 -           setEmoji({ content: icon, background: icon_background })
 -           setShowEmojiPicker(false)
 -         }}
 -         onClose={() => {
 -           setShowEmojiPicker(false)
 -         }}
 -       />}
 -       {showModal && (
 -         <ConfirmModal
 -           show={showModal}
 -           onClose={() => setShowModal(false)}
 -           onConfirm={onConfirm}
 -         />
 -       )}
 -     </>
 - 
 -   )
 - }
 - export default React.memo(WorkflowToolAsModal)
 
 
  |