var-group-item.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. 'use client'
  2. import React, { useCallback } from 'react'
  3. import type { ChangeEvent, FC } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import produce from 'immer'
  6. import { useBoolean } from 'ahooks'
  7. import type { VarGroupItem as VarGroupItemType } from '../types'
  8. import VarReferencePicker from '../../_base/components/variable/var-reference-picker'
  9. import VarList from '../components/var-list'
  10. import Field from '@/app/components/workflow/nodes/_base/components/field'
  11. import { VarType } from '@/app/components/workflow/types'
  12. import type { NodeOutPutVar, ValueSelector, Var } from '@/app/components/workflow/types'
  13. import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
  14. import { Trash03 } from '@/app/components/base/icons/src/vender/line/general'
  15. import { Folder } from '@/app/components/base/icons/src/vender/line/files'
  16. import { checkKeys } from '@/utils/var'
  17. import Toast from '@/app/components/base/toast'
  18. const i18nPrefix = 'workflow.nodes.variableAssigner'
  19. type Payload = VarGroupItemType & {
  20. group_name?: string
  21. }
  22. type Props = {
  23. readOnly: boolean
  24. nodeId: string
  25. payload: Payload
  26. onChange: (newPayload: Payload) => void
  27. groupEnabled: boolean
  28. onGroupNameChange?: (value: string) => void
  29. canRemove?: boolean
  30. onRemove?: () => void
  31. availableVars: NodeOutPutVar[]
  32. }
  33. const VarGroupItem: FC<Props> = ({
  34. readOnly,
  35. nodeId,
  36. payload,
  37. onChange,
  38. groupEnabled,
  39. onGroupNameChange,
  40. canRemove,
  41. onRemove,
  42. availableVars,
  43. }) => {
  44. const { t } = useTranslation()
  45. const handleAddVariable = useCallback((value: ValueSelector | string, _varKindType: VarKindType, varInfo?: Var) => {
  46. const chosenVariables = payload.variables
  47. if (chosenVariables.some(item => item.join('.') === (value as ValueSelector).join('.')))
  48. return
  49. const newPayload = produce(payload, (draft: Payload) => {
  50. draft.variables.push(value as ValueSelector)
  51. if (varInfo && varInfo.type !== VarType.any)
  52. draft.output_type = varInfo.type
  53. })
  54. onChange(newPayload)
  55. }, [onChange, payload])
  56. const handleListChange = useCallback((newList: ValueSelector[], changedItem?: ValueSelector) => {
  57. if (changedItem) {
  58. const chosenVariables = payload.variables
  59. if (chosenVariables.some(item => item.join('.') === (changedItem as ValueSelector).join('.')))
  60. return
  61. }
  62. const newPayload = produce(payload, (draft) => {
  63. draft.variables = newList
  64. if (newList.length === 0)
  65. draft.output_type = VarType.any
  66. })
  67. onChange(newPayload)
  68. }, [onChange, payload])
  69. const filterVar = useCallback((varPayload: Var) => {
  70. if (payload.output_type === VarType.any)
  71. return true
  72. return varPayload.type === payload.output_type
  73. }, [payload.output_type])
  74. const [isEditGroupName, {
  75. setTrue: setEditGroupName,
  76. setFalse: setNotEditGroupName,
  77. }] = useBoolean(false)
  78. const handleGroupNameChange = useCallback((e: ChangeEvent<any>) => {
  79. const value = e.target.value
  80. const { isValid, errorKey, errorMessageKey } = checkKeys([value], false)
  81. if (!isValid) {
  82. Toast.notify({
  83. type: 'error',
  84. message: t(`appDebug.varKeyError.${errorMessageKey}`, { key: errorKey }),
  85. })
  86. return
  87. }
  88. onGroupNameChange?.(value)
  89. }, [onGroupNameChange, t])
  90. return (
  91. <Field
  92. className='group'
  93. title={groupEnabled
  94. ? <div className='flex items-center'>
  95. <div className='flex items-center !normal-case'>
  96. <Folder className='mr-0.5 w-3.5 h-3.5' />
  97. {(!isEditGroupName)
  98. ? (
  99. <div className='flex items-center h-6 px-1 rounded-lg cursor-text hover:bg-gray-100' onClick={setEditGroupName}>
  100. {payload.group_name}
  101. </div>
  102. )
  103. : (
  104. <input
  105. type='text'
  106. className='h-6 px-1 rounded-lg bg-white border border-gray-300 focus:outline-none'
  107. // style={{
  108. // width: `${((payload.group_name?.length || 0) + 1) / 2}em`,
  109. // }}
  110. size={payload.group_name?.length} // to fit the input width
  111. autoFocus
  112. value={payload.group_name}
  113. onChange={handleGroupNameChange}
  114. onBlur={setNotEditGroupName}
  115. maxLength={30}
  116. />)}
  117. </div>
  118. {canRemove && (
  119. <div
  120. className='group-hover:block hidden ml-0.5 p-1 rounded-md text-gray-500 cursor-pointer hover:bg-[#FEE4E2] hover:text-[#D92D20]'
  121. onClick={onRemove}
  122. >
  123. <Trash03
  124. className='w-4 h-4'
  125. />
  126. </div>
  127. )}
  128. </div>
  129. : t(`${i18nPrefix}.title`)!}
  130. operations={
  131. <div className='flex items-center h-6 space-x-2'>
  132. {payload.variables.length > 0 && (
  133. <div className='flex items-center h-[18px] px-1 border border-black/8 rounded-[5px] text-xs font-medium text-gray-500 capitalize'>{payload.output_type}</div>
  134. )}
  135. {
  136. !readOnly
  137. ? <VarReferencePicker
  138. isAddBtnTrigger
  139. readonly={false}
  140. nodeId={nodeId}
  141. isShowNodeName
  142. value={[]}
  143. onChange={handleAddVariable}
  144. defaultVarKindType={VarKindType.variable}
  145. filterVar={filterVar}
  146. availableVars={availableVars}
  147. />
  148. : undefined
  149. }
  150. </div>
  151. }
  152. >
  153. <VarList
  154. readonly={readOnly}
  155. nodeId={nodeId}
  156. list={payload.variables}
  157. onChange={handleListChange}
  158. filterVar={filterVar}
  159. />
  160. </Field>
  161. )
  162. }
  163. export default React.memo(VarGroupItem)