Add title support for webui
This commit is contained in:
@@ -5,8 +5,8 @@
|
|||||||
# PORT=9621
|
# PORT=9621
|
||||||
# WORKERS=2
|
# WORKERS=2
|
||||||
# CORS_ORIGINS=http://localhost:3000,http://localhost:8080
|
# CORS_ORIGINS=http://localhost:3000,http://localhost:8080
|
||||||
# WEBUI_TITLE='My Best RAG System'
|
WEBUI_TITLE='Graph RAG Engine'
|
||||||
# WEBUI_DESCRIPTION="My Knowledge System Based on LightRAG"
|
WEBUI_DESCRIPTION="Simple and Fast Graph Based RAG System"
|
||||||
|
|
||||||
### Optional SSL Configuration
|
### Optional SSL Configuration
|
||||||
# SSL=true
|
# SSL=true
|
||||||
|
@@ -3,6 +3,7 @@ import { backendBaseUrl } from '@/lib/constants'
|
|||||||
import { errorMessage } from '@/lib/utils'
|
import { errorMessage } from '@/lib/utils'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
import { navigationService } from '@/services/navigation'
|
import { navigationService } from '@/services/navigation'
|
||||||
|
import { useAuthStore } from '@/stores/state'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
export type LightragNodeType = {
|
export type LightragNodeType = {
|
||||||
@@ -46,6 +47,8 @@ export type LightragStatus = {
|
|||||||
api_version?: string
|
api_version?: string
|
||||||
auth_mode?: 'enabled' | 'disabled'
|
auth_mode?: 'enabled' | 'disabled'
|
||||||
pipeline_busy: boolean
|
pipeline_busy: boolean
|
||||||
|
webui_title?: string
|
||||||
|
webui_description?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LightragDocumentsScanProgress = {
|
export type LightragDocumentsScanProgress = {
|
||||||
@@ -140,6 +143,8 @@ export type AuthStatusResponse = {
|
|||||||
message?: string
|
message?: string
|
||||||
core_version?: string
|
core_version?: string
|
||||||
api_version?: string
|
api_version?: string
|
||||||
|
webui_title?: string
|
||||||
|
webui_description?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PipelineStatusResponse = {
|
export type PipelineStatusResponse = {
|
||||||
@@ -163,6 +168,8 @@ export type LoginResponse = {
|
|||||||
message?: string // Optional message
|
message?: string // Optional message
|
||||||
core_version?: string
|
core_version?: string
|
||||||
api_version?: string
|
api_version?: string
|
||||||
|
webui_title?: string
|
||||||
|
webui_description?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const InvalidApiKeyError = 'Invalid API Key'
|
export const InvalidApiKeyError = 'Invalid API Key'
|
||||||
@@ -419,12 +426,26 @@ export const getAuthStatus = async (): Promise<AuthStatusResponse> => {
|
|||||||
// For unconfigured auth, ensure we have an access token
|
// For unconfigured auth, ensure we have an access token
|
||||||
if (!response.data.auth_configured) {
|
if (!response.data.auth_configured) {
|
||||||
if (response.data.access_token && typeof response.data.access_token === 'string') {
|
if (response.data.access_token && typeof response.data.access_token === 'string') {
|
||||||
|
// Update custom title if available
|
||||||
|
if (response.data.webui_title || response.data.webui_description) {
|
||||||
|
useAuthStore.getState().setCustomTitle(
|
||||||
|
response.data.webui_title || null,
|
||||||
|
response.data.webui_description || null
|
||||||
|
);
|
||||||
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
} else {
|
} else {
|
||||||
console.warn('Auth not configured but no valid access token provided');
|
console.warn('Auth not configured but no valid access token provided');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For configured auth, just return the data
|
// For configured auth, just return the data
|
||||||
|
// Update custom title if available
|
||||||
|
if (response.data.webui_title || response.data.webui_description) {
|
||||||
|
useAuthStore.getState().setCustomTitle(
|
||||||
|
response.data.webui_title || null,
|
||||||
|
response.data.webui_description || null
|
||||||
|
);
|
||||||
|
}
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,5 +484,13 @@ export const loginToServer = async (username: string, password: string): Promise
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update custom title if available
|
||||||
|
if (response.data.webui_title || response.data.webui_description) {
|
||||||
|
useAuthStore.getState().setCustomTitle(
|
||||||
|
response.data.webui_title || null,
|
||||||
|
response.data.webui_description || null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import { cn } from '@/lib/utils'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { navigationService } from '@/services/navigation'
|
import { navigationService } from '@/services/navigation'
|
||||||
import { ZapIcon, GithubIcon, LogOutIcon } from 'lucide-react'
|
import { ZapIcon, GithubIcon, LogOutIcon } from 'lucide-react'
|
||||||
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/Tooltip'
|
||||||
|
|
||||||
interface NavigationTabProps {
|
interface NavigationTabProps {
|
||||||
value: string
|
value: string
|
||||||
@@ -55,7 +56,7 @@ function TabsNavigation() {
|
|||||||
|
|
||||||
export default function SiteHeader() {
|
export default function SiteHeader() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { isGuestMode, coreVersion, apiVersion, username } = useAuthStore()
|
const { isGuestMode, coreVersion, apiVersion, username, webuiTitle, webuiDescription } = useAuthStore()
|
||||||
|
|
||||||
const versionDisplay = (coreVersion && apiVersion)
|
const versionDisplay = (coreVersion && apiVersion)
|
||||||
? `${coreVersion}/${apiVersion}`
|
? `${coreVersion}/${apiVersion}`
|
||||||
@@ -67,17 +68,31 @@ export default function SiteHeader() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="border-border/40 bg-background/95 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50 flex h-10 w-full border-b px-4 backdrop-blur">
|
<header className="border-border/40 bg-background/95 supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50 flex h-10 w-full border-b px-4 backdrop-blur">
|
||||||
<div className="w-[200px] flex items-center">
|
<div className="min-w-[200px] w-auto flex items-center">
|
||||||
<a href={webuiPrefix} className="flex items-center gap-2">
|
<a href={webuiPrefix} className="flex items-center gap-2">
|
||||||
<ZapIcon className="size-4 text-emerald-400" aria-hidden="true" />
|
<ZapIcon className="size-4 text-emerald-400" aria-hidden="true" />
|
||||||
{/* <img src='/logo.png' className="size-4" /> */}
|
{/* <img src='/logo.png' className="size-4" /> */}
|
||||||
<span className="font-bold md:inline-block">{SiteInfo.name}</span>
|
<span className="font-bold md:inline-block">{SiteInfo.name}</span>
|
||||||
{versionDisplay && (
|
|
||||||
<span className="ml-2 text-xs text-gray-500 dark:text-gray-400">
|
|
||||||
v{versionDisplay}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</a>
|
</a>
|
||||||
|
{webuiTitle && (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span className="mx-1 text-xs text-gray-500 dark:text-gray-400">|</span>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<span className="font-medium text-sm cursor-default">
|
||||||
|
{webuiTitle}
|
||||||
|
</span>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{webuiDescription && (
|
||||||
|
<TooltipContent side="bottom">
|
||||||
|
{webuiDescription}
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex h-10 flex-1 items-center justify-center">
|
<div className="flex h-10 flex-1 items-center justify-center">
|
||||||
@@ -91,6 +106,11 @@ export default function SiteHeader() {
|
|||||||
|
|
||||||
<nav className="w-[200px] flex items-center justify-end">
|
<nav className="w-[200px] flex items-center justify-end">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
{versionDisplay && (
|
||||||
|
<span className="text-xs text-gray-500 dark:text-gray-400 mr-1">
|
||||||
|
v{versionDisplay}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<Button variant="ghost" size="icon" side="bottom" tooltip={t('header.projectRepository')}>
|
<Button variant="ghost" size="icon" side="bottom" tooltip={t('header.projectRepository')}>
|
||||||
<a href={SiteInfo.github} target="_blank" rel="noopener noreferrer">
|
<a href={SiteInfo.github} target="_blank" rel="noopener noreferrer">
|
||||||
<GithubIcon className="size-4" aria-hidden="true" />
|
<GithubIcon className="size-4" aria-hidden="true" />
|
||||||
|
@@ -22,10 +22,13 @@ interface AuthState {
|
|||||||
coreVersion: string | null;
|
coreVersion: string | null;
|
||||||
apiVersion: string | null;
|
apiVersion: string | null;
|
||||||
username: string | null; // login username
|
username: string | null; // login username
|
||||||
|
webuiTitle: string | null; // Custom title
|
||||||
|
webuiDescription: string | null; // Title description
|
||||||
|
|
||||||
login: (token: string, isGuest?: boolean, coreVersion?: string | null, apiVersion?: string | null) => void;
|
login: (token: string, isGuest?: boolean, coreVersion?: string | null, apiVersion?: string | null, webuiTitle?: string | null, webuiDescription?: string | null) => void;
|
||||||
logout: () => void;
|
logout: () => void;
|
||||||
setVersion: (coreVersion: string | null, apiVersion: string | null) => void;
|
setVersion: (coreVersion: string | null, apiVersion: string | null) => void;
|
||||||
|
setCustomTitle: (webuiTitle: string | null, webuiDescription: string | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useBackendStateStoreBase = create<BackendState>()((set) => ({
|
const useBackendStateStoreBase = create<BackendState>()((set) => ({
|
||||||
@@ -46,6 +49,14 @@ const useBackendStateStoreBase = create<BackendState>()((set) => ({
|
|||||||
health.api_version || null
|
health.api_version || null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update custom title information if health check returns it
|
||||||
|
if (health.webui_title || health.webui_description) {
|
||||||
|
useAuthStore.getState().setCustomTitle(
|
||||||
|
health.webui_title || null,
|
||||||
|
health.webui_description || null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
set({
|
set({
|
||||||
health: true,
|
health: true,
|
||||||
@@ -107,10 +118,12 @@ const isGuestToken = (token: string): boolean => {
|
|||||||
return payload.role === 'guest';
|
return payload.role === 'guest';
|
||||||
};
|
};
|
||||||
|
|
||||||
const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; coreVersion: string | null; apiVersion: string | null; username: string | null } => {
|
const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; coreVersion: string | null; apiVersion: string | null; username: string | null; webuiTitle: string | null; webuiDescription: string | null } => {
|
||||||
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
||||||
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
||||||
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
||||||
|
const webuiTitle = localStorage.getItem('LIGHTRAG-WEBUI-TITLE');
|
||||||
|
const webuiDescription = localStorage.getItem('LIGHTRAG-WEBUI-DESCRIPTION');
|
||||||
const username = token ? getUsernameFromToken(token) : null;
|
const username = token ? getUsernameFromToken(token) : null;
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
@@ -120,6 +133,8 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; core
|
|||||||
coreVersion: coreVersion,
|
coreVersion: coreVersion,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
username: null,
|
username: null,
|
||||||
|
webuiTitle: webuiTitle,
|
||||||
|
webuiDescription: webuiDescription,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +144,8 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean; core
|
|||||||
coreVersion: coreVersion,
|
coreVersion: coreVersion,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
username: username,
|
username: username,
|
||||||
|
webuiTitle: webuiTitle,
|
||||||
|
webuiDescription: webuiDescription,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,8 +159,10 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
coreVersion: initialState.coreVersion,
|
coreVersion: initialState.coreVersion,
|
||||||
apiVersion: initialState.apiVersion,
|
apiVersion: initialState.apiVersion,
|
||||||
username: initialState.username,
|
username: initialState.username,
|
||||||
|
webuiTitle: initialState.webuiTitle,
|
||||||
|
webuiDescription: initialState.webuiDescription,
|
||||||
|
|
||||||
login: (token, isGuest = false, coreVersion = null, apiVersion = null) => {
|
login: (token, isGuest = false, coreVersion = null, apiVersion = null, webuiTitle = null, webuiDescription = null) => {
|
||||||
localStorage.setItem('LIGHTRAG-API-TOKEN', token);
|
localStorage.setItem('LIGHTRAG-API-TOKEN', token);
|
||||||
|
|
||||||
if (coreVersion) {
|
if (coreVersion) {
|
||||||
@@ -152,6 +171,12 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
if (apiVersion) {
|
if (apiVersion) {
|
||||||
localStorage.setItem('LIGHTRAG-API-VERSION', apiVersion);
|
localStorage.setItem('LIGHTRAG-API-VERSION', apiVersion);
|
||||||
}
|
}
|
||||||
|
if (webuiTitle) {
|
||||||
|
localStorage.setItem('LIGHTRAG-WEBUI-TITLE', webuiTitle);
|
||||||
|
}
|
||||||
|
if (webuiDescription) {
|
||||||
|
localStorage.setItem('LIGHTRAG-WEBUI-DESCRIPTION', webuiDescription);
|
||||||
|
}
|
||||||
|
|
||||||
const username = getUsernameFromToken(token);
|
const username = getUsernameFromToken(token);
|
||||||
set({
|
set({
|
||||||
@@ -160,6 +185,8 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
username: username,
|
username: username,
|
||||||
coreVersion: coreVersion,
|
coreVersion: coreVersion,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
|
webuiTitle: webuiTitle,
|
||||||
|
webuiDescription: webuiDescription,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -168,6 +195,8 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
|
|
||||||
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
const coreVersion = localStorage.getItem('LIGHTRAG-CORE-VERSION');
|
||||||
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
const apiVersion = localStorage.getItem('LIGHTRAG-API-VERSION');
|
||||||
|
const webuiTitle = localStorage.getItem('LIGHTRAG-WEBUI-TITLE');
|
||||||
|
const webuiDescription = localStorage.getItem('LIGHTRAG-WEBUI-DESCRIPTION');
|
||||||
|
|
||||||
set({
|
set({
|
||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
@@ -175,6 +204,8 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
username: null,
|
username: null,
|
||||||
coreVersion: coreVersion,
|
coreVersion: coreVersion,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
|
webuiTitle: webuiTitle,
|
||||||
|
webuiDescription: webuiDescription,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -192,6 +223,27 @@ export const useAuthStore = create<AuthState>(set => {
|
|||||||
coreVersion: coreVersion,
|
coreVersion: coreVersion,
|
||||||
apiVersion: apiVersion
|
apiVersion: apiVersion
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCustomTitle: (webuiTitle, webuiDescription) => {
|
||||||
|
// Update localStorage
|
||||||
|
if (webuiTitle) {
|
||||||
|
localStorage.setItem('LIGHTRAG-WEBUI-TITLE', webuiTitle);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('LIGHTRAG-WEBUI-TITLE');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (webuiDescription) {
|
||||||
|
localStorage.setItem('LIGHTRAG-WEBUI-DESCRIPTION', webuiDescription);
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('LIGHTRAG-WEBUI-DESCRIPTION');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
set({
|
||||||
|
webuiTitle: webuiTitle,
|
||||||
|
webuiDescription: webuiDescription
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user