yangdx commited on
Commit
402ce00
Β·
1 Parent(s): 7b96a33

Refactor API key alert and remove message alert component

Browse files

- Move StatusIndicator to status directory
- Remove obsolete MessageAlert component
- Enhance ApiKeyAlert with open state control
- Improve health check logic with alert state
- Add error message display in ApiKeyAlert

lightrag_webui/src/App.tsx CHANGED
@@ -1,9 +1,8 @@
1
  import { useState, useCallback, useEffect, useRef } from 'react'
2
  import ThemeProvider from '@/components/ThemeProvider'
3
  import TabVisibilityProvider from '@/contexts/TabVisibilityProvider'
4
- import MessageAlert from '@/components/MessageAlert'
5
  import ApiKeyAlert from '@/components/ApiKeyAlert'
6
- import StatusIndicator from '@/components/graph/StatusIndicator'
7
  import { healthCheckInterval } from '@/lib/constants'
8
  import { useBackendState, useAuthStore } from '@/stores/state'
9
  import { useSettingsStore } from '@/stores/settings'
@@ -22,26 +21,30 @@ function App() {
22
  const message = useBackendState.use.message()
23
  const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
24
  const currentTab = useSettingsStore.use.currentTab()
25
- const [apiKeyInvalid, setApiKeyInvalid] = useState(false)
26
  const versionCheckRef = useRef(false); // Prevent duplicate calls in Vite dev mode
27
 
 
 
 
 
 
 
 
28
  // Health check - can be disabled
29
  useEffect(() => {
30
- // Only execute if health check is enabled
31
- if (!enableHealthCheck) return;
32
 
33
  // Health check function
34
  const performHealthCheck = async () => {
35
  await useBackendState.getState().check();
36
  };
37
 
38
- // Execute immediately
39
- performHealthCheck();
40
-
41
  // Set interval for periodic execution
42
  const interval = setInterval(performHealthCheck, healthCheckInterval * 1000);
43
  return () => clearInterval(interval);
44
- }, [enableHealthCheck]);
45
 
46
  // Version check - independent and executed only once
47
  useEffect(() => {
@@ -90,12 +93,10 @@ function App() {
90
  useEffect(() => {
91
  if (message) {
92
  if (message.includes(InvalidApiKeyError) || message.includes(RequireApiKeError)) {
93
- setApiKeyInvalid(true)
94
- return
95
  }
96
  }
97
- setApiKeyInvalid(false)
98
- }, [message, setApiKeyInvalid])
99
 
100
  return (
101
  <ThemeProvider>
@@ -123,8 +124,7 @@ function App() {
123
  </div>
124
  </Tabs>
125
  {enableHealthCheck && <StatusIndicator />}
126
- {message !== null && !apiKeyInvalid && <MessageAlert />}
127
- {apiKeyInvalid && <ApiKeyAlert />}
128
  </main>
129
  </TabVisibilityProvider>
130
  </ThemeProvider>
 
1
  import { useState, useCallback, useEffect, useRef } from 'react'
2
  import ThemeProvider from '@/components/ThemeProvider'
3
  import TabVisibilityProvider from '@/contexts/TabVisibilityProvider'
 
4
  import ApiKeyAlert from '@/components/ApiKeyAlert'
5
+ import StatusIndicator from '@/components/status/StatusIndicator'
6
  import { healthCheckInterval } from '@/lib/constants'
7
  import { useBackendState, useAuthStore } from '@/stores/state'
8
  import { useSettingsStore } from '@/stores/settings'
 
21
  const message = useBackendState.use.message()
22
  const enableHealthCheck = useSettingsStore.use.enableHealthCheck()
23
  const currentTab = useSettingsStore.use.currentTab()
24
+ const [apiKeyAlertOpen, setApiKeyAlertOpen] = useState(false)
25
  const versionCheckRef = useRef(false); // Prevent duplicate calls in Vite dev mode
26
 
27
+ const handleApiKeyAlertOpenChange = useCallback((open: boolean) => {
28
+ setApiKeyAlertOpen(open)
29
+ if (!open) {
30
+ useBackendState.getState().clear()
31
+ }
32
+ }, [])
33
+
34
  // Health check - can be disabled
35
  useEffect(() => {
36
+ // Only execute if health check is enabled and ApiKeyAlert is closed
37
+ if (!enableHealthCheck || apiKeyAlertOpen) return;
38
 
39
  // Health check function
40
  const performHealthCheck = async () => {
41
  await useBackendState.getState().check();
42
  };
43
 
 
 
 
44
  // Set interval for periodic execution
45
  const interval = setInterval(performHealthCheck, healthCheckInterval * 1000);
46
  return () => clearInterval(interval);
47
+ }, [enableHealthCheck, apiKeyAlertOpen]);
48
 
49
  // Version check - independent and executed only once
50
  useEffect(() => {
 
93
  useEffect(() => {
94
  if (message) {
95
  if (message.includes(InvalidApiKeyError) || message.includes(RequireApiKeError)) {
96
+ setApiKeyAlertOpen(true)
 
97
  }
98
  }
99
+ }, [message])
 
100
 
101
  return (
102
  <ThemeProvider>
 
124
  </div>
125
  </Tabs>
126
  {enableHealthCheck && <StatusIndicator />}
127
+ <ApiKeyAlert open={apiKeyAlertOpen} onOpenChange={handleApiKeyAlertOpenChange} />
 
128
  </main>
129
  </TabVisibilityProvider>
130
  </ThemeProvider>
lightrag_webui/src/components/ApiKeyAlert.tsx CHANGED
@@ -12,10 +12,12 @@ import { useSettingsStore } from '@/stores/settings'
12
  import { useBackendState } from '@/stores/state'
13
  import { InvalidApiKeyError, RequireApiKeError } from '@/api/lightrag'
14
 
15
- import { toast } from 'sonner'
 
 
 
16
 
17
- const ApiKeyAlert = () => {
18
- const [opened, setOpened] = useState<boolean>(true)
19
  const apiKey = useSettingsStore.use.apiKey()
20
  const [tempApiKey, setTempApiKey] = useState<string>('')
21
  const message = useBackendState.use.message()
@@ -32,14 +34,10 @@ const ApiKeyAlert = () => {
32
  }
33
  }, [message, setOpened])
34
 
35
- const setApiKey = useCallback(async () => {
36
  useSettingsStore.setState({ apiKey: tempApiKey || null })
37
- if (await useBackendState.getState().check()) {
38
- setOpened(false)
39
- return
40
- }
41
- toast.error('API Key is invalid')
42
- }, [tempApiKey])
43
 
44
  const handleTempApiKeyChange = useCallback(
45
  (e: React.ChangeEvent<HTMLInputElement>) => {
@@ -53,22 +51,31 @@ const ApiKeyAlert = () => {
53
  <AlertDialogContent>
54
  <AlertDialogHeader>
55
  <AlertDialogTitle>API Key is required</AlertDialogTitle>
56
- <AlertDialogDescription>Please enter your API key</AlertDialogDescription>
 
 
57
  </AlertDialogHeader>
58
- <form className="flex gap-2" onSubmit={(e) => e.preventDefault()}>
59
- <Input
60
- type="password"
61
- value={tempApiKey}
62
- onChange={handleTempApiKeyChange}
63
- placeholder="Enter your API key"
64
- className="max-h-full w-full min-w-0"
65
- autoComplete="off"
66
- />
 
67
 
68
- <Button onClick={setApiKey} variant="outline" size="sm">
69
- Save
70
- </Button>
71
- </form>
 
 
 
 
 
 
72
  </AlertDialogContent>
73
  </AlertDialog>
74
  )
 
12
  import { useBackendState } from '@/stores/state'
13
  import { InvalidApiKeyError, RequireApiKeError } from '@/api/lightrag'
14
 
15
+ interface ApiKeyAlertProps {
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ }
19
 
20
+ const ApiKeyAlert = ({ open: opened, onOpenChange: setOpened }: ApiKeyAlertProps) => {
 
21
  const apiKey = useSettingsStore.use.apiKey()
22
  const [tempApiKey, setTempApiKey] = useState<string>('')
23
  const message = useBackendState.use.message()
 
34
  }
35
  }, [message, setOpened])
36
 
37
+ const setApiKey = useCallback(() => {
38
  useSettingsStore.setState({ apiKey: tempApiKey || null })
39
+ setOpened(false)
40
+ }, [tempApiKey, setOpened])
 
 
 
 
41
 
42
  const handleTempApiKeyChange = useCallback(
43
  (e: React.ChangeEvent<HTMLInputElement>) => {
 
51
  <AlertDialogContent>
52
  <AlertDialogHeader>
53
  <AlertDialogTitle>API Key is required</AlertDialogTitle>
54
+ <AlertDialogDescription>
55
+ Please enter your API key to access the service
56
+ </AlertDialogDescription>
57
  </AlertDialogHeader>
58
+ <div className="flex flex-col gap-4">
59
+ <form className="flex gap-2" onSubmit={(e) => e.preventDefault()}>
60
+ <Input
61
+ type="password"
62
+ value={tempApiKey}
63
+ onChange={handleTempApiKeyChange}
64
+ placeholder="Enter your API key"
65
+ className="max-h-full w-full min-w-0"
66
+ autoComplete="off"
67
+ />
68
 
69
+ <Button onClick={setApiKey} variant="outline" size="sm">
70
+ Save
71
+ </Button>
72
+ </form>
73
+ {message && (
74
+ <div className="text-sm text-red-500">
75
+ {message}
76
+ </div>
77
+ )}
78
+ </div>
79
  </AlertDialogContent>
80
  </AlertDialog>
81
  )
lightrag_webui/src/components/MessageAlert.tsx DELETED
@@ -1,56 +0,0 @@
1
- import { Alert, AlertDescription, AlertTitle } from '@/components/ui/Alert'
2
- import { useBackendState } from '@/stores/state'
3
- import { useEffect, useState } from 'react'
4
- import { cn } from '@/lib/utils'
5
-
6
- // import Button from '@/components/ui/Button'
7
- // import { controlButtonVariant } from '@/lib/constants'
8
-
9
- import { AlertCircle } from 'lucide-react'
10
-
11
- const MessageAlert = () => {
12
- const health = useBackendState.use.health()
13
- const message = useBackendState.use.message()
14
- const messageTitle = useBackendState.use.messageTitle()
15
- const [isMounted, setIsMounted] = useState(false)
16
-
17
- useEffect(() => {
18
- setTimeout(() => {
19
- setIsMounted(true)
20
- }, 50)
21
- }, [])
22
-
23
- return (
24
- <Alert
25
- // variant={health ? 'default' : 'destructive'}
26
- className={cn(
27
- 'bg-background/90 absolute top-12 left-1/2 flex w-auto max-w-lg -translate-x-1/2 transform items-center gap-4 shadow-md backdrop-blur-lg transition-all duration-500 ease-in-out',
28
- isMounted ? 'translate-y-0 opacity-100' : '-translate-y-20 opacity-0',
29
- !health && 'bg-red-700 text-white'
30
- )}
31
- >
32
- {!health && (
33
- <div>
34
- <AlertCircle className="size-4" />
35
- </div>
36
- )}
37
- <div>
38
- <AlertTitle className="font-bold">{messageTitle}</AlertTitle>
39
- <AlertDescription>{message}</AlertDescription>
40
- </div>
41
- {/* <div className="flex">
42
- <div className="flex-auto" />
43
- <Button
44
- size="sm"
45
- variant={controlButtonVariant}
46
- className="border-primary max-h-8 border !p-2 text-xs"
47
- onClick={() => useBackendState.getState().clear()}
48
- >
49
- Close
50
- </Button>
51
- </div> */}
52
- </Alert>
53
- )
54
- }
55
-
56
- export default MessageAlert
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lightrag_webui/src/components/{graph β†’ status}/StatusCard.tsx RENAMED
File without changes
lightrag_webui/src/components/{graph β†’ status}/StatusIndicator.tsx RENAMED
@@ -2,7 +2,7 @@ import { cn } from '@/lib/utils'
2
  import { useBackendState } from '@/stores/state'
3
  import { useEffect, useState } from 'react'
4
  import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
5
- import StatusCard from '@/components/graph/StatusCard'
6
  import { useTranslation } from 'react-i18next'
7
 
8
  const StatusIndicator = () => {
 
2
  import { useBackendState } from '@/stores/state'
3
  import { useEffect, useState } from 'react'
4
  import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
5
+ import StatusCard from '@/components/status/StatusCard'
6
  import { useTranslation } from 'react-i18next'
7
 
8
  const StatusIndicator = () => {