feat: prompt ide and fin direct ansewer node

This commit is contained in:
Joel
2024-02-20 16:52:22 +08:00
parent 291201db1c
commit 92219b5aad
10 changed files with 252 additions and 2 deletions

View File

@@ -0,0 +1,5 @@
<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon">
<path id="Icon_2" d="M11.6667 8.66667V10.3C11.6667 10.9534 11.6667 11.2801 11.5395 11.5297C11.4277 11.7492 11.2492 11.9277 11.0297 12.0395C10.7801 12.1667 10.4534 12.1667 9.8 12.1667H8.16667M5.83333 2.83333H4.2C3.54661 2.83333 3.21991 2.83333 2.97034 2.96049C2.75082 3.07234 2.57234 3.25082 2.46049 3.47034C2.33333 3.71991 2.33333 4.04661 2.33333 4.7V6.33333M8.75 5.75L12.25 2.25M12.25 2.25H8.75M12.25 2.25V5.75M5.25 9.25L1.75 12.75M1.75 12.75H5.25M1.75 12.75L1.75 9.25" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 679 B

View File

@@ -0,0 +1,39 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "14",
"height": "15",
"viewBox": "0 0 14 15",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon_2",
"d": "M11.6667 8.66667V10.3C11.6667 10.9534 11.6667 11.2801 11.5395 11.5297C11.4277 11.7492 11.2492 11.9277 11.0297 12.0395C10.7801 12.1667 10.4534 12.1667 9.8 12.1667H8.16667M5.83333 2.83333H4.2C3.54661 2.83333 3.21991 2.83333 2.97034 2.96049C2.75082 3.07234 2.57234 3.25082 2.46049 3.47034C2.33333 3.71991 2.33333 4.04661 2.33333 4.7V6.33333M8.75 5.75L12.25 2.25M12.25 2.25H8.75M12.25 2.25V5.75M5.25 9.25L1.75 12.75M1.75 12.75H5.25M1.75 12.75L1.75 9.25",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
},
"name": "Expand04"
}

View File

@@ -0,0 +1,16 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Expand04.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
Icon.displayName = 'Expand04'
export default Icon

View File

@@ -1,2 +1,3 @@
export { default as ChevronDown } from './ChevronDown'
export { default as Expand04 } from './Expand04'
export { default as HighPriority } from './HighPriority'

View File

@@ -0,0 +1,108 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import cn from 'classnames'
import copy from 'copy-to-clipboard'
import { useTranslation } from 'react-i18next'
import PromptEditorHeightResizeWrap from '@/app/components/app/configuration/config-prompt/prompt-editor-height-resize-wrap'
import PromptEditor from '@/app/components/base/prompt-editor'
import { Clipboard, ClipboardCheck } from '@/app/components/base/icons/src/vender/line/files'
import { Expand04 } from '@/app/components/base/icons/src/vender/solid/arrows'
import s from '@/app/components/app/configuration/config-prompt/style.module.css'
type Props = {
title: string
value: string
variables: string[]
onChange: (value: string) => void
}
const Editor: FC<Props> = ({
title,
value,
variables,
onChange,
}) => {
const { t } = useTranslation()
const minHeight = 98
const [editorHeight, setEditorHeight] = React.useState(minHeight)
const [isCopied, setIsCopied] = React.useState(false)
const handleCopy = useCallback(() => {
copy(value)
setIsCopied(true)
}, [value])
const [isExpanded, setIsExpanded] = React.useState(false)
const toggleExpand = useCallback(() => {
setIsExpanded(!isExpanded)
}, [isExpanded])
return (
<div className={cn(s.gradientBorder, '!rounded-[9px] shadow-md')}>
<div className='rounded-lg bg-white'>
<div className='pt-1 pl-3 pr-1 flex justify-between h-6 items-center'>
<div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div>
<div className='flex items-center'>
<div className='leading-[18px] text-xs font-medium text-gray-500'>{value.length}</div>
<div className='w-px h-3 ml-2 mr-3 bg-gray-200'></div>
{!isCopied
? (
<Clipboard className='mx-1 w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={handleCopy} />
)
: (
<ClipboardCheck className='mx-1 w-3.5 h-3.5 text-gray-500' />
)
}
<Expand04 className='ml-2 mr-2 w-3.5 h-3.5 text-gray-500 cursor-pointer' onClick={toggleExpand} />
</div>
</div>
<PromptEditorHeightResizeWrap
className='px-3 min-h-[102px] overflow-y-auto text-sm text-gray-700'
height={editorHeight}
minHeight={minHeight}
onHeightChange={setEditorHeight}
footer={(
<div className='pl-4 pb-2 flex'>
<div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{'{x} '}{t('workflow.nodes.common.insertVarTip')}</div>
</div>
)}
>
<PromptEditor
className='min-h-[84px]'
value={value}
contextBlock={{
show: true,
selectable: true,
datasets: [],
onAddContext: () => { },
}}
variableBlock={{
variables: variables.map(item => ({
name: item,
value: item,
})),
externalTools: [],
onAddExternalTool: () => { },
}}
historyBlock={{
show: true,
selectable: true,
history: {
user: 'user',
assistant: 'xxx',
},
onEditRole: () => { },
}}
queryBlock={{
show: true,
selectable: true,
}}
onChange={onChange}
onBlur={() => { }}
/>
</PromptEditorHeightResizeWrap>
</div>
</div>
)
}
export default React.memo(Editor)

View File

@@ -1,8 +1,47 @@
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import useConfig from './use-config'
import { mockData } from './mock'
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
import Field from '@/app/components/workflow/nodes/_base/components/field'
import AddButton from '@/app/components/base/button/add-button'
import Split from '@/app/components/workflow/nodes/_base/components/split'
import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
const i18nPrefix = 'workflow.nodes.directAnswer'
const Panel: FC = () => {
const { t } = useTranslation()
const readOnly = false
const {
inputs,
handleVarListChange,
handleAddVariable,
handleAnswerChange,
} = useConfig(mockData)
return (
<div>start panel inputs</div>
<div className='mt-2 px-4 space-y-4'>
<Field
title={t(`${i18nPrefix}.inputVars`)}
operations={
<AddButton onClick={handleAddVariable} />
}
>
<VarList
readonly={readOnly}
list={inputs.variables}
onChange={handleVarListChange}
/>
</Field>
<Split />
<Editor
title={t(`${i18nPrefix}.answer`)}
value={inputs.answer}
onChange={handleAnswerChange}
variables={inputs.variables.map(item => item.variable)}
/>
</div>
)
}

View File

@@ -0,0 +1,40 @@
import { useCallback, useState } from 'react'
import produce from 'immer'
import type { Variable } from '../../types'
import type { DirectAnswerNodeType } from './types'
const useConfig = (initInputs: DirectAnswerNodeType) => {
const [inputs, setInputs] = useState<DirectAnswerNodeType>(initInputs)
// variables
const handleVarListChange = useCallback((newList: Variable[]) => {
const newInputs = produce(inputs, (draft) => {
draft.variables = newList
})
setInputs(newInputs)
}, [inputs, setInputs])
const handleAddVariable = useCallback(() => {
const newInputs = produce(inputs, (draft) => {
draft.variables.push({
variable: '',
value_selector: [],
})
})
setInputs(newInputs)
}, [inputs, setInputs])
const handleAnswerChange = useCallback((value: string) => {
const newInputs = produce(inputs, (draft) => {
draft.answer = value
})
setInputs(newInputs)
}, [inputs, setInputs])
return {
inputs,
handleVarListChange,
handleAddVariable,
handleAnswerChange,
}
}
export default useConfig

View File

@@ -1,8 +1,8 @@
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import VarList from '../_base/components/variable/var-list'
import useConfig from './use-config'
import { mockData } from './mock'
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
import Field from '@/app/components/workflow/nodes/_base/components/field'
import AddButton from '@/app/components/base/button/add-button'
import Split from '@/app/components/workflow/nodes/_base/components/split'

View File

@@ -2,6 +2,7 @@ const translation = {
nodes: {
common: {
outputVars: 'Output Variables',
insertVarTip: 'Insert Variable',
},
directAnswer: {
answer: 'Answer',

View File

@@ -2,6 +2,7 @@ const translation = {
nodes: {
common: {
outputVars: '输出变量',
insertVarTip: '插入变量',
},
directAnswer: {
answer: '回复',