yangdx
commited on
Commit
·
2e179f3
1
Parent(s):
9bf536e
Fix linting
Browse files- lightrag/api/webui/assets/{index-DbL6qA5M.js → index-CKDgttI2.js} +0 -0
- lightrag/api/webui/assets/index-CRQxBxm4.css +0 -0
- lightrag/api/webui/assets/index-ban2VJxS.css +0 -0
- lightrag/api/webui/index.html +0 -0
- lightrag_webui/src/components/graph/GraphLabels.tsx +9 -9
- lightrag_webui/src/components/ui/TabContent.tsx +1 -1
- lightrag_webui/src/contexts/TabVisibilityProvider.tsx +1 -1
- lightrag_webui/src/contexts/useTabVisibility.ts +2 -2
- lightrag_webui/src/features/ApiSite.tsx +4 -4
- lightrag_webui/src/features/DocumentManager.tsx +2 -2
- lightrag_webui/src/features/GraphViewer.tsx +2 -2
- lightrag_webui/src/hooks/useLightragGraph.tsx +29 -29
- lightrag_webui/src/stores/graph.ts +6 -6
lightrag/api/webui/assets/{index-DbL6qA5M.js → index-CKDgttI2.js}
RENAMED
Binary files a/lightrag/api/webui/assets/index-DbL6qA5M.js and b/lightrag/api/webui/assets/index-CKDgttI2.js differ
|
|
lightrag/api/webui/assets/index-CRQxBxm4.css
DELETED
Binary file (48.3 kB)
|
|
lightrag/api/webui/assets/index-ban2VJxS.css
ADDED
Binary file (48.4 kB). View file
|
|
lightrag/api/webui/index.html
CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
|
|
lightrag_webui/src/components/graph/GraphLabels.tsx
CHANGED
@@ -11,23 +11,23 @@ const GraphLabels = () => {
|
|
11 |
const label = useSettingsStore.use.queryLabel()
|
12 |
const allDatabaseLabels = useGraphStore.use.allDatabaseLabels()
|
13 |
const labelsLoadedRef = useRef(false)
|
14 |
-
|
15 |
// Track if a fetch is in progress to prevent multiple simultaneous fetches
|
16 |
const fetchInProgressRef = useRef(false)
|
17 |
-
|
18 |
// Fetch labels once on component mount, using global flag to prevent duplicates
|
19 |
useEffect(() => {
|
20 |
// Check if we've already attempted to fetch labels in this session
|
21 |
const labelsFetchAttempted = useGraphStore.getState().labelsFetchAttempted
|
22 |
-
|
23 |
// Only fetch if we haven't attempted in this session and no fetch is in progress
|
24 |
if (!labelsFetchAttempted && !fetchInProgressRef.current) {
|
25 |
fetchInProgressRef.current = true
|
26 |
// Set global flag to indicate we've attempted to fetch in this session
|
27 |
useGraphStore.getState().setLabelsFetchAttempted(true)
|
28 |
-
|
29 |
console.log('Fetching graph labels (once per session)...')
|
30 |
-
|
31 |
useGraphStore.getState().fetchAllDatabaseLabels()
|
32 |
.then(() => {
|
33 |
labelsLoadedRef.current = true
|
@@ -103,22 +103,22 @@ const GraphLabels = () => {
|
|
103 |
if (newLabel === '...') {
|
104 |
newLabel = '*'
|
105 |
}
|
106 |
-
|
107 |
// Reset the fetch attempted flag to force a new data fetch
|
108 |
useGraphStore.getState().setGraphDataFetchAttempted(false)
|
109 |
-
|
110 |
// Clear current graph data to ensure complete reload when label changes
|
111 |
if (newLabel !== currentLabel) {
|
112 |
const graphStore = useGraphStore.getState();
|
113 |
graphStore.clearSelection();
|
114 |
-
|
115 |
// Reset the graph state but preserve the instance
|
116 |
if (graphStore.sigmaGraph) {
|
117 |
const nodes = Array.from(graphStore.sigmaGraph.nodes());
|
118 |
nodes.forEach(node => graphStore.sigmaGraph?.dropNode(node));
|
119 |
}
|
120 |
}
|
121 |
-
|
122 |
if (newLabel === currentLabel && newLabel !== '*') {
|
123 |
// 选择相同标签时切换到'*'
|
124 |
useSettingsStore.getState().setQueryLabel('*')
|
|
|
11 |
const label = useSettingsStore.use.queryLabel()
|
12 |
const allDatabaseLabels = useGraphStore.use.allDatabaseLabels()
|
13 |
const labelsLoadedRef = useRef(false)
|
14 |
+
|
15 |
// Track if a fetch is in progress to prevent multiple simultaneous fetches
|
16 |
const fetchInProgressRef = useRef(false)
|
17 |
+
|
18 |
// Fetch labels once on component mount, using global flag to prevent duplicates
|
19 |
useEffect(() => {
|
20 |
// Check if we've already attempted to fetch labels in this session
|
21 |
const labelsFetchAttempted = useGraphStore.getState().labelsFetchAttempted
|
22 |
+
|
23 |
// Only fetch if we haven't attempted in this session and no fetch is in progress
|
24 |
if (!labelsFetchAttempted && !fetchInProgressRef.current) {
|
25 |
fetchInProgressRef.current = true
|
26 |
// Set global flag to indicate we've attempted to fetch in this session
|
27 |
useGraphStore.getState().setLabelsFetchAttempted(true)
|
28 |
+
|
29 |
console.log('Fetching graph labels (once per session)...')
|
30 |
+
|
31 |
useGraphStore.getState().fetchAllDatabaseLabels()
|
32 |
.then(() => {
|
33 |
labelsLoadedRef.current = true
|
|
|
103 |
if (newLabel === '...') {
|
104 |
newLabel = '*'
|
105 |
}
|
106 |
+
|
107 |
// Reset the fetch attempted flag to force a new data fetch
|
108 |
useGraphStore.getState().setGraphDataFetchAttempted(false)
|
109 |
+
|
110 |
// Clear current graph data to ensure complete reload when label changes
|
111 |
if (newLabel !== currentLabel) {
|
112 |
const graphStore = useGraphStore.getState();
|
113 |
graphStore.clearSelection();
|
114 |
+
|
115 |
// Reset the graph state but preserve the instance
|
116 |
if (graphStore.sigmaGraph) {
|
117 |
const nodes = Array.from(graphStore.sigmaGraph.nodes());
|
118 |
nodes.forEach(node => graphStore.sigmaGraph?.dropNode(node));
|
119 |
}
|
120 |
}
|
121 |
+
|
122 |
if (newLabel === currentLabel && newLabel !== '*') {
|
123 |
// 选择相同标签时切换到'*'
|
124 |
useSettingsStore.getState().setQueryLabel('*')
|
lightrag_webui/src/components/ui/TabContent.tsx
CHANGED
@@ -18,7 +18,7 @@ const TabContent: React.FC<TabContentProps> = ({ tabId, children, className = ''
|
|
18 |
// Register this tab with the context when mounted
|
19 |
useEffect(() => {
|
20 |
setTabVisibility(tabId, true);
|
21 |
-
|
22 |
// Cleanup when unmounted
|
23 |
return () => {
|
24 |
setTabVisibility(tabId, false);
|
|
|
18 |
// Register this tab with the context when mounted
|
19 |
useEffect(() => {
|
20 |
setTabVisibility(tabId, true);
|
21 |
+
|
22 |
// Cleanup when unmounted
|
23 |
return () => {
|
24 |
setTabVisibility(tabId, false);
|
lightrag_webui/src/contexts/TabVisibilityProvider.tsx
CHANGED
@@ -14,7 +14,7 @@ interface TabVisibilityProviderProps {
|
|
14 |
export const TabVisibilityProvider: React.FC<TabVisibilityProviderProps> = ({ children }) => {
|
15 |
// Get current tab from settings store
|
16 |
const currentTab = useSettingsStore.use.currentTab();
|
17 |
-
|
18 |
// Initialize visibility state with current tab as visible
|
19 |
const [visibleTabs, setVisibleTabs] = useState<Record<string, boolean>>(() => ({
|
20 |
[currentTab]: true
|
|
|
14 |
export const TabVisibilityProvider: React.FC<TabVisibilityProviderProps> = ({ children }) => {
|
15 |
// Get current tab from settings store
|
16 |
const currentTab = useSettingsStore.use.currentTab();
|
17 |
+
|
18 |
// Initialize visibility state with current tab as visible
|
19 |
const [visibleTabs, setVisibleTabs] = useState<Record<string, boolean>>(() => ({
|
20 |
[currentTab]: true
|
lightrag_webui/src/contexts/useTabVisibility.ts
CHANGED
@@ -8,10 +8,10 @@ import { TabVisibilityContextType } from './types';
|
|
8 |
*/
|
9 |
export const useTabVisibility = (): TabVisibilityContextType => {
|
10 |
const context = useContext(TabVisibilityContext);
|
11 |
-
|
12 |
if (!context) {
|
13 |
throw new Error('useTabVisibility must be used within a TabVisibilityProvider');
|
14 |
}
|
15 |
-
|
16 |
return context;
|
17 |
};
|
|
|
8 |
*/
|
9 |
export const useTabVisibility = (): TabVisibilityContextType => {
|
10 |
const context = useContext(TabVisibilityContext);
|
11 |
+
|
12 |
if (!context) {
|
13 |
throw new Error('useTabVisibility must be used within a TabVisibilityProvider');
|
14 |
}
|
15 |
+
|
16 |
return context;
|
17 |
};
|
lightrag_webui/src/features/ApiSite.tsx
CHANGED
@@ -8,20 +8,20 @@ export default function ApiSite() {
|
|
8 |
const { isTabVisible } = useTabVisibility()
|
9 |
const isApiTabVisible = isTabVisible('api')
|
10 |
const [iframeLoaded, setIframeLoaded] = useState(false)
|
11 |
-
|
12 |
// Load the iframe once on component mount
|
13 |
useEffect(() => {
|
14 |
if (!iframeLoaded) {
|
15 |
setIframeLoaded(true)
|
16 |
}
|
17 |
}, [iframeLoaded])
|
18 |
-
|
19 |
// Use CSS to hide content when tab is not visible
|
20 |
return (
|
21 |
<div className={`size-full ${isApiTabVisible ? '' : 'hidden'}`}>
|
22 |
{iframeLoaded ? (
|
23 |
-
<iframe
|
24 |
-
src={backendBaseUrl + '/docs'}
|
25 |
className="size-full w-full h-full"
|
26 |
style={{ width: '100%', height: '100%', border: 'none' }}
|
27 |
// Use key to ensure iframe doesn't reload
|
|
|
8 |
const { isTabVisible } = useTabVisibility()
|
9 |
const isApiTabVisible = isTabVisible('api')
|
10 |
const [iframeLoaded, setIframeLoaded] = useState(false)
|
11 |
+
|
12 |
// Load the iframe once on component mount
|
13 |
useEffect(() => {
|
14 |
if (!iframeLoaded) {
|
15 |
setIframeLoaded(true)
|
16 |
}
|
17 |
}, [iframeLoaded])
|
18 |
+
|
19 |
// Use CSS to hide content when tab is not visible
|
20 |
return (
|
21 |
<div className={`size-full ${isApiTabVisible ? '' : 'hidden'}`}>
|
22 |
{iframeLoaded ? (
|
23 |
+
<iframe
|
24 |
+
src={backendBaseUrl + '/docs'}
|
25 |
className="size-full w-full h-full"
|
26 |
style={{ width: '100%', height: '100%', border: 'none' }}
|
27 |
// Use key to ensure iframe doesn't reload
|
lightrag_webui/src/features/DocumentManager.tsx
CHANGED
@@ -76,7 +76,7 @@ export default function DocumentManager() {
|
|
76 |
if (!isDocumentsTabVisible || !health) {
|
77 |
return
|
78 |
}
|
79 |
-
|
80 |
const interval = setInterval(async () => {
|
81 |
try {
|
82 |
await fetchDocuments()
|
@@ -84,7 +84,7 @@ export default function DocumentManager() {
|
|
84 |
toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
|
85 |
}
|
86 |
}, 5000)
|
87 |
-
|
88 |
return () => clearInterval(interval)
|
89 |
}, [health, fetchDocuments, t, isDocumentsTabVisible])
|
90 |
|
|
|
76 |
if (!isDocumentsTabVisible || !health) {
|
77 |
return
|
78 |
}
|
79 |
+
|
80 |
const interval = setInterval(async () => {
|
81 |
try {
|
82 |
await fetchDocuments()
|
|
|
84 |
toast.error(t('documentPanel.documentManager.errors.scanProgressFailed', { error: errorMessage(err) }))
|
85 |
}
|
86 |
}, 5000)
|
87 |
+
|
88 |
return () => clearInterval(interval)
|
89 |
}, [health, fetchDocuments, t, isDocumentsTabVisible])
|
90 |
|
lightrag_webui/src/features/GraphViewer.tsx
CHANGED
@@ -115,7 +115,7 @@ const GraphViewer = () => {
|
|
115 |
const moveToSelectedNode = useGraphStore.use.moveToSelectedNode()
|
116 |
const isFetching = useGraphStore.use.isFetching()
|
117 |
const shouldRender = useGraphStore.use.shouldRender() // Rendering control state
|
118 |
-
|
119 |
// Get tab visibility
|
120 |
const { isTabVisible } = useTabVisibility()
|
121 |
const isGraphTabVisible = isTabVisible('knowledge-graph')
|
@@ -137,7 +137,7 @@ const GraphViewer = () => {
|
|
137 |
initAttemptedRef.current = true
|
138 |
console.log('Graph viewer initialized')
|
139 |
}
|
140 |
-
|
141 |
// Cleanup function when component unmounts
|
142 |
return () => {
|
143 |
// Only log cleanup, don't actually clean up the WebGL context
|
|
|
115 |
const moveToSelectedNode = useGraphStore.use.moveToSelectedNode()
|
116 |
const isFetching = useGraphStore.use.isFetching()
|
117 |
const shouldRender = useGraphStore.use.shouldRender() // Rendering control state
|
118 |
+
|
119 |
// Get tab visibility
|
120 |
const { isTabVisible } = useTabVisibility()
|
121 |
const isGraphTabVisible = isTabVisible('knowledge-graph')
|
|
|
137 |
initAttemptedRef.current = true
|
138 |
console.log('Graph viewer initialized')
|
139 |
}
|
140 |
+
|
141 |
// Cleanup function when component unmounts
|
142 |
return () => {
|
143 |
// Only log cleanup, don't actually clean up the WebGL context
|
lightrag_webui/src/hooks/useLightragGraph.tsx
CHANGED
@@ -148,7 +148,7 @@ const createSigmaGraph = (rawGraph: RawGraph | null) => {
|
|
148 |
seedrandom(rawNode.id + Date.now().toString(), { global: true })
|
149 |
const x = Math.random()
|
150 |
const y = Math.random()
|
151 |
-
|
152 |
graph.addNode(rawNode.id, {
|
153 |
label: rawNode.labels.join(', '),
|
154 |
color: rawNode.color,
|
@@ -178,20 +178,20 @@ const useLightrangeGraph = () => {
|
|
178 |
const maxQueryDepth = useSettingsStore.use.graphQueryMaxDepth()
|
179 |
const minDegree = useSettingsStore.use.graphMinDegree()
|
180 |
const isFetching = useGraphStore.use.isFetching()
|
181 |
-
|
182 |
// Get tab visibility
|
183 |
const { isTabVisible } = useTabVisibility()
|
184 |
const isGraphTabVisible = isTabVisible('knowledge-graph')
|
185 |
-
|
186 |
// Track previous parameters to detect actual changes
|
187 |
const prevParamsRef = useRef({ queryLabel, maxQueryDepth, minDegree })
|
188 |
-
|
189 |
// Use ref to track if data has been loaded and initial load
|
190 |
const dataLoadedRef = useRef(false)
|
191 |
const initialLoadRef = useRef(false)
|
192 |
-
|
193 |
// Check if parameters have changed
|
194 |
-
const paramsChanged =
|
195 |
prevParamsRef.current.queryLabel !== queryLabel ||
|
196 |
prevParamsRef.current.maxQueryDepth !== maxQueryDepth ||
|
197 |
prevParamsRef.current.minDegree !== minDegree
|
@@ -212,14 +212,14 @@ const useLightrangeGraph = () => {
|
|
212 |
|
213 |
// Track if a fetch is in progress to prevent multiple simultaneous fetches
|
214 |
const fetchInProgressRef = useRef(false)
|
215 |
-
|
216 |
// Data fetching logic - simplified but preserving TAB visibility check
|
217 |
useEffect(() => {
|
218 |
// Skip if fetch is already in progress
|
219 |
if (fetchInProgressRef.current) {
|
220 |
return
|
221 |
}
|
222 |
-
|
223 |
// If there's no query label, reset the graph
|
224 |
if (!queryLabel) {
|
225 |
if (rawGraph !== null || sigmaGraph !== null) {
|
@@ -233,25 +233,25 @@ const useLightrangeGraph = () => {
|
|
233 |
initialLoadRef.current = false
|
234 |
return
|
235 |
}
|
236 |
-
|
237 |
// Check if parameters have changed
|
238 |
-
if (!isFetching && !fetchInProgressRef.current &&
|
239 |
(paramsChanged || !useGraphStore.getState().graphDataFetchAttempted)) {
|
240 |
-
|
241 |
// Only fetch data if the Graph tab is visible
|
242 |
if (!isGraphTabVisible) {
|
243 |
console.log('Graph tab not visible, skipping data fetch');
|
244 |
return;
|
245 |
}
|
246 |
-
|
247 |
// Set flags
|
248 |
fetchInProgressRef.current = true
|
249 |
useGraphStore.getState().setGraphDataFetchAttempted(true)
|
250 |
-
|
251 |
const state = useGraphStore.getState()
|
252 |
state.setIsFetching(true)
|
253 |
state.setShouldRender(false) // Disable rendering during data loading
|
254 |
-
|
255 |
// Clear selection and highlighted nodes before fetching new graph
|
256 |
state.clearSelection()
|
257 |
if (state.sigmaGraph) {
|
@@ -259,32 +259,32 @@ const useLightrangeGraph = () => {
|
|
259 |
state.sigmaGraph?.setNodeAttribute(node, 'highlighted', false)
|
260 |
})
|
261 |
}
|
262 |
-
|
263 |
// Update parameter reference
|
264 |
prevParamsRef.current = { queryLabel, maxQueryDepth, minDegree }
|
265 |
-
|
266 |
console.log('Fetching graph data...')
|
267 |
-
|
268 |
// Use a local copy of the parameters
|
269 |
const currentQueryLabel = queryLabel
|
270 |
const currentMaxQueryDepth = maxQueryDepth
|
271 |
const currentMinDegree = minDegree
|
272 |
-
|
273 |
// Fetch graph data
|
274 |
fetchGraph(currentQueryLabel, currentMaxQueryDepth, currentMinDegree).then((data) => {
|
275 |
const state = useGraphStore.getState()
|
276 |
-
|
277 |
// Reset state
|
278 |
state.reset()
|
279 |
-
|
280 |
// Create and set new graph directly
|
281 |
const newSigmaGraph = createSigmaGraph(data)
|
282 |
data?.buildDynamicMap()
|
283 |
-
|
284 |
// Set new graph data
|
285 |
state.setSigmaGraph(newSigmaGraph)
|
286 |
state.setRawGraph(data)
|
287 |
-
|
288 |
// Extract labels from current graph data
|
289 |
if (data) {
|
290 |
const labelSet = new Set<string>()
|
@@ -303,21 +303,21 @@ const useLightrangeGraph = () => {
|
|
303 |
} else {
|
304 |
state.setGraphLabels(['*'])
|
305 |
}
|
306 |
-
|
307 |
// Update flags
|
308 |
dataLoadedRef.current = true
|
309 |
initialLoadRef.current = true
|
310 |
fetchInProgressRef.current = false
|
311 |
-
|
312 |
// Reset camera view
|
313 |
state.setMoveToSelectedNode(true)
|
314 |
-
|
315 |
// Enable rendering if the tab is visible
|
316 |
state.setShouldRender(isGraphTabVisible)
|
317 |
state.setIsFetching(false)
|
318 |
}).catch((error) => {
|
319 |
console.error('Error fetching graph data:', error)
|
320 |
-
|
321 |
// Reset state on error
|
322 |
const state = useGraphStore.getState()
|
323 |
state.setIsFetching(false)
|
@@ -328,7 +328,7 @@ const useLightrangeGraph = () => {
|
|
328 |
})
|
329 |
}
|
330 |
}, [queryLabel, maxQueryDepth, minDegree, isFetching, paramsChanged, isGraphTabVisible, rawGraph, sigmaGraph])
|
331 |
-
|
332 |
// Update rendering state and handle tab visibility changes
|
333 |
useEffect(() => {
|
334 |
// When tab becomes visible
|
@@ -337,7 +337,7 @@ const useLightrangeGraph = () => {
|
|
337 |
if (rawGraph) {
|
338 |
useGraphStore.getState().setShouldRender(true)
|
339 |
}
|
340 |
-
|
341 |
// We no longer reset the fetch attempted flag here to prevent continuous API calls
|
342 |
} else {
|
343 |
// When tab becomes invisible, disable rendering
|
@@ -350,7 +350,7 @@ const useLightrangeGraph = () => {
|
|
350 |
if (sigmaGraph) {
|
351 |
return sigmaGraph as Graph<NodeType, EdgeType>
|
352 |
}
|
353 |
-
|
354 |
// If no graph exists yet, create a new one and store it
|
355 |
console.log('Creating new Sigma graph instance')
|
356 |
const graph = new DirectedGraph()
|
|
|
148 |
seedrandom(rawNode.id + Date.now().toString(), { global: true })
|
149 |
const x = Math.random()
|
150 |
const y = Math.random()
|
151 |
+
|
152 |
graph.addNode(rawNode.id, {
|
153 |
label: rawNode.labels.join(', '),
|
154 |
color: rawNode.color,
|
|
|
178 |
const maxQueryDepth = useSettingsStore.use.graphQueryMaxDepth()
|
179 |
const minDegree = useSettingsStore.use.graphMinDegree()
|
180 |
const isFetching = useGraphStore.use.isFetching()
|
181 |
+
|
182 |
// Get tab visibility
|
183 |
const { isTabVisible } = useTabVisibility()
|
184 |
const isGraphTabVisible = isTabVisible('knowledge-graph')
|
185 |
+
|
186 |
// Track previous parameters to detect actual changes
|
187 |
const prevParamsRef = useRef({ queryLabel, maxQueryDepth, minDegree })
|
188 |
+
|
189 |
// Use ref to track if data has been loaded and initial load
|
190 |
const dataLoadedRef = useRef(false)
|
191 |
const initialLoadRef = useRef(false)
|
192 |
+
|
193 |
// Check if parameters have changed
|
194 |
+
const paramsChanged =
|
195 |
prevParamsRef.current.queryLabel !== queryLabel ||
|
196 |
prevParamsRef.current.maxQueryDepth !== maxQueryDepth ||
|
197 |
prevParamsRef.current.minDegree !== minDegree
|
|
|
212 |
|
213 |
// Track if a fetch is in progress to prevent multiple simultaneous fetches
|
214 |
const fetchInProgressRef = useRef(false)
|
215 |
+
|
216 |
// Data fetching logic - simplified but preserving TAB visibility check
|
217 |
useEffect(() => {
|
218 |
// Skip if fetch is already in progress
|
219 |
if (fetchInProgressRef.current) {
|
220 |
return
|
221 |
}
|
222 |
+
|
223 |
// If there's no query label, reset the graph
|
224 |
if (!queryLabel) {
|
225 |
if (rawGraph !== null || sigmaGraph !== null) {
|
|
|
233 |
initialLoadRef.current = false
|
234 |
return
|
235 |
}
|
236 |
+
|
237 |
// Check if parameters have changed
|
238 |
+
if (!isFetching && !fetchInProgressRef.current &&
|
239 |
(paramsChanged || !useGraphStore.getState().graphDataFetchAttempted)) {
|
240 |
+
|
241 |
// Only fetch data if the Graph tab is visible
|
242 |
if (!isGraphTabVisible) {
|
243 |
console.log('Graph tab not visible, skipping data fetch');
|
244 |
return;
|
245 |
}
|
246 |
+
|
247 |
// Set flags
|
248 |
fetchInProgressRef.current = true
|
249 |
useGraphStore.getState().setGraphDataFetchAttempted(true)
|
250 |
+
|
251 |
const state = useGraphStore.getState()
|
252 |
state.setIsFetching(true)
|
253 |
state.setShouldRender(false) // Disable rendering during data loading
|
254 |
+
|
255 |
// Clear selection and highlighted nodes before fetching new graph
|
256 |
state.clearSelection()
|
257 |
if (state.sigmaGraph) {
|
|
|
259 |
state.sigmaGraph?.setNodeAttribute(node, 'highlighted', false)
|
260 |
})
|
261 |
}
|
262 |
+
|
263 |
// Update parameter reference
|
264 |
prevParamsRef.current = { queryLabel, maxQueryDepth, minDegree }
|
265 |
+
|
266 |
console.log('Fetching graph data...')
|
267 |
+
|
268 |
// Use a local copy of the parameters
|
269 |
const currentQueryLabel = queryLabel
|
270 |
const currentMaxQueryDepth = maxQueryDepth
|
271 |
const currentMinDegree = minDegree
|
272 |
+
|
273 |
// Fetch graph data
|
274 |
fetchGraph(currentQueryLabel, currentMaxQueryDepth, currentMinDegree).then((data) => {
|
275 |
const state = useGraphStore.getState()
|
276 |
+
|
277 |
// Reset state
|
278 |
state.reset()
|
279 |
+
|
280 |
// Create and set new graph directly
|
281 |
const newSigmaGraph = createSigmaGraph(data)
|
282 |
data?.buildDynamicMap()
|
283 |
+
|
284 |
// Set new graph data
|
285 |
state.setSigmaGraph(newSigmaGraph)
|
286 |
state.setRawGraph(data)
|
287 |
+
|
288 |
// Extract labels from current graph data
|
289 |
if (data) {
|
290 |
const labelSet = new Set<string>()
|
|
|
303 |
} else {
|
304 |
state.setGraphLabels(['*'])
|
305 |
}
|
306 |
+
|
307 |
// Update flags
|
308 |
dataLoadedRef.current = true
|
309 |
initialLoadRef.current = true
|
310 |
fetchInProgressRef.current = false
|
311 |
+
|
312 |
// Reset camera view
|
313 |
state.setMoveToSelectedNode(true)
|
314 |
+
|
315 |
// Enable rendering if the tab is visible
|
316 |
state.setShouldRender(isGraphTabVisible)
|
317 |
state.setIsFetching(false)
|
318 |
}).catch((error) => {
|
319 |
console.error('Error fetching graph data:', error)
|
320 |
+
|
321 |
// Reset state on error
|
322 |
const state = useGraphStore.getState()
|
323 |
state.setIsFetching(false)
|
|
|
328 |
})
|
329 |
}
|
330 |
}, [queryLabel, maxQueryDepth, minDegree, isFetching, paramsChanged, isGraphTabVisible, rawGraph, sigmaGraph])
|
331 |
+
|
332 |
// Update rendering state and handle tab visibility changes
|
333 |
useEffect(() => {
|
334 |
// When tab becomes visible
|
|
|
337 |
if (rawGraph) {
|
338 |
useGraphStore.getState().setShouldRender(true)
|
339 |
}
|
340 |
+
|
341 |
// We no longer reset the fetch attempted flag here to prevent continuous API calls
|
342 |
} else {
|
343 |
// When tab becomes invisible, disable rendering
|
|
|
350 |
if (sigmaGraph) {
|
351 |
return sigmaGraph as Graph<NodeType, EdgeType>
|
352 |
}
|
353 |
+
|
354 |
// If no graph exists yet, create a new one and store it
|
355 |
console.log('Creating new Sigma graph instance')
|
356 |
const graph = new DirectedGraph()
|
lightrag_webui/src/stores/graph.ts
CHANGED
@@ -72,7 +72,7 @@ interface GraphState {
|
|
72 |
moveToSelectedNode: boolean
|
73 |
isFetching: boolean
|
74 |
shouldRender: boolean
|
75 |
-
|
76 |
// Global flags to track data fetching attempts
|
77 |
graphDataFetchAttempted: boolean
|
78 |
labelsFetchAttempted: boolean
|
@@ -94,7 +94,7 @@ interface GraphState {
|
|
94 |
fetchAllDatabaseLabels: () => Promise<void>
|
95 |
setIsFetching: (isFetching: boolean) => void
|
96 |
setShouldRender: (shouldRender: boolean) => void
|
97 |
-
|
98 |
// Methods to set global flags
|
99 |
setGraphDataFetchAttempted: (attempted: boolean) => void
|
100 |
setLabelsFetchAttempted: (attempted: boolean) => void
|
@@ -109,7 +109,7 @@ const useGraphStoreBase = create<GraphState>()((set, get) => ({
|
|
109 |
moveToSelectedNode: false,
|
110 |
isFetching: false,
|
111 |
shouldRender: false,
|
112 |
-
|
113 |
// Initialize global flags
|
114 |
graphDataFetchAttempted: false,
|
115 |
labelsFetchAttempted: false,
|
@@ -147,13 +147,13 @@ const useGraphStoreBase = create<GraphState>()((set, get) => ({
|
|
147 |
reset: () => {
|
148 |
// Get the existing graph
|
149 |
const existingGraph = get().sigmaGraph;
|
150 |
-
|
151 |
// If we have an existing graph, clear it by removing all nodes
|
152 |
if (existingGraph) {
|
153 |
const nodes = Array.from(existingGraph.nodes());
|
154 |
nodes.forEach(node => existingGraph.dropNode(node));
|
155 |
}
|
156 |
-
|
157 |
set({
|
158 |
selectedNode: null,
|
159 |
focusedNode: null,
|
@@ -195,7 +195,7 @@ const useGraphStoreBase = create<GraphState>()((set, get) => ({
|
|
195 |
},
|
196 |
|
197 |
setMoveToSelectedNode: (moveToSelectedNode?: boolean) => set({ moveToSelectedNode }),
|
198 |
-
|
199 |
// Methods to set global flags
|
200 |
setGraphDataFetchAttempted: (attempted: boolean) => set({ graphDataFetchAttempted: attempted }),
|
201 |
setLabelsFetchAttempted: (attempted: boolean) => set({ labelsFetchAttempted: attempted })
|
|
|
72 |
moveToSelectedNode: boolean
|
73 |
isFetching: boolean
|
74 |
shouldRender: boolean
|
75 |
+
|
76 |
// Global flags to track data fetching attempts
|
77 |
graphDataFetchAttempted: boolean
|
78 |
labelsFetchAttempted: boolean
|
|
|
94 |
fetchAllDatabaseLabels: () => Promise<void>
|
95 |
setIsFetching: (isFetching: boolean) => void
|
96 |
setShouldRender: (shouldRender: boolean) => void
|
97 |
+
|
98 |
// Methods to set global flags
|
99 |
setGraphDataFetchAttempted: (attempted: boolean) => void
|
100 |
setLabelsFetchAttempted: (attempted: boolean) => void
|
|
|
109 |
moveToSelectedNode: false,
|
110 |
isFetching: false,
|
111 |
shouldRender: false,
|
112 |
+
|
113 |
// Initialize global flags
|
114 |
graphDataFetchAttempted: false,
|
115 |
labelsFetchAttempted: false,
|
|
|
147 |
reset: () => {
|
148 |
// Get the existing graph
|
149 |
const existingGraph = get().sigmaGraph;
|
150 |
+
|
151 |
// If we have an existing graph, clear it by removing all nodes
|
152 |
if (existingGraph) {
|
153 |
const nodes = Array.from(existingGraph.nodes());
|
154 |
nodes.forEach(node => existingGraph.dropNode(node));
|
155 |
}
|
156 |
+
|
157 |
set({
|
158 |
selectedNode: null,
|
159 |
focusedNode: null,
|
|
|
195 |
},
|
196 |
|
197 |
setMoveToSelectedNode: (moveToSelectedNode?: boolean) => set({ moveToSelectedNode }),
|
198 |
+
|
199 |
// Methods to set global flags
|
200 |
setGraphDataFetchAttempted: (attempted: boolean) => set({ graphDataFetchAttempted: attempted }),
|
201 |
setLabelsFetchAttempted: (attempted: boolean) => set({ labelsFetchAttempted: attempted })
|