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
This commit is contained in:
parent
78ad8873b8
commit
f89b5ab101
7 changed files with 125 additions and 32 deletions
|
|
@ -242,6 +242,7 @@ export type PipelineStatusResponse = {
|
||||||
batchs: number
|
batchs: number
|
||||||
cur_batch: number
|
cur_batch: number
|
||||||
request_pending: boolean
|
request_pending: boolean
|
||||||
|
cancellation_requested?: boolean
|
||||||
latest_message: string
|
latest_message: string
|
||||||
history_messages?: string[]
|
history_messages?: string[]
|
||||||
update_status?: Record<string, any>
|
update_status?: Record<string, any>
|
||||||
|
|
@ -691,6 +692,14 @@ export const getPipelineStatus = async (): Promise<PipelineStatusResponse> => {
|
||||||
return response.data
|
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> => {
|
export const loginToServer = async (username: string, password: string): Promise<LoginResponse> => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('username', username);
|
formData.append('username', username);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
DialogDescription
|
DialogDescription
|
||||||
} from '@/components/ui/Dialog'
|
} from '@/components/ui/Dialog'
|
||||||
import Button from '@/components/ui/Button'
|
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 { errorMessage } from '@/lib/utils'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
|
@ -81,6 +81,23 @@ export default function PipelineStatusDialog({
|
||||||
return () => clearInterval(interval)
|
return () => clearInterval(interval)
|
||||||
}, [open, t])
|
}, [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 (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
|
|
@ -142,16 +159,43 @@ export default function PipelineStatusDialog({
|
||||||
|
|
||||||
{/* Status Content */}
|
{/* Status Content */}
|
||||||
<div className="space-y-4 pt-4">
|
<div className="space-y-4 pt-4">
|
||||||
{/* Pipeline Status */}
|
{/* Pipeline Status - with cancel button */}
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex flex-wrap items-center justify-between gap-4">
|
||||||
<div className="flex items-center gap-2">
|
{/* Left side: Status indicators */}
|
||||||
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.busy')}:</div>
|
<div className="flex items-center gap-4">
|
||||||
<div className={`h-2 w-2 rounded-full ${status?.busy ? 'bg-green-500' : 'bg-gray-300'}`} />
|
<div className="flex items-center gap-2">
|
||||||
</div>
|
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.busy')}:</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className={`h-2 w-2 rounded-full ${status?.busy ? 'bg-green-500' : 'bg-gray-300'}`} />
|
||||||
<div className="text-sm font-medium">{t('documentPanel.pipelineStatus.requestPending')}:</div>
|
</div>
|
||||||
<div className={`h-2 w-2 rounded-full ${status?.request_pending ? 'bg-green-500' : 'bg-gray-300'}`} />
|
<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>
|
</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>
|
</div>
|
||||||
|
|
||||||
{/* Job Information */}
|
{/* Job Information */}
|
||||||
|
|
|
||||||
|
|
@ -157,17 +157,25 @@
|
||||||
"hideFileNameTooltip": "إخفاء اسم الملف"
|
"hideFileNameTooltip": "إخفاء اسم الملف"
|
||||||
},
|
},
|
||||||
"pipelineStatus": {
|
"pipelineStatus": {
|
||||||
"title": "حالة خط المعالجة",
|
"title": "حالة خط الأنابيب",
|
||||||
"busy": "خط المعالجة مشغول",
|
"busy": "خط الأنابيب مشغول",
|
||||||
"requestPending": "الطلب معلق",
|
"requestPending": "طلب معلق",
|
||||||
|
"cancellationRequested": "طلب الإلغاء",
|
||||||
"jobName": "اسم المهمة",
|
"jobName": "اسم المهمة",
|
||||||
"startTime": "وقت البدء",
|
"startTime": "وقت البدء",
|
||||||
"progress": "التقدم",
|
"progress": "التقدم",
|
||||||
"unit": "دفعة",
|
"unit": "دفعة",
|
||||||
"latestMessage": "آخر رسالة",
|
"latestMessage": "آخر رسالة",
|
||||||
"historyMessages": "سجل الرسائل",
|
"historyMessages": "رسائل السجل",
|
||||||
|
"cancelButton": "إلغاء",
|
||||||
|
"cancelTooltip": "إلغاء معالجة خط الأنابيب",
|
||||||
|
"cancelInProgress": "الإلغاء قيد التقدم...",
|
||||||
|
"pipelineNotRunning": "خط الأنابيب غير قيد التشغيل",
|
||||||
|
"cancelSuccess": "تم طلب إلغاء خط الأنابيب",
|
||||||
|
"cancelFailed": "فشل إلغاء خط الأنابيب\n{{error}}",
|
||||||
|
"cancelNotBusy": "خط الأنابيب غير قيد التشغيل، لا حاجة للإلغاء",
|
||||||
"errors": {
|
"errors": {
|
||||||
"fetchFailed": "فشل في جلب حالة خط المعالجة\n{{error}}"
|
"fetchFailed": "فشل في جلب حالة خط الأنابيب\n{{error}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -160,14 +160,22 @@
|
||||||
"title": "Pipeline Status",
|
"title": "Pipeline Status",
|
||||||
"busy": "Pipeline Busy",
|
"busy": "Pipeline Busy",
|
||||||
"requestPending": "Request Pending",
|
"requestPending": "Request Pending",
|
||||||
|
"cancellationRequested": "Cancellation Requested",
|
||||||
"jobName": "Job Name",
|
"jobName": "Job Name",
|
||||||
"startTime": "Start Time",
|
"startTime": "Start Time",
|
||||||
"progress": "Progress",
|
"progress": "Progress",
|
||||||
"unit": "batch",
|
"unit": "Batch",
|
||||||
"latestMessage": "Latest Message",
|
"latestMessage": "Latest Message",
|
||||||
"historyMessages": "History Messages",
|
"historyMessages": "History Messages",
|
||||||
|
"cancelButton": "Cancel",
|
||||||
|
"cancelTooltip": "Cancel pipeline processing",
|
||||||
|
"cancelInProgress": "Cancellation in progress...",
|
||||||
|
"pipelineNotRunning": "Pipeline not running",
|
||||||
|
"cancelSuccess": "Pipeline cancellation requested",
|
||||||
|
"cancelFailed": "Failed to cancel pipeline\n{{error}}",
|
||||||
|
"cancelNotBusy": "Pipeline is not running, no need to cancel",
|
||||||
"errors": {
|
"errors": {
|
||||||
"fetchFailed": "Failed to get pipeline status\n{{error}}"
|
"fetchFailed": "Failed to fetch pipeline status\n{{error}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -158,14 +158,22 @@
|
||||||
},
|
},
|
||||||
"pipelineStatus": {
|
"pipelineStatus": {
|
||||||
"title": "État du Pipeline",
|
"title": "État du Pipeline",
|
||||||
"busy": "Pipeline occupé",
|
"busy": "Pipeline Occupé",
|
||||||
"requestPending": "Requête en attente",
|
"requestPending": "Demande en Attente",
|
||||||
"jobName": "Nom du travail",
|
"cancellationRequested": "Annulation Demandée",
|
||||||
"startTime": "Heure de début",
|
"jobName": "Nom du Travail",
|
||||||
"progress": "Progression",
|
"startTime": "Heure de Début",
|
||||||
"unit": "lot",
|
"progress": "Progrès",
|
||||||
"latestMessage": "Dernier message",
|
"unit": "Lot",
|
||||||
"historyMessages": "Historique des messages",
|
"latestMessage": "Dernier Message",
|
||||||
|
"historyMessages": "Messages d'Historique",
|
||||||
|
"cancelButton": "Annuler",
|
||||||
|
"cancelTooltip": "Annuler le traitement du pipeline",
|
||||||
|
"cancelInProgress": "Annulation en cours...",
|
||||||
|
"pipelineNotRunning": "Le pipeline n'est pas en cours d'exécution",
|
||||||
|
"cancelSuccess": "Annulation du pipeline demandée",
|
||||||
|
"cancelFailed": "Échec de l'annulation du pipeline\n{{error}}",
|
||||||
|
"cancelNotBusy": "Le pipeline n'est pas en cours d'exécution, pas besoin d'annuler",
|
||||||
"errors": {
|
"errors": {
|
||||||
"fetchFailed": "Échec de la récupération de l'état du pipeline\n{{error}}"
|
"fetchFailed": "Échec de la récupération de l'état du pipeline\n{{error}}"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,12 +160,20 @@
|
||||||
"title": "流水线状态",
|
"title": "流水线状态",
|
||||||
"busy": "流水线忙碌",
|
"busy": "流水线忙碌",
|
||||||
"requestPending": "待处理请求",
|
"requestPending": "待处理请求",
|
||||||
|
"cancellationRequested": "取消请求",
|
||||||
"jobName": "作业名称",
|
"jobName": "作业名称",
|
||||||
"startTime": "开始时间",
|
"startTime": "开始时间",
|
||||||
"progress": "进度",
|
"progress": "进度",
|
||||||
"unit": "批",
|
"unit": "批",
|
||||||
"latestMessage": "最新消息",
|
"latestMessage": "最新消息",
|
||||||
"historyMessages": "历史消息",
|
"historyMessages": "历史消息",
|
||||||
|
"cancelButton": "中断",
|
||||||
|
"cancelTooltip": "中断流水线处理",
|
||||||
|
"cancelInProgress": "取消请求进行中...",
|
||||||
|
"pipelineNotRunning": "流水线未运行",
|
||||||
|
"cancelSuccess": "流水线中断请求已发送",
|
||||||
|
"cancelFailed": "中断流水线失败\n{{error}}",
|
||||||
|
"cancelNotBusy": "流水线未运行,无需中断",
|
||||||
"errors": {
|
"errors": {
|
||||||
"fetchFailed": "获取流水线状态失败\n{{error}}"
|
"fetchFailed": "获取流水线状态失败\n{{error}}"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,17 +157,25 @@
|
||||||
"hideFileNameTooltip": "隱藏檔案名稱"
|
"hideFileNameTooltip": "隱藏檔案名稱"
|
||||||
},
|
},
|
||||||
"pipelineStatus": {
|
"pipelineStatus": {
|
||||||
"title": "pipeline 狀態",
|
"title": "流水線狀態",
|
||||||
"busy": "pipeline 忙碌中",
|
"busy": "流水線忙碌",
|
||||||
"requestPending": "待處理請求",
|
"requestPending": "待處理請求",
|
||||||
"jobName": "工作名稱",
|
"cancellationRequested": "取消請求",
|
||||||
|
"jobName": "作業名稱",
|
||||||
"startTime": "開始時間",
|
"startTime": "開始時間",
|
||||||
"progress": "進度",
|
"progress": "進度",
|
||||||
"unit": "梯次",
|
"unit": "批",
|
||||||
"latestMessage": "最新訊息",
|
"latestMessage": "最新消息",
|
||||||
"historyMessages": "歷史訊息",
|
"historyMessages": "歷史消息",
|
||||||
|
"cancelButton": "中斷",
|
||||||
|
"cancelTooltip": "中斷流水線處理",
|
||||||
|
"cancelInProgress": "取消請求進行中...",
|
||||||
|
"pipelineNotRunning": "流水線未運行",
|
||||||
|
"cancelSuccess": "流水線中斷請求已發送",
|
||||||
|
"cancelFailed": "中斷流水線失敗\n{{error}}",
|
||||||
|
"cancelNotBusy": "流水線未運行,無需中斷",
|
||||||
"errors": {
|
"errors": {
|
||||||
"fetchFailed": "取得pipeline 狀態失敗\n{{error}}"
|
"fetchFailed": "獲取流水線狀態失敗\n{{error}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue