Skip to content

Commit 8d77a48

Browse files
committed
feat: обновлен сайдбар
1 parent c5248cb commit 8d77a48

5 files changed

Lines changed: 101 additions & 77 deletions

File tree

frontend/public/locales/en/sidebar.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
{
22
"dashboard": "Dashboard",
33
"scheduler": "Scheduler",
4-
"graphStore": "Graph Store",
54
"apiKeys": "API Keys",
65
"proxy": "Proxy",
7-
"changelog": "Version History",
86
"bots": "Bots",
97
"admin": "Administration",
108
"servers": "Servers",
@@ -24,8 +22,9 @@
2422
"cancel": "Cancel",
2523
"confirm": "Log out"
2624
},
27-
"whatsNew": "What's New?",
2825
"openMenu": "Open Menu",
26+
"whatsNew": "What's New?",
27+
"askQuestion": "Ask Question",
2928
"theme": {
3029
"label": "Theme",
3130
"light": "Light",

frontend/public/locales/ru/sidebar.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
{
22
"dashboard": "Дашборд",
33
"scheduler": "Планировщик",
4-
"graphStore": "Магазин графов",
54
"apiKeys": "API Ключи",
65
"proxy": "Прокси",
7-
"changelog": "История версий",
86
"bots": "Боты",
97
"admin": "Администрирование",
108
"servers": "Серверы",
@@ -24,8 +22,9 @@
2422
"cancel": "Отмена",
2523
"confirm": "Выйти"
2624
},
27-
"whatsNew": "Что нового?",
2825
"openMenu": "Открыть меню",
26+
"whatsNew": "Что нового?",
27+
"askQuestion": "Задать вопрос",
2928
"theme": {
3029
"label": "Тема",
3130
"light": "Светлая",
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { ExternalLink } from 'lucide-react';
3+
import { cn } from '@/lib/utils';
4+
5+
export default function TelegramWidget({ isCollapsed }) {
6+
const [membersCount, setMembersCount] = useState(null);
7+
const [isLoading, setIsLoading] = useState(true);
8+
9+
useEffect(() => {
10+
async function fetchMembers() {
11+
try {
12+
const response = await fetch('https://api.telegram.org/bot8062196096:AAH1bLASmX8oJFiTmPx0vB2t0oN6K_3pNjk/getChat?chat_id=@blockmineJs');
13+
if (response.ok) {
14+
const data = await response.json();
15+
if (data.ok && data.result) {
16+
setMembersCount(data.result.member_count || data.result.members_count);
17+
}
18+
}
19+
} catch (error) {
20+
console.error('Failed to fetch Telegram members:', error);
21+
} finally {
22+
setIsLoading(false);
23+
}
24+
}
25+
26+
fetchMembers();
27+
}, []);
28+
29+
return (
30+
<a
31+
href="https://t.me/blockmineJs"
32+
target="_blank"
33+
rel="noopener noreferrer"
34+
title={isCollapsed ? 'Telegram' : undefined}
35+
className={cn(
36+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors duration-200 bg-muted/50 hover:bg-muted text-muted-foreground hover:text-foreground",
37+
isCollapsed && "mx-auto h-9 w-9 justify-center px-0"
38+
)}
39+
>
40+
<svg
41+
viewBox="0 0 24 24"
42+
className="h-4 w-4 flex-shrink-0"
43+
fill="currentColor"
44+
>
45+
<path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/>
46+
</svg>
47+
<span className={cn("flex-1 truncate", isCollapsed && "hidden")}>Telegram</span>
48+
{isLoading ? (
49+
<span className="text-xs text-muted-foreground hidden sm:inline">...</span>
50+
) : membersCount ? (
51+
<span className="text-xs bg-primary/10 text-primary px-2 py-0.5 rounded-full font-medium hidden sm:inline">
52+
{membersCount.toLocaleString()}
53+
</span>
54+
) : (
55+
<ExternalLink className="h-3 w-3 hidden sm:block" />
56+
)}
57+
</a>
58+
);
59+
}

frontend/src/pages/AdminPage.jsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,34 @@ import React from 'react';
44
import { useTranslation } from 'react-i18next';
55
import { CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
66
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
7-
import { ShieldCheck } from 'lucide-react';
7+
import { ShieldCheck, Key } from 'lucide-react';
88
import PanelUsersManager from '@/components/admin/PanelUsersManager';
99
import PanelRolesManager from '@/components/admin/PanelRolesManager';
1010
import GlobalSettingsManager from '@/components/admin/GlobalSettingsManager';
11+
import { Button } from '@/components/ui/button';
12+
import { useNavigate } from 'react-router-dom';
1113

1214
export default function AdminPage() {
1315
const { t } = useTranslation('admin');
16+
const navigate = useNavigate();
17+
1418
return (
1519
<div className="h-full flex flex-col p-4">
1620
<CardHeader className="px-0">
17-
<div className="flex items-center gap-3">
18-
<ShieldCheck className="w-8 h-8 text-primary" />
19-
<div>
20-
<CardTitle>{t('title')}</CardTitle>
21-
<CardDescription>
22-
{t('description')}
23-
</CardDescription>
21+
<div className="flex items-center justify-between gap-3">
22+
<div className="flex items-center gap-3">
23+
<ShieldCheck className="w-8 h-8 text-primary" />
24+
<div>
25+
<CardTitle>{t('title')}</CardTitle>
26+
<CardDescription>
27+
{t('description')}
28+
</CardDescription>
29+
</div>
2430
</div>
31+
<Button variant="outline" onClick={() => navigate('/api-keys')}>
32+
<Key className="h-4 w-4 mr-2" />
33+
API Keys
34+
</Button>
2535
</div>
2636
</CardHeader>
2737

frontend/src/pages/Layout.jsx

Lines changed: 20 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ import {
2727
ChevronsRight,
2828
Server,
2929
ShieldCheck,
30-
Store,
31-
Lightbulb,
3230
Key,
33-
MessageSquarePlus,
34-
Globe
31+
Globe,
32+
Send
3533
} from 'lucide-react';
3634
import ImportBotDialog from '@/components/ImportBotDialog';
3735
import { cn } from "@/lib/utils";
@@ -63,7 +61,7 @@ import {
6361
useSortable,
6462
} from '@dnd-kit/sortable';
6563
import { CSS } from '@dnd-kit/utilities';
66-
import ContributeDialog from '@/components/ContributeDialog';
64+
import TelegramWidget from '@/components/TelegramWidget';
6765
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
6866

6967
const SIDEBAR_TRANSITION = 'duration-300 ease-out';
@@ -232,24 +230,6 @@ const SidebarNav = ({ onLinkClick, isCollapsed, isSheetOpen }) => {
232230
const navigate = useNavigate();
233231
const { toast } = useToast();
234232
const [isDragging, setIsDragging] = useState(false);
235-
const [randomFeature, setRandomFeature] = useState({ text: t('contribute.improve'), icon: <Lightbulb className="h-4 w-4 flex-shrink-0" /> });
236-
const [isContributeModalOpen, setIsContributeModalOpen] = useState(false);
237-
238-
useEffect(() => {
239-
const texts = [
240-
t('contribute.suggest'),
241-
t('contribute.change'),
242-
t('contribute.question'),
243-
t('contribute.improve')
244-
];
245-
const icons = [
246-
<Lightbulb key="lightbulb" className="h-4 w-4 flex-shrink-0" />,
247-
<MessageSquarePlus key="msg" className="h-4 w-4 flex-shrink-0" />
248-
];
249-
const randomText = texts[Math.floor(Math.random() * texts.length)];
250-
const randomIcon = icons[Math.floor(Math.random() * icons.length)];
251-
setRandomFeature({ text: randomText, icon: randomIcon });
252-
}, [t]);
253233

254234
const activeBotId = location.pathname.match(/\/bots\/(\d+)/)?.[1];
255235

@@ -416,52 +396,13 @@ const SidebarNav = ({ onLinkClick, isCollapsed, isSheetOpen }) => {
416396
</NavLink>
417397
)}
418398

419-
<NavLink to="/graph-store" onClick={onLinkClick} className={navLinkClasses}>
420-
{iconAndText(<Store className="h-4 w-4 flex-shrink-0" />, t('graphStore'))}
421-
</NavLink>
422-
423-
<NavLink to="/api-keys" onClick={onLinkClick} className={navLinkClasses}>
424-
{iconAndText(<Key className="h-4 w-4 flex-shrink-0" />, t('apiKeys'))}
425-
</NavLink>
426-
427399
{hasPermission('bot:update') && (
428400
<NavLink to="/proxy-config" onClick={onLinkClick} className={navLinkClasses}>
429401
{iconAndText(<Globe className="h-4 w-4 flex-shrink-0" />, t('proxy'))}
430402
</NavLink>
431403
)}
432404

433-
<Dialog open={isContributeModalOpen} onOpenChange={setIsContributeModalOpen}>
434-
<DialogTrigger asChild>
435-
<Button
436-
variant="ghost"
437-
className={cn(
438-
"w-full justify-start flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors duration-200 text-muted-foreground hover:text-foreground hover:bg-muted/50",
439-
isCollapsed && "mx-auto h-9 w-9 justify-center gap-0 px-0"
440-
)}
441-
onClick={() => {
442-
setIsContributeModalOpen(true);
443-
if (typeof onLinkClick === 'function') onLinkClick();
444-
}}
445-
>
446-
{iconAndText(randomFeature.icon, randomFeature.text)}
447-
</Button>
448-
</DialogTrigger>
449-
<ContributeDialog onClose={() => setIsContributeModalOpen(false)} />
450-
</Dialog>
451-
452-
<Button
453-
variant="ghost"
454-
className={cn(
455-
"w-full justify-start flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors duration-200 text-muted-foreground hover:text-foreground hover:bg-accent",
456-
isCollapsed && "mx-auto h-9 w-9 justify-center gap-0 px-0"
457-
)}
458-
onClick={async () => {
459-
onLinkClick();
460-
await useAppStore.getState().openChangelogDialog();
461-
}}
462-
>
463-
{iconAndText(<Github className="h-4 w-4 flex-shrink-0" />, t('changelog'))}
464-
</Button>
405+
<TelegramWidget isCollapsed={isCollapsed} />
465406

466407
<Separator className="my-2" />
467408

@@ -703,6 +644,22 @@ export default function Layout() {
703644
<span className={sidebarLabelClasses(isCollapsed)}>{t('admin')}</span>
704645
</NavLink>
705646
)}
647+
{hasPermission('api_key:list') && (
648+
<NavLink
649+
to="/api-keys"
650+
onClick={() => setIsSheetOpen(false)}
651+
className={({ isActive }) => cn(
652+
"relative flex items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium transition-[background-color,color,gap,padding] " + SIDEBAR_TRANSITION,
653+
isActive
654+
? "bg-primary/10 text-primary before:absolute before:left-0 before:top-1 before:bottom-1 before:w-0.5 before:bg-primary before:rounded-r"
655+
: "text-muted-foreground hover:text-foreground hover:bg-accent",
656+
isCollapsed && "mx-auto h-9 w-9 justify-center gap-0 px-0"
657+
)}
658+
>
659+
<Key className="h-4 w-4 flex-shrink-0" />
660+
<span className={sidebarLabelClasses(isCollapsed)}>{t('apiKeys')}</span>
661+
</NavLink>
662+
)}
706663
{hasPermission('server:list') && (
707664
<NavLink
708665
to="/servers"

0 commit comments

Comments
 (0)