feat: add pipeline busy status indicator with breathing effect

- Add pipeline_busy field to health check response
- Track pipeline busy state in frontend store
- Add breathing animation for pipeline status button
- Enhance dark mode visibility with stronger contrast
This commit is contained in:
yangdx
2025-03-26 13:11:53 +08:00
parent 51be3fcfa5
commit 814f3b3308
3 changed files with 66 additions and 3 deletions

View File

@@ -45,6 +45,7 @@ export type LightragStatus = {
core_version?: string
api_version?: string
auth_mode?: 'enabled' | 'disabled'
pipeline_busy: boolean
}
export type LightragDocumentsScanProgress = {

View File

@@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useSettingsStore } from '@/stores/settings'
import Button from '@/components/ui/Button'
import { cn } from '@/lib/utils'
import {
Table,
TableBody,
@@ -45,15 +46,67 @@ const getDisplayFileName = (doc: DocStatusResponse, maxLength: number = 20): str
: fileName;
};
const pulseStyle = `
@keyframes pulse {
0% {
background-color: rgb(255 0 0 / 0.1);
border-color: rgb(255 0 0 / 0.2);
}
50% {
background-color: rgb(255 0 0 / 0.2);
border-color: rgb(255 0 0 / 0.4);
}
100% {
background-color: rgb(255 0 0 / 0.1);
border-color: rgb(255 0 0 / 0.2);
}
}
.dark .pipeline-busy {
animation: dark-pulse 2s infinite;
}
@keyframes dark-pulse {
0% {
background-color: rgb(255 0 0 / 0.2);
border-color: rgb(255 0 0 / 0.4);
}
50% {
background-color: rgb(255 0 0 / 0.3);
border-color: rgb(255 0 0 / 0.6);
}
100% {
background-color: rgb(255 0 0 / 0.2);
border-color: rgb(255 0 0 / 0.4);
}
}
.pipeline-busy {
animation: pulse 2s infinite;
border: 1px solid;
}
`;
export default function DocumentManager() {
const [showPipelineStatus, setShowPipelineStatus] = useState(false)
const { t } = useTranslation()
const health = useBackendState.use.health()
const pipelineBusy = useBackendState.use.pipelineBusy()
const [docs, setDocs] = useState<DocsStatusesResponse | null>(null)
const currentTab = useSettingsStore.use.currentTab()
const showFileName = useSettingsStore.use.showFileName()
const setShowFileName = useSettingsStore.use.setShowFileName()
// Add pulse style to document
useEffect(() => {
const style = document.createElement('style')
style.textContent = pulseStyle
document.head.appendChild(style)
return () => {
document.head.removeChild(style)
}
}, [])
const fetchDocuments = useCallback(async () => {
try {
const docs = await getDocuments()
@@ -132,6 +185,9 @@ export default function DocumentManager() {
side="bottom"
tooltip={t('documentPanel.documentManager.pipelineStatusTooltip')}
size="sm"
className={cn(
pipelineBusy && 'pipeline-busy'
)}
>
<ActivityIcon /> {t('documentPanel.documentManager.pipelineStatusButton')}
</Button>

View File

@@ -6,14 +6,14 @@ interface BackendState {
health: boolean
message: string | null
messageTitle: string | null
status: LightragStatus | null
lastCheckTime: number
pipelineBusy: boolean
check: () => Promise<boolean>
clear: () => void
setErrorMessage: (message: string, messageTitle: string) => void
setPipelineBusy: (busy: boolean) => void
}
interface AuthState {
@@ -34,6 +34,7 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
messageTitle: null,
lastCheckTime: Date.now(),
status: null,
pipelineBusy: false,
check: async () => {
const health = await checkHealth()
@@ -51,7 +52,8 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
message: null,
messageTitle: null,
lastCheckTime: Date.now(),
status: health
status: health,
pipelineBusy: health.pipeline_busy
})
return true
}
@@ -71,6 +73,10 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
setErrorMessage: (message: string, messageTitle: string) => {
set({ health: false, message, messageTitle })
},
setPipelineBusy: (busy: boolean) => {
set({ pipelineBusy: busy })
}
}))