Add pipeline cancellation feature with UI and i18n support

- Add cancelPipeline API endpoint
- Add cancel button to status dialog
- Update status response type
- Add cancellation UI translations
- Handle cancellation request states

(cherry picked from commit f89b5ab101)
This commit is contained in:
yangdx 2025-10-24 15:30:27 +08:00 committed by Raphaël MANSUY
parent 687d2b6b13
commit 74d0a22020
7 changed files with 73 additions and 15 deletions

View file

@ -236,6 +236,7 @@ export type PipelineStatusResponse = {
batchs: number
cur_batch: number
request_pending: boolean
cancellation_requested?: boolean
latest_message: string
history_messages?: string[]
update_status?: Record<string, any>
@ -673,6 +674,14 @@ export const getPipelineStatus = async (): Promise<PipelineStatusResponse> => {
return response.data
}
export const cancelPipeline = async (): Promise<{
status: 'cancellation_requested' | 'not_busy'
message: string
}> => {
const response = await axiosInstance.post('/documents/cancel_pipeline')
return response.data
}
export const loginToServer = async (username: string, password: string): Promise<LoginResponse> => {
const formData = new FormData();
formData.append('username', username);

View file

@ -11,7 +11,7 @@ import {
DialogDescription
} from '@/components/ui/Dialog'
import Button from '@/components/ui/Button'
import { getPipelineStatus, PipelineStatusResponse } from '@/api/lightrag'
import { getPipelineStatus, cancelPipeline, PipelineStatusResponse } from '@/api/lightrag'
import { errorMessage } from '@/lib/utils'
import { cn } from '@/lib/utils'
@ -81,6 +81,23 @@ export default function PipelineStatusDialog({
return () => clearInterval(interval)
}, [open, t])
// Handle cancel pipeline
const handleCancelPipeline = async () => {
try {
const result = await cancelPipeline()
if (result.status === 'cancellation_requested') {
toast.success(t('documentPanel.pipelineStatus.cancelSuccess'))
} else if (result.status === 'not_busy') {
toast.info(t('documentPanel.pipelineStatus.cancelNotBusy'))
}
} catch (err) {
toast.error(t('documentPanel.pipelineStatus.cancelFailed', { error: errorMessage(err) }))
}
}
// Determine if cancel button should be enabled
const canCancel = status?.busy === true && !status?.cancellation_requested
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent
@ -142,16 +159,43 @@ export default function PipelineStatusDialog({
{/* Status Content */}
<div className="space-y-4 pt-4">
{/* Pipeline Status */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.busy')}:</div>
<div className={`h-2 w-2 rounded-full ${status?.busy ? 'bg-green-500' : 'bg-gray-300'}`} />
</div>
<div className="flex items-center gap-2">
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.requestPending')}:</div>
<div className={`h-2 w-2 rounded-full ${status?.request_pending ? 'bg-green-500' : 'bg-gray-300'}`} />
{/* Pipeline Status - with cancel button */}
<div className="flex flex-wrap items-center justify-between gap-4">
{/* Left side: Status indicators */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.busy')}:</div>
<div className={`h-2 w-2 rounded-full ${status?.busy ? 'bg-green-500' : 'bg-gray-300'}`} />
</div>
<div className="flex items-center gap-2">
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.requestPending')}:</div>
<div className={`h-2 w-2 rounded-full ${status?.request_pending ? 'bg-green-500' : 'bg-gray-300'}`} />
</div>
{/* Only show cancellation status when it's requested */}
{status?.cancellation_requested && (
<div className="flex items-center gap-2">
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.cancellationRequested')}:</div>
<div className="h-2 w-2 rounded-full bg-red-500" />
</div>
)}
</div>
{/* Right side: Cancel button - only show when pipeline is busy */}
{status?.busy && (
<Button
variant="destructive"
size="sm"
disabled={!canCancel}
onClick={handleCancelPipeline}
title={
status?.cancellation_requested
? t('documentPanel.pipelineStatus.cancelInProgress')
: t('documentPanel.pipelineStatus.cancelTooltip')
}
>
{t('documentPanel.pipelineStatus.cancelButton')}
</Button>
)}
</div>
{/* Job Information */}

View file

@ -165,7 +165,8 @@
"startTime": "وقت البدء",
"progress": "التقدم",
"unit": "دفعة",
"pipelineMessages": "رسائل خط الأنابيب",
"latestMessage": "آخر رسالة",
"historyMessages": "رسائل السجل",
"cancelButton": "إلغاء",
"cancelTooltip": "إلغاء معالجة خط الأنابيب",
"cancelInProgress": "الإلغاء قيد التقدم...",

View file

@ -165,7 +165,8 @@
"startTime": "Start Time",
"progress": "Progress",
"unit": "Batch",
"pipelineMessages": "Pipeline Messages",
"latestMessage": "Latest Message",
"historyMessages": "History Messages",
"cancelButton": "Cancel",
"cancelTooltip": "Cancel pipeline processing",
"cancelInProgress": "Cancellation in progress...",

View file

@ -165,7 +165,8 @@
"startTime": "Heure de Début",
"progress": "Progrès",
"unit": "Lot",
"pipelineMessages": "Messages de Pipeline",
"latestMessage": "Dernier Message",
"historyMessages": "Messages d'Historique",
"cancelButton": "Annuler",
"cancelTooltip": "Annuler le traitement du pipeline",
"cancelInProgress": "Annulation en cours...",

View file

@ -165,7 +165,8 @@
"startTime": "开始时间",
"progress": "进度",
"unit": "批",
"pipelineMessages": "流水线消息",
"latestMessage": "最新消息",
"historyMessages": "历史消息",
"cancelButton": "中断",
"cancelTooltip": "中断流水线处理",
"cancelInProgress": "取消请求进行中...",

View file

@ -165,7 +165,8 @@
"startTime": "開始時間",
"progress": "進度",
"unit": "批",
"pipelineMessages": "流水線消息",
"latestMessage": "最新消息",
"historyMessages": "歷史消息",
"cancelButton": "中斷",
"cancelTooltip": "中斷流水線處理",
"cancelInProgress": "取消請求進行中...",