feat: enhance graph refresh with dynamic tooltips and loading states
• Add refresh loading state with spinner • Dynamic tooltips based on current label • Improved refresh logic for labels • Force dropdown re-render on refresh • Update i18n for new tooltip messages
This commit is contained in:
parent
36f242c164
commit
446767ba50
6 changed files with 98 additions and 32 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { AsyncSelect } from '@/components/ui/AsyncSelect'
|
||||
import { useSettingsStore } from '@/stores/settings'
|
||||
import { useGraphStore } from '@/stores/graph'
|
||||
|
|
@ -17,6 +17,22 @@ import { getPopularLabels, searchLabels } from '@/api/lightrag'
|
|||
const GraphLabels = () => {
|
||||
const { t } = useTranslation()
|
||||
const label = useSettingsStore.use.queryLabel()
|
||||
const [isRefreshing, setIsRefreshing] = useState(false)
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||||
const [selectKey, setSelectKey] = useState(0)
|
||||
|
||||
// Dynamic tooltip based on current label state
|
||||
const getRefreshTooltip = useCallback(() => {
|
||||
if (isRefreshing) {
|
||||
return t('graphPanel.graphLabels.refreshingTooltip')
|
||||
}
|
||||
|
||||
if (!label || label === '*') {
|
||||
return t('graphPanel.graphLabels.refreshGlobalTooltip')
|
||||
} else {
|
||||
return t('graphPanel.graphLabels.refreshCurrentLabelTooltip', { label })
|
||||
}
|
||||
}, [label, t, isRefreshing])
|
||||
|
||||
// Initialize search history on component mount
|
||||
useEffect(() => {
|
||||
|
|
@ -67,37 +83,75 @@ const GraphLabels = () => {
|
|||
const finalResults = ['*', ...results.filter(label => label !== '*')];
|
||||
return finalResults;
|
||||
},
|
||||
[]
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[refreshTrigger] // Intentionally added to trigger re-creation when data changes
|
||||
)
|
||||
|
||||
const handleRefresh = useCallback(async () => {
|
||||
// Clear search history
|
||||
SearchHistoryManager.clearHistory()
|
||||
setIsRefreshing(true)
|
||||
|
||||
// Reinitialize with popular labels
|
||||
try {
|
||||
const popularLabels = await getPopularLabels(popularLabelsDefaultLimit)
|
||||
await SearchHistoryManager.initializeWithDefaults(popularLabels)
|
||||
const currentLabel = label
|
||||
|
||||
if (currentLabel && currentLabel !== '*') {
|
||||
// Scenario 1: Has specific label, try to refresh current label
|
||||
console.log(`Refreshing current label: ${currentLabel}`)
|
||||
|
||||
// Reset graph data fetch status to trigger refresh
|
||||
useGraphStore.getState().setGraphDataFetchAttempted(false)
|
||||
useGraphStore.getState().setLastSuccessfulQueryLabel('')
|
||||
|
||||
// Force data refresh for current label
|
||||
useGraphStore.getState().incrementGraphDataVersion()
|
||||
|
||||
// Note: If the current label has no data after refresh,
|
||||
// the fallback logic would be handled by the graph component itself
|
||||
// For now, we keep the current label and let the user see the result
|
||||
|
||||
} else {
|
||||
// Scenario 3: queryLabel is "*", refresh global data and popular labels
|
||||
console.log('Refreshing global data and popular labels')
|
||||
|
||||
try {
|
||||
// Re-fetch popular labels and update search history
|
||||
const popularLabels = await getPopularLabels(popularLabelsDefaultLimit)
|
||||
SearchHistoryManager.clearHistory()
|
||||
|
||||
if (popularLabels.length === 0) {
|
||||
// If no popular labels, provide fallback defaults
|
||||
const fallbackLabels = ['entity', 'relationship', 'document', 'concept']
|
||||
await SearchHistoryManager.initializeWithDefaults(fallbackLabels)
|
||||
} else {
|
||||
await SearchHistoryManager.initializeWithDefaults(popularLabels)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to reload popular labels:', error)
|
||||
// Provide fallback even if API fails
|
||||
const fallbackLabels = ['entity', 'relationship', 'document']
|
||||
SearchHistoryManager.clearHistory()
|
||||
await SearchHistoryManager.initializeWithDefaults(fallbackLabels)
|
||||
}
|
||||
|
||||
// Reset graph data fetch status
|
||||
useGraphStore.getState().setGraphDataFetchAttempted(false)
|
||||
useGraphStore.getState().setLastSuccessfulQueryLabel('')
|
||||
|
||||
// Force global data refresh
|
||||
useGraphStore.getState().incrementGraphDataVersion()
|
||||
|
||||
// Ensure data update completes before triggering UI refresh
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
|
||||
// Trigger both refresh mechanisms to ensure dropdown updates
|
||||
setRefreshTrigger(prev => prev + 1)
|
||||
setSelectKey(prev => prev + 1)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to reload popular labels:', error)
|
||||
// No fallback needed
|
||||
console.error('Error during refresh:', error)
|
||||
} finally {
|
||||
setIsRefreshing(false)
|
||||
}
|
||||
|
||||
// Reset fetch status flags to trigger UI refresh
|
||||
useGraphStore.getState().setLabelsFetchAttempted(false)
|
||||
useGraphStore.getState().setGraphDataFetchAttempted(false)
|
||||
|
||||
// Clear last successful query label to ensure labels are fetched,
|
||||
// which is the key to forcing a data refresh.
|
||||
useGraphStore.getState().setLastSuccessfulQueryLabel('')
|
||||
|
||||
// Reset to default label to ensure consistency
|
||||
useSettingsStore.getState().setQueryLabel('*')
|
||||
|
||||
// Force a data refresh by incrementing the version counter in the graph store.
|
||||
// This is the reliable way to trigger a re-fetch of the graph data.
|
||||
useGraphStore.getState().incrementGraphDataVersion()
|
||||
}, []);
|
||||
}, [label])
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
|
|
@ -106,12 +160,14 @@ const GraphLabels = () => {
|
|||
size="icon"
|
||||
variant={controlButtonVariant}
|
||||
onClick={handleRefresh}
|
||||
tooltip={t('graphPanel.graphLabels.refreshTooltip')}
|
||||
tooltip={getRefreshTooltip()}
|
||||
className="mr-2"
|
||||
disabled={isRefreshing}
|
||||
>
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
<RefreshCw className={`h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} />
|
||||
</Button>
|
||||
<AsyncSelect<string>
|
||||
key={selectKey} // Force re-render when data changes
|
||||
className="min-w-[300px]"
|
||||
triggerClassName="max-h-8"
|
||||
searchInputClassName="max-h-8"
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@
|
|||
"label": "التسمية",
|
||||
"placeholder": "ابحث في التسميات...",
|
||||
"andOthers": "و {{count}} آخرون",
|
||||
"refreshTooltip": "إعادة تعيين بيانات الرسم البياني وسجل البحث (مطلوب بعد تغيير المستندات)"
|
||||
"refreshGlobalTooltip": "تحديث بيانات الرسم البياني العالمي وسجل البحث",
|
||||
"refreshCurrentLabelTooltip": "تحديث بيانات الرسم البياني للصفحة الحالية",
|
||||
"refreshingTooltip": "جارٍ تحديث البيانات..."
|
||||
},
|
||||
"emptyGraph": "فارغ (حاول إعادة التحميل)"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@
|
|||
"label": "Label",
|
||||
"placeholder": "Search labels...",
|
||||
"andOthers": "And {count} others",
|
||||
"refreshTooltip": "Reset graph data and search history (required after document changes)"
|
||||
"refreshGlobalTooltip": "Refresh global graph data and search history",
|
||||
"refreshCurrentLabelTooltip": "Refresh current page graph data",
|
||||
"refreshingTooltip": "Refreshing data..."
|
||||
},
|
||||
"emptyGraph": "Empty(Try Reload Again)"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@
|
|||
"label": "Étiquette",
|
||||
"placeholder": "Rechercher des étiquettes...",
|
||||
"andOthers": "Et {{count}} autres",
|
||||
"refreshTooltip": "Réinitialiser les données du graphe et l'historique de recherche (requis après modification des documents)"
|
||||
"refreshGlobalTooltip": "Actualiser les données du graphe global et l'historique de recherche",
|
||||
"refreshCurrentLabelTooltip": "Actualiser les données du graphe de la page actuelle",
|
||||
"refreshingTooltip": "Actualisation des données en cours..."
|
||||
},
|
||||
"emptyGraph": "Vide (Essayez de recharger)"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@
|
|||
"label": "标签",
|
||||
"placeholder": "搜索标签...",
|
||||
"andOthers": "还有 {count} 个",
|
||||
"refreshTooltip": "重置图形数据和搜索历史(文档变化后需重置)"
|
||||
"refreshGlobalTooltip": "刷新全图数据和搜索历史",
|
||||
"refreshCurrentLabelTooltip": "刷新当前页面图数据",
|
||||
"refreshingTooltip": "正在刷新数据..."
|
||||
},
|
||||
"emptyGraph": "无数据(请重载图形数据)"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -336,7 +336,9 @@
|
|||
"label": "標籤",
|
||||
"placeholder": "搜尋標籤...",
|
||||
"andOthers": "還有 {count} 個",
|
||||
"refreshTooltip": "重設圖形資料和搜尋歷史(文件變化後需重設)"
|
||||
"refreshGlobalTooltip": "重新整理全圖資料和搜尋歷史",
|
||||
"refreshCurrentLabelTooltip": "重新整理目前頁面圖形資料",
|
||||
"refreshingTooltip": "正在重新整理資料..."
|
||||
},
|
||||
"emptyGraph": "無數據(請重載圖形數據)"
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue