Sync frontend with backend MAX_GRAPH_NODES
Browse files- Auto-adjust graph nodes when limit changes
- Add refresh trigger for node count changes
- Store backend limit in settings
lightrag_webui/src/components/graph/Settings.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
import { useState, useCallback} from 'react'
|
2 |
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
|
3 |
import Checkbox from '@/components/ui/Checkbox'
|
4 |
import Button from '@/components/ui/Button'
|
@@ -62,6 +62,10 @@ const LabeledNumberInput = ({
|
|
62 |
// Create unique ID using the label text converted to lowercase with spaces removed
|
63 |
const id = `input-${label.toLowerCase().replace(/\s+/g, '-')}`;
|
64 |
|
|
|
|
|
|
|
|
|
65 |
const onValueChange = useCallback(
|
66 |
(e: React.ChangeEvent<HTMLInputElement>) => {
|
67 |
const text = e.target.value.trim()
|
@@ -154,6 +158,7 @@ export default function Settings() {
|
|
154 |
const maxEdgeSize = useSettingsStore.use.maxEdgeSize()
|
155 |
const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth()
|
156 |
const graphMaxNodes = useSettingsStore.use.graphMaxNodes()
|
|
|
157 |
const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations()
|
158 |
|
159 |
const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
|
@@ -213,14 +218,10 @@ export default function Settings() {
|
|
213 |
}, [])
|
214 |
|
215 |
const setGraphMaxNodes = useCallback((nodes: number) => {
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
setTimeout(() => {
|
221 |
-
useSettingsStore.getState().setQueryLabel(currentLabel)
|
222 |
-
}, 300)
|
223 |
-
}, [])
|
224 |
|
225 |
const setGraphLayoutMaxIterations = useCallback((iterations: number) => {
|
226 |
if (iterations < 1) return
|
@@ -360,11 +361,11 @@ export default function Settings() {
|
|
360 |
onEditFinished={setGraphQueryMaxDepth}
|
361 |
/>
|
362 |
<LabeledNumberInput
|
363 |
-
label={t('graphPanel.sideBar.settings.maxNodes')}
|
364 |
min={1}
|
365 |
-
max={1000}
|
366 |
value={graphMaxNodes}
|
367 |
-
defaultValue={1000}
|
368 |
onEditFinished={setGraphMaxNodes}
|
369 |
/>
|
370 |
<LabeledNumberInput
|
|
|
1 |
+
import { useState, useCallback, useEffect} from 'react'
|
2 |
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
|
3 |
import Checkbox from '@/components/ui/Checkbox'
|
4 |
import Button from '@/components/ui/Button'
|
|
|
62 |
// Create unique ID using the label text converted to lowercase with spaces removed
|
63 |
const id = `input-${label.toLowerCase().replace(/\s+/g, '-')}`;
|
64 |
|
65 |
+
useEffect(() => {
|
66 |
+
setCurrentValue(value)
|
67 |
+
}, [value])
|
68 |
+
|
69 |
const onValueChange = useCallback(
|
70 |
(e: React.ChangeEvent<HTMLInputElement>) => {
|
71 |
const text = e.target.value.trim()
|
|
|
158 |
const maxEdgeSize = useSettingsStore.use.maxEdgeSize()
|
159 |
const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth()
|
160 |
const graphMaxNodes = useSettingsStore.use.graphMaxNodes()
|
161 |
+
const backendMaxGraphNodes = useSettingsStore.use.backendMaxGraphNodes()
|
162 |
const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations()
|
163 |
|
164 |
const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
|
|
|
218 |
}, [])
|
219 |
|
220 |
const setGraphMaxNodes = useCallback((nodes: number) => {
|
221 |
+
const maxLimit = backendMaxGraphNodes || 1000
|
222 |
+
if (nodes < 1 || nodes > maxLimit) return
|
223 |
+
useSettingsStore.getState().setGraphMaxNodes(nodes, true)
|
224 |
+
}, [backendMaxGraphNodes])
|
|
|
|
|
|
|
|
|
225 |
|
226 |
const setGraphLayoutMaxIterations = useCallback((iterations: number) => {
|
227 |
if (iterations < 1) return
|
|
|
361 |
onEditFinished={setGraphQueryMaxDepth}
|
362 |
/>
|
363 |
<LabeledNumberInput
|
364 |
+
label={`${t('graphPanel.sideBar.settings.maxNodes')} (≤ ${backendMaxGraphNodes || 1000})`}
|
365 |
min={1}
|
366 |
+
max={backendMaxGraphNodes || 1000}
|
367 |
value={graphMaxNodes}
|
368 |
+
defaultValue={backendMaxGraphNodes || 1000}
|
369 |
onEditFinished={setGraphMaxNodes}
|
370 |
/>
|
371 |
<LabeledNumberInput
|
lightrag_webui/src/stores/settings.ts
CHANGED
@@ -36,7 +36,10 @@ interface SettingsState {
|
|
36 |
setGraphQueryMaxDepth: (depth: number) => void
|
37 |
|
38 |
graphMaxNodes: number
|
39 |
-
setGraphMaxNodes: (nodes: number) => void
|
|
|
|
|
|
|
40 |
|
41 |
graphLayoutMaxIterations: number
|
42 |
setGraphLayoutMaxIterations: (iterations: number) => void
|
@@ -90,6 +93,7 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|
90 |
|
91 |
graphQueryMaxDepth: 3,
|
92 |
graphMaxNodes: 1000,
|
|
|
93 |
graphLayoutMaxIterations: 15,
|
94 |
|
95 |
queryLabel: defaultQueryLabel,
|
@@ -143,7 +147,27 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|
143 |
|
144 |
setGraphQueryMaxDepth: (depth: number) => set({ graphQueryMaxDepth: depth }),
|
145 |
|
146 |
-
setGraphMaxNodes: (nodes: number) =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
setMinEdgeSize: (size: number) => set({ minEdgeSize: size }),
|
149 |
|
@@ -168,7 +192,7 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|
168 |
{
|
169 |
name: 'settings-storage',
|
170 |
storage: createJSONStorage(() => localStorage),
|
171 |
-
version:
|
172 |
migrate: (state: any, version: number) => {
|
173 |
if (version < 2) {
|
174 |
state.showEdgeLabel = false
|
@@ -232,6 +256,10 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|
232 |
state.querySettings.user_prompt = ''
|
233 |
}
|
234 |
}
|
|
|
|
|
|
|
|
|
235 |
return state
|
236 |
}
|
237 |
}
|
|
|
36 |
setGraphQueryMaxDepth: (depth: number) => void
|
37 |
|
38 |
graphMaxNodes: number
|
39 |
+
setGraphMaxNodes: (nodes: number, triggerRefresh?: boolean) => void
|
40 |
+
|
41 |
+
backendMaxGraphNodes: number | null
|
42 |
+
setBackendMaxGraphNodes: (maxNodes: number | null) => void
|
43 |
|
44 |
graphLayoutMaxIterations: number
|
45 |
setGraphLayoutMaxIterations: (iterations: number) => void
|
|
|
93 |
|
94 |
graphQueryMaxDepth: 3,
|
95 |
graphMaxNodes: 1000,
|
96 |
+
backendMaxGraphNodes: null,
|
97 |
graphLayoutMaxIterations: 15,
|
98 |
|
99 |
queryLabel: defaultQueryLabel,
|
|
|
147 |
|
148 |
setGraphQueryMaxDepth: (depth: number) => set({ graphQueryMaxDepth: depth }),
|
149 |
|
150 |
+
setGraphMaxNodes: (nodes: number, triggerRefresh: boolean = false) => {
|
151 |
+
const state = useSettingsStore.getState();
|
152 |
+
if (state.graphMaxNodes === nodes) {
|
153 |
+
return;
|
154 |
+
}
|
155 |
+
|
156 |
+
if (triggerRefresh) {
|
157 |
+
const currentLabel = state.queryLabel;
|
158 |
+
// Atomically update both the node count and the query label to trigger a refresh.
|
159 |
+
set({ graphMaxNodes: nodes, queryLabel: '' });
|
160 |
+
|
161 |
+
// Restore the label after a short delay.
|
162 |
+
setTimeout(() => {
|
163 |
+
set({ queryLabel: currentLabel });
|
164 |
+
}, 300);
|
165 |
+
} else {
|
166 |
+
set({ graphMaxNodes: nodes });
|
167 |
+
}
|
168 |
+
},
|
169 |
+
|
170 |
+
setBackendMaxGraphNodes: (maxNodes: number | null) => set({ backendMaxGraphNodes: maxNodes }),
|
171 |
|
172 |
setMinEdgeSize: (size: number) => set({ minEdgeSize: size }),
|
173 |
|
|
|
192 |
{
|
193 |
name: 'settings-storage',
|
194 |
storage: createJSONStorage(() => localStorage),
|
195 |
+
version: 14,
|
196 |
migrate: (state: any, version: number) => {
|
197 |
if (version < 2) {
|
198 |
state.showEdgeLabel = false
|
|
|
256 |
state.querySettings.user_prompt = ''
|
257 |
}
|
258 |
}
|
259 |
+
if (version < 14) {
|
260 |
+
// Add backendMaxGraphNodes field for older versions
|
261 |
+
state.backendMaxGraphNodes = null
|
262 |
+
}
|
263 |
return state
|
264 |
}
|
265 |
}
|
lightrag_webui/src/stores/state.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import { create } from 'zustand'
|
2 |
import { createSelectors } from '@/lib/utils'
|
3 |
import { checkHealth, LightragStatus } from '@/api/lightrag'
|
|
|
4 |
|
5 |
interface BackendState {
|
6 |
health: boolean
|
@@ -58,6 +59,25 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
|
|
58 |
);
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
set({
|
62 |
health: true,
|
63 |
message: null,
|
|
|
1 |
import { create } from 'zustand'
|
2 |
import { createSelectors } from '@/lib/utils'
|
3 |
import { checkHealth, LightragStatus } from '@/api/lightrag'
|
4 |
+
import { useSettingsStore } from './settings'
|
5 |
|
6 |
interface BackendState {
|
7 |
health: boolean
|
|
|
59 |
);
|
60 |
}
|
61 |
|
62 |
+
// Extract and store backend max graph nodes limit
|
63 |
+
if (health.configuration?.max_graph_nodes) {
|
64 |
+
const maxNodes = parseInt(health.configuration.max_graph_nodes, 10)
|
65 |
+
if (!isNaN(maxNodes) && maxNodes > 0) {
|
66 |
+
const currentBackendMaxNodes = useSettingsStore.getState().backendMaxGraphNodes
|
67 |
+
|
68 |
+
// Only update if the backend limit has actually changed
|
69 |
+
if (currentBackendMaxNodes !== maxNodes) {
|
70 |
+
useSettingsStore.getState().setBackendMaxGraphNodes(maxNodes)
|
71 |
+
|
72 |
+
// Auto-adjust current graphMaxNodes if it exceeds the new backend limit
|
73 |
+
const currentMaxNodes = useSettingsStore.getState().graphMaxNodes
|
74 |
+
if (currentMaxNodes > maxNodes) {
|
75 |
+
useSettingsStore.getState().setGraphMaxNodes(maxNodes, true)
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
}
|
80 |
+
|
81 |
set({
|
82 |
health: true,
|
83 |
message: null,
|