feat: add functionality to regenerate child chunks and enhance UI components for segment management
parent
6055e27050
commit
b4a6ec077f
@ -0,0 +1,81 @@
|
|||||||
|
import React, { type FC, useMemo } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useKeyPress } from 'ahooks'
|
||||||
|
import { useDocumentContext } from '../../index'
|
||||||
|
import Button from '@/app/components/base/button'
|
||||||
|
import { getKeyboardKeyCodeBySystem, getKeyboardKeyNameBySystem } from '@/app/components/workflow/utils'
|
||||||
|
|
||||||
|
type IActionButtonsProps = {
|
||||||
|
handleCancel: () => void
|
||||||
|
handleSave: (needRegenerate: boolean) => void
|
||||||
|
loading: boolean
|
||||||
|
actionType?: 'edit' | 'add'
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActionButtons: FC<IActionButtonsProps> = ({
|
||||||
|
handleCancel,
|
||||||
|
handleSave,
|
||||||
|
loading,
|
||||||
|
actionType = 'edit',
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [mode, parentMode] = useDocumentContext(s => [s.mode, s.parentMode])
|
||||||
|
|
||||||
|
useKeyPress(['esc'], (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
handleCancel()
|
||||||
|
})
|
||||||
|
|
||||||
|
useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.s`, (e) => {
|
||||||
|
if (loading)
|
||||||
|
return
|
||||||
|
e.preventDefault()
|
||||||
|
handleSave(false)
|
||||||
|
}
|
||||||
|
, { exactMatch: true, useCapture: true })
|
||||||
|
|
||||||
|
const isParentChildParagraphMode = useMemo(() => {
|
||||||
|
return mode === 'hierarchical' && parentMode === 'paragraph'
|
||||||
|
}, [mode, parentMode])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex items-center gap-x-2'>
|
||||||
|
<Button
|
||||||
|
onClick={handleCancel}
|
||||||
|
>
|
||||||
|
<div className='flex items-center gap-x-1'>
|
||||||
|
<span className='text-components-button-secondary-text system-sm-medium'>{t('common.operation.cancel')}</span>
|
||||||
|
<span className='px-[1px] bg-components-kbd-bg-gray rounded-[4px] text-text-tertiary system-kbd'>ESC</span>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
{(isParentChildParagraphMode && actionType === 'edit')
|
||||||
|
? <Button
|
||||||
|
onClick={handleSave.bind(null, true)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<span className='text-components-button-secondary-text system-sm-medium'>
|
||||||
|
{t('datasetDocuments.segment.saveAndRegenerate')}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
<Button
|
||||||
|
variant='primary'
|
||||||
|
onClick={handleSave.bind(null, false)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<div className='flex items-center gap-x-1'>
|
||||||
|
<span className='text-components-button-primary-text'>{t('common.operation.save')}</span>
|
||||||
|
<div className='flex items-center gap-x-0.5'>
|
||||||
|
<span className='w-4 h-4 bg-components-kbd-bg-white rounded-[4px] text-text-primary-on-surface system-kbd capitalize'>{getKeyboardKeyNameBySystem('ctrl')}</span>
|
||||||
|
<span className='w-4 h-4 bg-components-kbd-bg-white rounded-[4px] text-text-primary-on-surface system-kbd'>S</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionButtons.displayName = 'ActionButtons'
|
||||||
|
|
||||||
|
export default React.memo(ActionButtons)
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import React, { type FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
import Checkbox from '@/app/components/base/checkbox'
|
||||||
|
|
||||||
|
type AddAnotherProps = {
|
||||||
|
className?: string
|
||||||
|
isChecked: boolean
|
||||||
|
onCheck: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AddAnother: FC<AddAnotherProps> = ({
|
||||||
|
className,
|
||||||
|
isChecked,
|
||||||
|
onCheck,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames('flex items-center gap-x-1 pl-1', className)}>
|
||||||
|
<Checkbox
|
||||||
|
key='add-another-checkbox'
|
||||||
|
className='shrink-0'
|
||||||
|
checked={isChecked}
|
||||||
|
onCheck={onCheck}
|
||||||
|
/>
|
||||||
|
<span className='text-text-tertiary system-xs-medium'>{t('datasetDocuments.segment.addAnother')}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(AddAnother)
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
import React, { type FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import AutoHeightTextarea from '@/app/components/base/auto-height-textarea/common'
|
||||||
|
|
||||||
|
type IChunkContentProps = {
|
||||||
|
question: string
|
||||||
|
answer: string
|
||||||
|
onQuestionChange: (question: string) => void
|
||||||
|
onAnswerChange: (answer: string) => void
|
||||||
|
isEditMode?: boolean
|
||||||
|
docForm: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChunkContent: FC<IChunkContentProps> = ({
|
||||||
|
question,
|
||||||
|
answer,
|
||||||
|
onQuestionChange,
|
||||||
|
onAnswerChange,
|
||||||
|
isEditMode,
|
||||||
|
docForm,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
if (docForm === 'qa_model') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='mb-1 text-xs font-medium text-gray-500'>QUESTION</div>
|
||||||
|
<AutoHeightTextarea
|
||||||
|
outerClassName='mb-4'
|
||||||
|
className='leading-6 text-md text-gray-800'
|
||||||
|
value={question}
|
||||||
|
placeholder={t('datasetDocuments.segment.questionPlaceholder') || ''}
|
||||||
|
onChange={e => onQuestionChange(e.target.value)}
|
||||||
|
disabled={!isEditMode}
|
||||||
|
/>
|
||||||
|
<div className='mb-1 text-xs font-medium text-gray-500'>ANSWER</div>
|
||||||
|
<AutoHeightTextarea
|
||||||
|
outerClassName='mb-4'
|
||||||
|
className='leading-6 text-md text-gray-800'
|
||||||
|
value={answer}
|
||||||
|
placeholder={t('datasetDocuments.segment.answerPlaceholder') || ''}
|
||||||
|
onChange={e => onAnswerChange(e.target.value)}
|
||||||
|
disabled={!isEditMode}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AutoHeightTextarea
|
||||||
|
className='body-md-regular text-text-secondary tracking-[-0.07px] caret-[#295EFF]'
|
||||||
|
value={question}
|
||||||
|
placeholder={t('datasetDocuments.segment.contentPlaceholder') || ''}
|
||||||
|
onChange={e => onQuestionChange(e.target.value)}
|
||||||
|
disabled={!isEditMode}
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkContent.displayName = 'ChunkContent'
|
||||||
|
|
||||||
|
export default React.memo(ChunkContent)
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import React, { type FC } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import classNames from '@/utils/classnames'
|
||||||
|
import type { SegmentDetailModel } from '@/models/datasets'
|
||||||
|
import TagInput from '@/app/components/base/tag-input'
|
||||||
|
|
||||||
|
type IKeywordsProps = {
|
||||||
|
segInfo?: Partial<SegmentDetailModel> & { id: string }
|
||||||
|
className?: string
|
||||||
|
keywords: string[]
|
||||||
|
onKeywordsChange: (keywords: string[]) => void
|
||||||
|
isEditMode?: boolean
|
||||||
|
actionType?: 'edit' | 'add' | 'view'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Keywords: FC<IKeywordsProps> = ({
|
||||||
|
segInfo,
|
||||||
|
className,
|
||||||
|
keywords,
|
||||||
|
onKeywordsChange,
|
||||||
|
isEditMode,
|
||||||
|
actionType = 'view',
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
return (
|
||||||
|
<div className={classNames('flex flex-col', className)}>
|
||||||
|
<div className='text-text-tertiary system-xs-medium-uppercase'>{t('datasetDocuments.segment.keywords')}</div>
|
||||||
|
<div className='text-text-tertiary w-full max-h-[200px] overflow-auto flex flex-wrap gap-1'>
|
||||||
|
{(!segInfo?.keywords?.length && actionType === 'view')
|
||||||
|
? '-'
|
||||||
|
: (
|
||||||
|
<TagInput
|
||||||
|
items={keywords}
|
||||||
|
onChange={newKeywords => onKeywordsChange(newKeywords)}
|
||||||
|
disableAdd={!isEditMode}
|
||||||
|
disableRemove={!isEditMode || (keywords.length === 1)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Keywords.displayName = 'Keywords'
|
||||||
|
|
||||||
|
export default React.memo(Keywords)
|
||||||
Loading…
Reference in New Issue