mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-08 02:16:51 +08:00
fix: segment error tip & save segment disable when loading (#949)
This commit is contained in:
@@ -28,6 +28,7 @@ import AutoHeightTextarea from '@/app/components/base/auto-height-textarea/commo
|
|||||||
import Button from '@/app/components/base/button'
|
import Button from '@/app/components/base/button'
|
||||||
import NewSegmentModal from '@/app/components/datasets/documents/detail/new-segment-modal'
|
import NewSegmentModal from '@/app/components/datasets/documents/detail/new-segment-modal'
|
||||||
import TagInput from '@/app/components/base/tag-input'
|
import TagInput from '@/app/components/base/tag-input'
|
||||||
|
import { useEventEmitterContextContext } from '@/context/event-emitter'
|
||||||
|
|
||||||
export const SegmentIndexTag: FC<{ positionId: string | number; className?: string }> = ({ positionId, className }) => {
|
export const SegmentIndexTag: FC<{ positionId: string | number; className?: string }> = ({ positionId, className }) => {
|
||||||
const localPositionId = useMemo(() => {
|
const localPositionId = useMemo(() => {
|
||||||
@@ -66,6 +67,15 @@ export const SegmentDetail: FC<ISegmentDetailProps> = memo(({
|
|||||||
const [question, setQuestion] = useState(segInfo?.content || '')
|
const [question, setQuestion] = useState(segInfo?.content || '')
|
||||||
const [answer, setAnswer] = useState(segInfo?.answer || '')
|
const [answer, setAnswer] = useState(segInfo?.answer || '')
|
||||||
const [keywords, setKeywords] = useState<string[]>(segInfo?.keywords || [])
|
const [keywords, setKeywords] = useState<string[]>(segInfo?.keywords || [])
|
||||||
|
const { eventEmitter } = useEventEmitterContextContext()
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
eventEmitter?.useSubscription((v) => {
|
||||||
|
if (v === 'update-segment')
|
||||||
|
setLoading(true)
|
||||||
|
else
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setIsEditing(false)
|
setIsEditing(false)
|
||||||
@@ -129,7 +139,9 @@ export const SegmentDetail: FC<ISegmentDetailProps> = memo(({
|
|||||||
<Button
|
<Button
|
||||||
type='primary'
|
type='primary'
|
||||||
className='!h-7 !px-3 !py-[5px] text-xs font-medium !rounded-md'
|
className='!h-7 !px-3 !py-[5px] text-xs font-medium !rounded-md'
|
||||||
onClick={handleSave}>
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
{t('common.operation.save')}
|
{t('common.operation.save')}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
@@ -225,6 +237,7 @@ const Completed: FC<ICompletedProps> = ({
|
|||||||
const [allSegments, setAllSegments] = useState<Array<SegmentDetailModel[]>>([]) // all segments data
|
const [allSegments, setAllSegments] = useState<Array<SegmentDetailModel[]>>([]) // all segments data
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [total, setTotal] = useState<number | undefined>()
|
const [total, setTotal] = useState<number | undefined>()
|
||||||
|
const { eventEmitter } = useEventEmitterContextContext()
|
||||||
|
|
||||||
const onChangeStatus = ({ value }: Item) => {
|
const onChangeStatus = ({ value }: Item) => {
|
||||||
setSelectedStatus(value === 'all' ? 'all' : !!value)
|
setSelectedStatus(value === 'all' ? 'all' : !!value)
|
||||||
@@ -318,23 +331,29 @@ const Completed: FC<ICompletedProps> = ({
|
|||||||
if (keywords.length)
|
if (keywords.length)
|
||||||
params.keywords = keywords
|
params.keywords = keywords
|
||||||
|
|
||||||
const res = await updateSegment({ datasetId, documentId, segmentId, body: params })
|
try {
|
||||||
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
eventEmitter?.emit('update-segment')
|
||||||
onCloseModal()
|
const res = await updateSegment({ datasetId, documentId, segmentId, body: params })
|
||||||
for (const item of allSegments) {
|
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
||||||
for (const seg of item) {
|
onCloseModal()
|
||||||
if (seg.id === segmentId) {
|
for (const item of allSegments) {
|
||||||
seg.answer = res.data.answer
|
for (const seg of item) {
|
||||||
seg.content = res.data.content
|
if (seg.id === segmentId) {
|
||||||
seg.keywords = res.data.keywords
|
seg.answer = res.data.answer
|
||||||
seg.word_count = res.data.word_count
|
seg.content = res.data.content
|
||||||
seg.hit_count = res.data.hit_count
|
seg.keywords = res.data.keywords
|
||||||
seg.index_node_hash = res.data.index_node_hash
|
seg.word_count = res.data.word_count
|
||||||
seg.enabled = res.data.enabled
|
seg.hit_count = res.data.hit_count
|
||||||
|
seg.index_node_hash = res.data.index_node_hash
|
||||||
|
seg.enabled = res.data.enabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setAllSegments([...allSegments])
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
eventEmitter?.emit('')
|
||||||
}
|
}
|
||||||
setAllSegments([...allSegments])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
|
|||||||
const [answer, setAnswer] = useState('')
|
const [answer, setAnswer] = useState('')
|
||||||
const { datasetId, documentId } = useParams()
|
const { datasetId, documentId } = useParams()
|
||||||
const [keywords, setKeywords] = useState<string[]>([])
|
const [keywords, setKeywords] = useState<string[]>([])
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
setQuestion('')
|
setQuestion('')
|
||||||
@@ -60,10 +61,16 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
|
|||||||
if (keywords?.length)
|
if (keywords?.length)
|
||||||
params.keywords = keywords
|
params.keywords = keywords
|
||||||
|
|
||||||
await addSegment({ datasetId, documentId, body: params })
|
setLoading(true)
|
||||||
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
try {
|
||||||
handleCancel()
|
await addSegment({ datasetId, documentId, body: params })
|
||||||
onSave()
|
notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
|
||||||
|
handleCancel()
|
||||||
|
onSave()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
@@ -136,7 +143,9 @@ const NewSegmentModal: FC<NewSegmentModalProps> = memo(({
|
|||||||
<Button
|
<Button
|
||||||
type='primary'
|
type='primary'
|
||||||
className='!h-9 !px-4 !py-2 text-sm font-medium !rounded-lg'
|
className='!h-9 !px-4 !py-2 text-sm font-medium !rounded-lg'
|
||||||
onClick={handleSave}>
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
{t('common.operation.save')}
|
{t('common.operation.save')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import NotionIcon from '@/app/components/base/notion-icon'
|
|||||||
import ProgressBar from '@/app/components/base/progress-bar'
|
import ProgressBar from '@/app/components/base/progress-bar'
|
||||||
import { DataSourceType, type DocumentDisplayStatus, type SimpleDocumentDetail } from '@/models/datasets'
|
import { DataSourceType, type DocumentDisplayStatus, type SimpleDocumentDetail } from '@/models/datasets'
|
||||||
import type { CommonResponse } from '@/models/common'
|
import type { CommonResponse } from '@/models/common'
|
||||||
import { FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
|
|
||||||
import { DotsHorizontal, HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
|
import { DotsHorizontal, HelpCircle } from '@/app/components/base/icons/src/vender/line/general'
|
||||||
|
|
||||||
export const SettingsIcon: FC<{ className?: string }> = ({ className }) => {
|
export const SettingsIcon: FC<{ className?: string }> = ({ className }) => {
|
||||||
@@ -89,7 +88,9 @@ export const StatusItem: FC<{
|
|||||||
errorMessage && (
|
errorMessage && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
selector='dataset-document-detail-item-status'
|
selector='dataset-document-detail-item-status'
|
||||||
content={errorMessage}
|
htmlContent={
|
||||||
|
<div className='max-w-[260px]'>{errorMessage}</div>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<HelpCircle className='ml-1 w-[14px] h-[14px] text-gray-700' />
|
<HelpCircle className='ml-1 w-[14px] h-[14px] text-gray-700' />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -152,73 +153,6 @@ export const OperationAction: FC<{
|
|||||||
onUpdate(operationName)
|
onUpdate(operationName)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Operations = (props: any) => <div className='w-full py-1'>
|
|
||||||
{!isListScene && <>
|
|
||||||
<div className='flex justify-between items-center mx-4 pt-2'>
|
|
||||||
<span className={cn(s.actionName, 'font-medium')}>
|
|
||||||
{!archived && enabled ? t('datasetDocuments.list.index.enable') : t('datasetDocuments.list.index.disable')}
|
|
||||||
</span>
|
|
||||||
<Tooltip
|
|
||||||
selector={`detail-switch-${id}`}
|
|
||||||
content={t('datasetDocuments.list.action.enableWarning') as string}
|
|
||||||
className='!font-semibold'
|
|
||||||
disabled={!archived}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<Switch
|
|
||||||
defaultValue={archived ? false : enabled}
|
|
||||||
onChange={v => !archived && onOperate(v ? 'enable' : 'disable')}
|
|
||||||
disabled={archived}
|
|
||||||
size='md'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<div className='mx-4 pb-1 pt-0.5 text-xs text-gray-500'>
|
|
||||||
{!archived && enabled ? t('datasetDocuments.list.index.enableTip') : t('datasetDocuments.list.index.disableTip')}
|
|
||||||
</div>
|
|
||||||
<Divider />
|
|
||||||
</>}
|
|
||||||
{!archived && (
|
|
||||||
<>
|
|
||||||
<div className={s.actionItem} onClick={() => router.push(`/datasets/${datasetId}/documents/${detail.id}/settings`)}>
|
|
||||||
<SettingsIcon />
|
|
||||||
<span className={s.actionName}>{t('datasetDocuments.list.action.settings')}</span>
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
!isListScene && (
|
|
||||||
<div className={s.actionItem} onClick={showNewSegmentModal}>
|
|
||||||
<FilePlus02 className='w-4 h-4 text-gray-500' />
|
|
||||||
<span className={s.actionName}>{t('datasetDocuments.list.action.add')}</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
data_source_type === 'notion_import' && (
|
|
||||||
<div className={s.actionItem} onClick={() => onOperate('sync')}>
|
|
||||||
<SyncIcon />
|
|
||||||
<span className={s.actionName}>{t('datasetDocuments.list.action.sync')}</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<Divider className='my-1' />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{!archived && <div className={s.actionItem} onClick={() => onOperate('archive')}>
|
|
||||||
<ArchiveIcon />
|
|
||||||
<span className={s.actionName}>{t('datasetDocuments.list.action.archive')}</span>
|
|
||||||
</div>}
|
|
||||||
<div
|
|
||||||
className={cn(s.actionItem, s.deleteActionItem, 'group')}
|
|
||||||
onClick={() => {
|
|
||||||
setShowModal(true)
|
|
||||||
props?.onClose()
|
|
||||||
}}>
|
|
||||||
<TrashIcon className={'w-4 h-4 stroke-current text-gray-500 stroke-2 group-hover:text-red-500'} />
|
|
||||||
<span className={cn(s.actionName, 'group-hover:text-red-500')}>{t('datasetDocuments.list.action.delete')}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
return <div className='flex items-center' onClick={e => e.stopPropagation()}>
|
return <div className='flex items-center' onClick={e => e.stopPropagation()}>
|
||||||
{isListScene && <>
|
{isListScene && <>
|
||||||
{archived
|
{archived
|
||||||
|
|||||||
Reference in New Issue
Block a user