mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-08-12 04:59:01 +08:00
### What problem does this PR solve? Feat: Add a language switch drop-down box to the top navigation bar #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
942b94fc3c
commit
de166d0ff2
@ -1,39 +1,87 @@
|
||||
import { useTheme } from '@/components/theme-provider';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Container } from '@/components/ui/container';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { Segmented, SegmentedValue } from '@/components/ui/segmented';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { LanguageList, LanguageMap } from '@/constants/common';
|
||||
import { useChangeLanguage } from '@/hooks/logic-hooks';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useNavigateWithFromState } from '@/hooks/route-hook';
|
||||
import { useFetchUserInfo, useListTenant } from '@/hooks/user-setting-hooks';
|
||||
import { TenantRole } from '@/pages/user-setting/constants';
|
||||
import { Routes } from '@/routes';
|
||||
import { camelCase } from 'lodash';
|
||||
import {
|
||||
ChevronDown,
|
||||
CircleHelp,
|
||||
Cpu,
|
||||
File,
|
||||
Github,
|
||||
House,
|
||||
Library,
|
||||
MessageSquareText,
|
||||
Moon,
|
||||
Search,
|
||||
Zap,
|
||||
Sun,
|
||||
} from 'lucide-react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'umi';
|
||||
|
||||
const handleDocHelpCLick = () => {
|
||||
window.open('https://ragflow.io/docs/dev/category/guides', 'target');
|
||||
};
|
||||
|
||||
export function Header() {
|
||||
const { t } = useTranslate('header');
|
||||
const { t } = useTranslation();
|
||||
const { pathname } = useLocation();
|
||||
const navigate = useNavigateWithFromState();
|
||||
const { navigateToProfile } = useNavigatePage();
|
||||
|
||||
const changeLanguage = useChangeLanguage();
|
||||
const { setTheme, theme } = useTheme();
|
||||
|
||||
const {
|
||||
data: { language = 'English' },
|
||||
} = useFetchUserInfo();
|
||||
|
||||
const handleItemClick = (key: string) => () => {
|
||||
changeLanguage(key);
|
||||
};
|
||||
|
||||
const { data } = useListTenant();
|
||||
|
||||
const showBell = useMemo(() => {
|
||||
return data.some((x) => x.role === TenantRole.Invite);
|
||||
}, [data]);
|
||||
|
||||
const items = LanguageList.map((x) => ({
|
||||
key: x,
|
||||
label: <span>{LanguageMap[x as keyof typeof LanguageMap]}</span>,
|
||||
}));
|
||||
|
||||
const onThemeClick = React.useCallback(() => {
|
||||
setTheme(theme === 'dark' ? 'light' : 'dark');
|
||||
}, [setTheme, theme]);
|
||||
|
||||
const handleBellClick = useCallback(() => {
|
||||
navigate('/user-setting/team');
|
||||
}, [navigate]);
|
||||
|
||||
const tagsData = useMemo(
|
||||
() => [
|
||||
{ path: Routes.Home, name: t('home'), icon: House },
|
||||
{ path: Routes.Datasets, name: t('knowledgeBase'), icon: Library },
|
||||
{ path: Routes.Chats, name: t('chat'), icon: MessageSquareText },
|
||||
{ path: Routes.Searches, name: t('search'), icon: Search },
|
||||
{ path: Routes.Agents, name: t('flow'), icon: Cpu },
|
||||
{ path: Routes.Files, name: t('fileManager'), icon: File },
|
||||
{ path: Routes.Home, name: t('header.home'), icon: House },
|
||||
{ path: Routes.Datasets, name: t('header.knowledgeBase'), icon: Library },
|
||||
{ path: Routes.Chats, name: t('header.chat'), icon: MessageSquareText },
|
||||
{ path: Routes.Searches, name: t('header.search'), icon: Search },
|
||||
{ path: Routes.Agents, name: t('header.flow'), icon: Cpu },
|
||||
{ path: Routes.Files, name: t('header.fileManager'), icon: File },
|
||||
],
|
||||
[t],
|
||||
);
|
||||
@ -87,30 +135,37 @@ export function Header() {
|
||||
value={currentPath}
|
||||
onChange={handleChange}
|
||||
></Segmented>
|
||||
<div className="flex items-center gap-4">
|
||||
<Container className="bg-colors-background-inverse-standard hidden xl:flex">
|
||||
V 0.13.0
|
||||
<Button variant="secondary" className="size-8">
|
||||
<ChevronDown />
|
||||
<div className="flex items-center gap-5 text-text-badge">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<div className="flex items-center gap-1">
|
||||
{t(`common.${camelCase(language)}`)}
|
||||
<ChevronDown className="size-4" />
|
||||
</div>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
{items.map((x) => (
|
||||
<DropdownMenuItem key={x.key} onClick={handleItemClick(x.key)}>
|
||||
{x.label}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button variant={'ghost'} onClick={handleDocHelpCLick}>
|
||||
<CircleHelp />
|
||||
</Button>
|
||||
</Container>
|
||||
<Container className="px-3 py-2 bg-colors-background-inverse-standard">
|
||||
<Avatar
|
||||
className="w-[30px] h-[30px] cursor-pointer"
|
||||
onClick={navigateToProfile}
|
||||
>
|
||||
<Button variant={'ghost'} onClick={onThemeClick}>
|
||||
{theme === 'light' ? <Sun /> : <Moon />}
|
||||
</Button>
|
||||
<div className="relative">
|
||||
<Avatar className="size-8 cursor-pointer" onClick={navigateToProfile}>
|
||||
<AvatarImage src="https://github.com/shadcn.png" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<span className="max-w-14 truncate"> yifanwu92@gmail.com</span>
|
||||
<Button
|
||||
variant="destructive"
|
||||
className="py-[2px] px-[8px] h-[23px] rounded-[4px]"
|
||||
>
|
||||
<Zap />
|
||||
<Badge className="h-5 w-8 absolute font-normal p-0 justify-center -right-8 -top-2 text-text-title-invert bg-gradient-to-l from-[#42D7E7] to-[#478AF5]">
|
||||
Pro
|
||||
</Button>
|
||||
</Container>
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
@ -164,8 +164,7 @@ const KnowledgeFile = () => {
|
||||
text: t(`runningStatus${value}`),
|
||||
value: value,
|
||||
})),
|
||||
onFilter: (value: string | number | boolean, record: IDocumentInfo) =>
|
||||
record.run === value,
|
||||
onFilter: (value, record: IDocumentInfo) => record.run === value,
|
||||
render: (text, record) => {
|
||||
return <ParsingStatusCell record={record}></ParsingStatusCell>;
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user