mirror of https://github.com/langgenius/dify.git
feat: clear all annotation (#22878)
Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
31985d94fa
commit
ee50a2bcd5
|
|
@ -123,6 +123,17 @@ class AnnotationListApi(Resource):
|
||||||
}
|
}
|
||||||
return response, 200
|
return response, 200
|
||||||
|
|
||||||
|
@setup_required
|
||||||
|
@login_required
|
||||||
|
@account_initialization_required
|
||||||
|
def delete(self, app_id):
|
||||||
|
if not current_user.is_editor:
|
||||||
|
raise Forbidden()
|
||||||
|
|
||||||
|
app_id = str(app_id)
|
||||||
|
AppAnnotationService.clear_all_annotations(app_id)
|
||||||
|
return {"result": "success"}, 204
|
||||||
|
|
||||||
|
|
||||||
class AnnotationExportApi(Resource):
|
class AnnotationExportApi(Resource):
|
||||||
@setup_required
|
@setup_required
|
||||||
|
|
|
||||||
|
|
@ -440,3 +440,27 @@ class AppAnnotationService:
|
||||||
"embedding_model_name": collection_binding_detail.model_name,
|
"embedding_model_name": collection_binding_detail.model_name,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear_all_annotations(cls, app_id: str) -> dict:
|
||||||
|
app = (
|
||||||
|
db.session.query(App)
|
||||||
|
.filter(App.id == app_id, App.tenant_id == current_user.current_tenant_id, App.status == "normal")
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
|
||||||
|
if not app:
|
||||||
|
raise NotFound("App not found")
|
||||||
|
|
||||||
|
annotations_query = db.session.query(MessageAnnotation).filter(MessageAnnotation.app_id == app_id)
|
||||||
|
for annotation in annotations_query.yield_per(100):
|
||||||
|
annotation_hit_histories_query = db.session.query(AppAnnotationHitHistory).filter(
|
||||||
|
AppAnnotationHitHistory.annotation_id == annotation.id
|
||||||
|
)
|
||||||
|
for annotation_hit_history in annotation_hit_histories_query.yield_per(100):
|
||||||
|
db.session.delete(annotation_hit_history)
|
||||||
|
|
||||||
|
db.session.delete(annotation)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return {"result": "success"}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import type { FC } from 'react'
|
||||||
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import Confirm from '@/app/components/base/confirm'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isShow: boolean
|
||||||
|
onHide: () => void
|
||||||
|
onConfirm: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClearAllAnnotationsConfirmModal: FC<Props> = ({
|
||||||
|
isShow,
|
||||||
|
onHide,
|
||||||
|
onConfirm,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Confirm
|
||||||
|
isShow={isShow}
|
||||||
|
onCancel={onHide}
|
||||||
|
onConfirm={onConfirm}
|
||||||
|
type='danger'
|
||||||
|
title={t('appAnnotation.table.header.clearAllConfirm')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(ClearAllAnnotationsConfirmModal)
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
'use client'
|
'use client'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import React, { Fragment, useEffect, useState } from 'react'
|
import React, { Fragment, useEffect, useState } from 'react'
|
||||||
|
import ClearAllAnnotationsConfirmModal from '../clear-all-annotations-confirm-modal'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import {
|
import {
|
||||||
RiAddLine,
|
RiAddLine,
|
||||||
|
RiDeleteBinLine,
|
||||||
RiMoreFill,
|
RiMoreFill,
|
||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import { useContext } from 'use-context-selector'
|
import { useContext } from 'use-context-selector'
|
||||||
|
|
@ -22,6 +24,7 @@ import { ChevronRight } from '@/app/components/base/icons/src/vender/line/arrows
|
||||||
|
|
||||||
import I18n from '@/context/i18n'
|
import I18n from '@/context/i18n'
|
||||||
import { fetchExportAnnotationList } from '@/service/annotation'
|
import { fetchExportAnnotationList } from '@/service/annotation'
|
||||||
|
import { clearAllAnnotations } from '@/service/annotation'
|
||||||
import { LanguagesSupported } from '@/i18n-config/language'
|
import { LanguagesSupported } from '@/i18n-config/language'
|
||||||
|
|
||||||
const CSV_HEADER_QA_EN = ['Question', 'Answer']
|
const CSV_HEADER_QA_EN = ['Question', 'Answer']
|
||||||
|
|
@ -76,7 +79,21 @@ const HeaderOptions: FC<Props> = ({
|
||||||
}, [controlUpdateList])
|
}, [controlUpdateList])
|
||||||
|
|
||||||
const [showBulkImportModal, setShowBulkImportModal] = useState(false)
|
const [showBulkImportModal, setShowBulkImportModal] = useState(false)
|
||||||
|
const [showClearConfirm, setShowClearConfirm] = useState(false)
|
||||||
|
const handleClearAll = () => {
|
||||||
|
setShowClearConfirm(true)
|
||||||
|
}
|
||||||
|
const handleConfirmed = async () => {
|
||||||
|
try {
|
||||||
|
await clearAllAnnotations(appId)
|
||||||
|
onAdded()
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setShowClearConfirm(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
const Operations = () => {
|
const Operations = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full py-1">
|
<div className="w-full py-1">
|
||||||
|
|
@ -125,6 +142,15 @@ const HeaderOptions: FC<Props> = ({
|
||||||
</MenuItems>
|
</MenuItems>
|
||||||
</Transition>
|
</Transition>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
<button
|
||||||
|
onClick={handleClearAll}
|
||||||
|
className='mx-1 flex h-9 w-[calc(100%_-_8px)] cursor-pointer items-center space-x-2 rounded-lg px-3 py-2 text-red-600 hover:bg-red-50 disabled:opacity-50'
|
||||||
|
>
|
||||||
|
<RiDeleteBinLine className='h-4 w-4'/>
|
||||||
|
<span className='system-sm-regular grow text-left'>
|
||||||
|
{t('appAnnotation.table.header.clearAll')}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -169,6 +195,15 @@ const HeaderOptions: FC<Props> = ({
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
showClearConfirm && (
|
||||||
|
<ClearAllAnnotationsConfirmModal
|
||||||
|
isShow={showClearConfirm}
|
||||||
|
onHide={() => setShowClearConfirm(false)}
|
||||||
|
onConfirm={handleConfirmed}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ const translation = {
|
||||||
addAnnotation: 'Add Annotation',
|
addAnnotation: 'Add Annotation',
|
||||||
bulkImport: 'Bulk Import',
|
bulkImport: 'Bulk Import',
|
||||||
bulkExport: 'Bulk Export',
|
bulkExport: 'Bulk Export',
|
||||||
clearAll: 'Clear All Annotation',
|
clearAll: 'Delete All',
|
||||||
|
clearAllConfirm: 'Delete all annotations?',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
editModal: {
|
editModal: {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ const translation = {
|
||||||
addAnnotation: '注釈を追加',
|
addAnnotation: '注釈を追加',
|
||||||
bulkImport: '一括インポート',
|
bulkImport: '一括インポート',
|
||||||
bulkExport: '一括エクスポート',
|
bulkExport: '一括エクスポート',
|
||||||
clearAll: 'すべての注釈をクリア',
|
clearAll: 'すべて削除',
|
||||||
|
clearAllConfirm: 'すべての寸法を削除?',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
editModal: {
|
editModal: {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@ const translation = {
|
||||||
addAnnotation: '添加标注',
|
addAnnotation: '添加标注',
|
||||||
bulkImport: '批量导入',
|
bulkImport: '批量导入',
|
||||||
bulkExport: '批量导出',
|
bulkExport: '批量导出',
|
||||||
clearAll: '删除所有标注',
|
clearAll: '删除所有',
|
||||||
|
clearAllConfirm: '删除所有标注?',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
editModal: {
|
editModal: {
|
||||||
|
|
|
||||||
|
|
@ -63,3 +63,7 @@ export const delAnnotation = (appId: string, annotationId: string) => {
|
||||||
export const fetchHitHistoryList = (appId: string, annotationId: string, params: Record<string, any>) => {
|
export const fetchHitHistoryList = (appId: string, annotationId: string, params: Record<string, any>) => {
|
||||||
return get(`apps/${appId}/annotations/${annotationId}/hit-histories`, { params })
|
return get(`apps/${appId}/annotations/${annotationId}/hit-histories`, { params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const clearAllAnnotations = (appId: string): Promise<any> => {
|
||||||
|
return del(`apps/${appId}/annotations`)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue