From 65f0378e430c5bfccb816545b6712c2e27d15edb Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 29 Feb 2024 11:37:53 +0800 Subject: [PATCH] feat: classlist crud --- .../_base/components/editor/text-editor.tsx | 5 +- .../components/class-item.tsx | 77 +++++++++++++++++++ .../components/class-list.tsx | 42 ++++++---- web/i18n/en-US/workflow.ts | 3 + web/i18n/zh-Hans/workflow.ts | 5 +- 5 files changed, 115 insertions(+), 17 deletions(-) create mode 100644 web/app/components/workflow/nodes/question-classifier/components/class-item.tsx diff --git a/web/app/components/workflow/nodes/_base/components/editor/text-editor.tsx b/web/app/components/workflow/nodes/_base/components/editor/text-editor.tsx index 2e0d9f1049..85e2bb5d42 100644 --- a/web/app/components/workflow/nodes/_base/components/editor/text-editor.tsx +++ b/web/app/components/workflow/nodes/_base/components/editor/text-editor.tsx @@ -11,6 +11,7 @@ type Props = { headerRight?: JSX.Element minHeight?: number onBlur?: () => void + placeholder?: string } const TextEditor: FC = ({ @@ -20,6 +21,7 @@ const TextEditor: FC = ({ headerRight, minHeight, onBlur, + placeholder, }) => { const [isFocus, { setTrue: setIsFocus, @@ -45,7 +47,8 @@ const TextEditor: FC = ({ onChange={e => onChange(e.target.value)} onFocus={setIsFocus} onBlur={handleBlur} - className='w-full h-full p-3 resize-none bg-transparent' + className='w-full h-full px-3 resize-none bg-transparent border-none focus:outline-none leading-[18px] text-[13px] font-normal text-gray-900 placeholder:text-gray-300' + placeholder={placeholder} /> diff --git a/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx b/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx new file mode 100644 index 0000000000..bcaa7ecb79 --- /dev/null +++ b/web/app/components/workflow/nodes/question-classifier/components/class-item.tsx @@ -0,0 +1,77 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import { useBoolean } from 'ahooks' +import type { Topic } from '../types' +import TextEditor from '../../_base/components/editor/text-editor' +import { Trash03 } from '@/app/components/base/icons/src/vender/line/general' + +const i18nPrefix = 'workflow.nodes.questionClassifiers' + +type Props = { + payload: Topic + onChange: (payload: Topic) => void + onRemove: () => void +} + +const ClassItem: FC = ({ + payload, + onChange, + onRemove, +}) => { + const { t } = useTranslation() + const [isEdit, { + setTrue: setIsEditTrue, + setFalse: setIsEditFalse, + }] = useBoolean(false) + + const handleTopicChange = useCallback((value: string) => { + onChange({ ...payload, topic: value }) + }, [onChange, payload]) + + const handleClassNameChange = useCallback((e: React.ChangeEvent) => { + onChange({ ...payload, name: e.target.value }) + }, [onChange, payload]) + return ( + +
+ {isEdit + ? ( + + ) + :
+ {payload.name} +
} +
+ } + value={payload.topic} + onChange={handleTopicChange} + placeholder={t(`${i18nPrefix}.topicPlaceholder`)!} + headerRight={( +
+
{payload.topic.length}
+
+ +
+ )} + minHeight={64} + /> + ) +} +export default React.memo(ClassItem) diff --git a/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx b/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx index 905d323edc..319da67aba 100644 --- a/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx +++ b/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx @@ -2,9 +2,13 @@ import type { FC } from 'react' import React, { useCallback } from 'react' import produce from 'immer' -import TextEditor from '../../_base/components/editor/text-editor' +import { useTranslation } from 'react-i18next' import AddButton from '../../_base/components/add-button' +import Item from './class-item' import type { Topic } from '@/app/components/workflow/nodes/question-classifier/types' + +const i18nPrefix = 'workflow.nodes.questionClassifiers' + type Props = { list: Topic[] onChange: (list: Topic[]) => void @@ -14,43 +18,51 @@ const ClassList: FC = ({ list, onChange, }) => { - const handleTopicChange = useCallback((index: number) => { - return (value: string) => { + const { t } = useTranslation() + + const handleClassChange = useCallback((index: number) => { + return (value: Topic) => { const newList = produce(list, (draft) => { - draft[index].topic = value + draft[index] = value }) onChange(newList) } }, [list, onChange]) - const handleAddTopic = useCallback(() => { + const handleAddClass = useCallback(() => { const newList = produce(list, (draft) => { - draft.push({ id: '', name: 'topic aaa', topic: 'aaa' }) + draft.push({ id: '', name: t(`${i18nPrefix}.class`) + (list.length + 1), topic: '' }) }) onChange(newList) }, [list, onChange]) + const handleRemoveClass = useCallback((index: number) => { + return () => { + const newList = produce(list, (draft) => { + draft.splice(index, 1) + }) + onChange(newList) + } + }, [list, onChange]) + // Todo Remove; edit topic name return (
{ list.map((item, index) => { return ( - - {/* can edit */} -
{item.name}
-
} + ) }) } ) diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index 834232f34c..ab68d01d21 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -129,7 +129,10 @@ const translation = { model: 'model', inputVars: 'Input Variables', class: 'Class', + classNamePlaceholder: 'Write your class name', advancedSetting: 'Advanced Setting', + topicPlaceholder: 'Write your topic name', + addClass: 'Add Class', }, }, } diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index aa5804b9b2..37c92fd95d 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -127,8 +127,11 @@ const translation = { questionClassifiers: { model: '模型', inputVars: '输入变量', - class: '类别', + class: '分类', + classNamePlaceholder: '输入你的分类名称', advancedSetting: '高级设置', + topicPlaceholder: '在这里输入你的主题内容', + addClass: '添加分类', }, }, }