Added tab visibility context and provider for dynamic tab management
- Introduced TabVisibilityProvider component - Created TabContent for conditional rendering - Added context and hooks for tab visibility - Updated DocumentManager dependencies - Integrated provider in App component
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import ThemeProvider from '@/components/ThemeProvider'
|
||||
import TabVisibilityProvider from '@/contexts/TabVisibilityProvider'
|
||||
import MessageAlert from '@/components/MessageAlert'
|
||||
import ApiKeyAlert from '@/components/ApiKeyAlert'
|
||||
import StatusIndicator from '@/components/graph/StatusIndicator'
|
||||
@@ -54,6 +55,7 @@ function App() {
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<TabVisibilityProvider>
|
||||
<main className="flex h-screen w-screen overflow-x-hidden">
|
||||
<Tabs
|
||||
defaultValue={currentTab}
|
||||
@@ -81,6 +83,7 @@ function App() {
|
||||
{apiKeyInvalid && <ApiKeyAlert />}
|
||||
<Toaster />
|
||||
</main>
|
||||
</TabVisibilityProvider>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
39
lightrag_webui/src/components/ui/TabContent.tsx
Normal file
39
lightrag_webui/src/components/ui/TabContent.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useTabVisibility } from '@/contexts/useTabVisibility';
|
||||
|
||||
interface TabContentProps {
|
||||
tabId: string;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* TabContent component that manages visibility based on tab selection
|
||||
* Works with the TabVisibilityContext to show/hide content based on active tab
|
||||
*/
|
||||
const TabContent: React.FC<TabContentProps> = ({ tabId, children, className = '' }) => {
|
||||
const { isTabVisible, setTabVisibility } = useTabVisibility();
|
||||
const isVisible = isTabVisible(tabId);
|
||||
|
||||
// Register this tab with the context when mounted
|
||||
useEffect(() => {
|
||||
setTabVisibility(tabId, true);
|
||||
|
||||
// Cleanup when unmounted
|
||||
return () => {
|
||||
setTabVisibility(tabId, false);
|
||||
};
|
||||
}, [tabId, setTabVisibility]);
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabContent;
|
38
lightrag_webui/src/contexts/TabVisibilityProvider.tsx
Normal file
38
lightrag_webui/src/contexts/TabVisibilityProvider.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { TabVisibilityContext } from './context';
|
||||
import { TabVisibilityContextType } from './types';
|
||||
|
||||
interface TabVisibilityProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider component for the TabVisibility context
|
||||
* Manages the visibility state of tabs throughout the application
|
||||
*/
|
||||
export const TabVisibilityProvider: React.FC<TabVisibilityProviderProps> = ({ children }) => {
|
||||
const [visibleTabs, setVisibleTabs] = useState<Record<string, boolean>>({});
|
||||
|
||||
// Create the context value with memoization to prevent unnecessary re-renders
|
||||
const contextValue = useMemo<TabVisibilityContextType>(
|
||||
() => ({
|
||||
visibleTabs,
|
||||
setTabVisibility: (tabId: string, isVisible: boolean) => {
|
||||
setVisibleTabs((prev) => ({
|
||||
...prev,
|
||||
[tabId]: isVisible,
|
||||
}));
|
||||
},
|
||||
isTabVisible: (tabId: string) => !!visibleTabs[tabId],
|
||||
}),
|
||||
[visibleTabs]
|
||||
);
|
||||
|
||||
return (
|
||||
<TabVisibilityContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</TabVisibilityContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabVisibilityProvider;
|
12
lightrag_webui/src/contexts/context.ts
Normal file
12
lightrag_webui/src/contexts/context.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createContext } from 'react';
|
||||
import { TabVisibilityContextType } from './types';
|
||||
|
||||
// Default context value
|
||||
const defaultContext: TabVisibilityContextType = {
|
||||
visibleTabs: {},
|
||||
setTabVisibility: () => {},
|
||||
isTabVisible: () => false,
|
||||
};
|
||||
|
||||
// Create the context
|
||||
export const TabVisibilityContext = createContext<TabVisibilityContextType>(defaultContext);
|
5
lightrag_webui/src/contexts/types.ts
Normal file
5
lightrag_webui/src/contexts/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface TabVisibilityContextType {
|
||||
visibleTabs: Record<string, boolean>;
|
||||
setTabVisibility: (tabId: string, isVisible: boolean) => void;
|
||||
isTabVisible: (tabId: string) => boolean;
|
||||
}
|
17
lightrag_webui/src/contexts/useTabVisibility.ts
Normal file
17
lightrag_webui/src/contexts/useTabVisibility.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useContext } from 'react';
|
||||
import { TabVisibilityContext } from './context';
|
||||
import { TabVisibilityContextType } from './types';
|
||||
|
||||
/**
|
||||
* Custom hook to access the tab visibility context
|
||||
* @returns The tab visibility context
|
||||
*/
|
||||
export const useTabVisibility = (): TabVisibilityContextType => {
|
||||
const context = useContext(TabVisibilityContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error('useTabVisibility must be used within a TabVisibilityProvider');
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
@@ -48,11 +48,11 @@ export default function DocumentManager() {
|
||||
} catch (err) {
|
||||
toast.error(t('documentPanel.documentManager.errors.loadFailed', { error: errorMessage(err) }))
|
||||
}
|
||||
}, [setDocs])
|
||||
}, [setDocs, t])
|
||||
|
||||
useEffect(() => {
|
||||
fetchDocuments()
|
||||
}, []) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [fetchDocuments, t])
|
||||
|
||||
const scanDocuments = useCallback(async () => {
|
||||
try {
|
||||
@@ -61,7 +61,7 @@ export default function DocumentManager() {
|
||||
} catch (err) {
|
||||
toast.error(t('documentPanel.documentManager.errors.scanFailed', { error: errorMessage(err) }))
|
||||
}
|
||||
}, [])
|
||||
}, [t])
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(async () => {
|
||||
@@ -75,7 +75,7 @@ export default function DocumentManager() {
|
||||
}
|
||||
}, 5000)
|
||||
return () => clearInterval(interval)
|
||||
}, [health, fetchDocuments])
|
||||
}, [health, fetchDocuments, t])
|
||||
|
||||
return (
|
||||
<Card className="!size-full !rounded-none !border-none">
|
||||
|
Reference in New Issue
Block a user