var-group-item.tsx 5.7 KB

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