Sync frontend with backend MAX_GRAPH_NODES

- Auto-adjust graph nodes when limit changes
- Add refresh trigger for node count changes
- Store backend limit in settings
This commit is contained in:
yangdx 2025-07-08 00:21:42 +08:00
parent ef79088f60
commit 9bf048a4b1
3 changed files with 64 additions and 15 deletions

View file

@ -1,4 +1,4 @@
import { useState, useCallback} from 'react'
import { useState, useCallback, useEffect} from 'react'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
import Checkbox from '@/components/ui/Checkbox'
import Button from '@/components/ui/Button'
@ -62,6 +62,10 @@ const LabeledNumberInput = ({
// Create unique ID using the label text converted to lowercase with spaces removed
const id = `input-${label.toLowerCase().replace(/\s+/g, '-')}`;
useEffect(() => {
setCurrentValue(value)
}, [value])
const onValueChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value.trim()
@ -154,6 +158,7 @@ export default function Settings() {
const maxEdgeSize = useSettingsStore.use.maxEdgeSize()
const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth()
const graphMaxNodes = useSettingsStore.use.graphMaxNodes()
const backendMaxGraphNodes = useSettingsStore.use.backendMaxGraphNodes()
const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations()
const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
@ -213,14 +218,10 @@ export default function Settings() {
}, [])
const setGraphMaxNodes = useCallback((nodes: number) => {
if (nodes < 1 || nodes > 1000) return
useSettingsStore.setState({ graphMaxNodes: nodes })
const currentLabel = useSettingsStore.getState().queryLabel
useSettingsStore.getState().setQueryLabel('')
setTimeout(() => {
useSettingsStore.getState().setQueryLabel(currentLabel)
}, 300)
}, [])
const maxLimit = backendMaxGraphNodes || 1000
if (nodes < 1 || nodes > maxLimit) return
useSettingsStore.getState().setGraphMaxNodes(nodes, true)
}, [backendMaxGraphNodes])
const setGraphLayoutMaxIterations = useCallback((iterations: number) => {
if (iterations < 1) return
@ -360,11 +361,11 @@ export default function Settings() {
onEditFinished={setGraphQueryMaxDepth}
/>
<LabeledNumberInput
label={t('graphPanel.sideBar.settings.maxNodes')}
label={`${t('graphPanel.sideBar.settings.maxNodes')} (≤ ${backendMaxGraphNodes || 1000})`}
min={1}
max={1000}
max={backendMaxGraphNodes || 1000}
value={graphMaxNodes}
defaultValue={1000}
defaultValue={backendMaxGraphNodes || 1000}
onEditFinished={setGraphMaxNodes}
/>
<LabeledNumberInput

View file

@ -36,7 +36,10 @@ interface SettingsState {
setGraphQueryMaxDepth: (depth: number) => void
graphMaxNodes: number
setGraphMaxNodes: (nodes: number) => void
setGraphMaxNodes: (nodes: number, triggerRefresh?: boolean) => void
backendMaxGraphNodes: number | null
setBackendMaxGraphNodes: (maxNodes: number | null) => void
graphLayoutMaxIterations: number
setGraphLayoutMaxIterations: (iterations: number) => void
@ -90,6 +93,7 @@ const useSettingsStoreBase = create<SettingsState>()(
graphQueryMaxDepth: 3,
graphMaxNodes: 1000,
backendMaxGraphNodes: null,
graphLayoutMaxIterations: 15,
queryLabel: defaultQueryLabel,
@ -143,7 +147,27 @@ const useSettingsStoreBase = create<SettingsState>()(
setGraphQueryMaxDepth: (depth: number) => set({ graphQueryMaxDepth: depth }),
setGraphMaxNodes: (nodes: number) => set({ graphMaxNodes: nodes }),
setGraphMaxNodes: (nodes: number, triggerRefresh: boolean = false) => {
const state = useSettingsStore.getState();
if (state.graphMaxNodes === nodes) {
return;
}
if (triggerRefresh) {
const currentLabel = state.queryLabel;
// Atomically update both the node count and the query label to trigger a refresh.
set({ graphMaxNodes: nodes, queryLabel: '' });
// Restore the label after a short delay.
setTimeout(() => {
set({ queryLabel: currentLabel });
}, 300);
} else {
set({ graphMaxNodes: nodes });
}
},
setBackendMaxGraphNodes: (maxNodes: number | null) => set({ backendMaxGraphNodes: maxNodes }),
setMinEdgeSize: (size: number) => set({ minEdgeSize: size }),
@ -168,7 +192,7 @@ const useSettingsStoreBase = create<SettingsState>()(
{
name: 'settings-storage',
storage: createJSONStorage(() => localStorage),
version: 13,
version: 14,
migrate: (state: any, version: number) => {
if (version < 2) {
state.showEdgeLabel = false
@ -232,6 +256,10 @@ const useSettingsStoreBase = create<SettingsState>()(
state.querySettings.user_prompt = ''
}
}
if (version < 14) {
// Add backendMaxGraphNodes field for older versions
state.backendMaxGraphNodes = null
}
return state
}
}

View file

@ -1,6 +1,7 @@
import { create } from 'zustand'
import { createSelectors } from '@/lib/utils'
import { checkHealth, LightragStatus } from '@/api/lightrag'
import { useSettingsStore } from './settings'
interface BackendState {
health: boolean
@ -58,6 +59,25 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
);
}
// Extract and store backend max graph nodes limit
if (health.configuration?.max_graph_nodes) {
const maxNodes = parseInt(health.configuration.max_graph_nodes, 10)
if (!isNaN(maxNodes) && maxNodes > 0) {
const currentBackendMaxNodes = useSettingsStore.getState().backendMaxGraphNodes
// Only update if the backend limit has actually changed
if (currentBackendMaxNodes !== maxNodes) {
useSettingsStore.getState().setBackendMaxGraphNodes(maxNodes)
// Auto-adjust current graphMaxNodes if it exceeds the new backend limit
const currentMaxNodes = useSettingsStore.getState().graphMaxNodes
if (currentMaxNodes > maxNodes) {
useSettingsStore.getState().setGraphMaxNodes(maxNodes, true)
}
}
}
}
set({
health: true,
message: null,