dify/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

161 lines
5.5 KiB
TypeScript

import type { ChatVariableTranslator, ToastPayload } from './variable-modal.helpers'
import type { ConversationVariable } from '@/app/components/workflow/types'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { toast } from '@langgenius/dify-ui/toast'
import { RiCloseLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { ChatVarType } from '@/app/components/workflow/panel/chat-variable-panel/type'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
import { useVariableModalState } from './use-variable-modal-state'
import {
getEditorToggleLabelKey,
MAX_DESCRIPTION_LENGTH,
typeList,
validateVariableName,
} from './variable-modal.helpers'
import {
DescriptionSection,
NameSection,
TypeSection,
ValueSection,
} from './variable-modal.sections'
type ModalPropsType = {
chatVar?: ConversationVariable
onClose: () => void
onSave: (chatVar: ConversationVariable) => void
}
const ChatVariableModal = ({ chatVar, onClose, onSave }: ModalPropsType) => {
const { t } = useTranslation()
const translateChatVariable: ChatVariableTranslator = (selector, options) => t(selector, options)
const workflowStore = useWorkflowStore()
const notify = React.useCallback(({ children, message, type = 'info' }: ToastPayload) => {
toast[type](message, children ? { description: children } : undefined)
}, [])
const {
description,
editInJSON,
editorContent,
editorMinHeight,
handleEditorChange,
handleEditorValueChange,
handleSave,
handleStringOrNumberChange,
handleTypeChange,
handleVarNameChange,
name,
objectValue,
placeholder,
setDescription,
setObjectValue,
setValue,
type,
value,
} = useVariableModalState({
chatVar,
conversationVariables: workflowStore.getState().conversationVariables,
notify,
onClose,
onSave,
t: translateChatVariable,
})
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
replaceSpaceWithUnderscoreInVarNameInput(e.target)
if (
e.target.value &&
!validateVariableName({ name: e.target.value, notify, t: translateChatVariable })
)
return
handleVarNameChange(e)
}
return (
<div
className={cn(
'flex h-full w-[360px] flex-col rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-2xl',
type === ChatVarType.Object && 'w-[480px]',
)}
>
<div className="mb-3 flex shrink-0 items-center justify-between p-4 pb-0 system-xl-semibold text-text-primary">
{!chatVar
? t(($) => $['chatVariable.modal.title'], { ns: 'workflow' })
: t(($) => $['chatVariable.modal.editTitle'], { ns: 'workflow' })}
<div className="flex items-center">
<div className="flex size-6 cursor-pointer items-center justify-center" onClick={onClose}>
<RiCloseLine className="size-4 text-text-tertiary" />
</div>
</div>
</div>
<div className="max-h-[480px] overflow-y-auto px-4 py-2">
<NameSection
name={name}
onBlur={(nextName) =>
validateVariableName({ name: nextName, notify, t: translateChatVariable })
}
onChange={handleNameChange}
placeholder={t(($) => $['chatVariable.modal.namePlaceholder'], { ns: 'workflow' }) || ''}
title={t(($) => $['chatVariable.modal.name'], { ns: 'workflow' })}
/>
<TypeSection
type={type}
list={typeList}
onSelect={handleTypeChange}
title={t(($) => $['chatVariable.modal.type'], { ns: 'workflow' })}
/>
<ValueSection
type={type}
value={value}
objectValue={objectValue}
editInJSON={editInJSON}
editorContent={editorContent}
editorMinHeight={editorMinHeight}
onArrayBoolChange={setValue}
onArrayChange={
type === ChatVarType.String || type === ChatVarType.Number
? handleStringOrNumberChange
: setValue
}
onEditorChange={handleEditorChange}
onEditorValueChange={handleEditorValueChange}
onObjectChange={setObjectValue}
onValueChange={setValue}
placeholder={placeholder}
t={translateChatVariable}
toggleLabelKey={
type === ChatVarType.Object ||
type === ChatVarType.ArrayString ||
type === ChatVarType.ArrayNumber ||
type === ChatVarType.ArrayBoolean
? getEditorToggleLabelKey(type, editInJSON)
: undefined
}
/>
<DescriptionSection
description={description}
maxLength={MAX_DESCRIPTION_LENGTH}
onChange={setDescription}
placeholder={
t(($) => $['chatVariable.modal.descriptionPlaceholder'], { ns: 'workflow' }) || ''
}
title={t(($) => $['chatVariable.modal.description'], { ns: 'workflow' })}
/>
</div>
<div className="flex flex-row-reverse rounded-b-2xl p-4 pt-2">
<div className="flex gap-2">
<Button onClick={onClose}>{t(($) => $['operation.cancel'], { ns: 'common' })}</Button>
<Button variant="primary" onClick={handleSave}>
{t(($) => $['operation.save'], { ns: 'common' })}
</Button>
</div>
</div>
</div>
)
}
export default ChatVariableModal