Skip to content

Commit 46472cf

Browse files
authored
🐛 Administrator can go to any configuration page #1346Hs/1028 bugfix3
2 parents ae03a11 + d073cb3 commit 46472cf

File tree

5 files changed

+160
-35
lines changed

5 files changed

+160
-35
lines changed

frontend/app/[locale]/chat/components/chatLeftSidebar.tsx

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
ChevronLeft,
1010
ChevronRight,
1111
User,
12+
Database,
13+
Box,
14+
Bot,
1215
} from "lucide-react";
1316

1417
import { Button } from "@/components/ui/button";
@@ -37,7 +40,8 @@ import { StaticScrollArea } from "@/components/ui/scrollArea";
3740
import { USER_ROLES } from "@/const/modelConfig";
3841
import { useConfig } from "@/hooks/useConfig";
3942
import { useResponsiveTextSize } from "@/hooks/useResponsiveTextSize";
40-
import { Spin, Tag, ConfigProvider } from "antd";
43+
import { Spin, Tag, ConfigProvider, Dropdown, Menu } from "antd";
44+
import type { MenuProps } from "antd";
4145
import { getRoleColor } from "@/lib/auth";
4246
import { useAuth } from "@/hooks/useAuth";
4347
import { extractColorsFromUri } from "@/lib/avatar";
@@ -120,6 +124,7 @@ export function ChatSidebar({
120124
onRename,
121125
onDelete,
122126
onSettingsClick,
127+
settingsMenuItems,
123128
onDropdownOpenChange,
124129
onToggleSidebar,
125130
expanded,
@@ -237,6 +242,100 @@ export function ChatSidebar({
237242
);
238243
};
239244

245+
// Get icon for menu item based on key
246+
const getMenuIcon = (key: string) => {
247+
switch (key) {
248+
case "models":
249+
return <Box className="h-4 w-4" />;
250+
case "knowledges":
251+
return <Database className="h-4 w-4" />;
252+
case "agents":
253+
return <Bot className="h-4 w-4" />;
254+
}
255+
};
256+
257+
// Render settings button (with dropdown for admin, plain button for regular users)
258+
const renderSettingsButton = (isCollapsed: boolean = false) => {
259+
const buttonContent = (
260+
<Button
261+
variant="ghost"
262+
size="icon"
263+
className={isCollapsed ? "h-10 w-10 rounded-full hover:bg-slate-100" : "size-10 rounded-full hover:bg-slate-100"}
264+
onClick={settingsMenuItems ? undefined : onSettingsClick}
265+
>
266+
<Settings className={isCollapsed ? "h-6 w-6" : "size-5"} />
267+
</Button>
268+
);
269+
270+
// If settingsMenuItems is provided, show dropdown with icons
271+
if (settingsMenuItems && settingsMenuItems.length > 0) {
272+
const menuProps: MenuProps = {
273+
items: settingsMenuItems.map((item, index) => ({
274+
key: item.key,
275+
label: (
276+
<div className="flex items-center gap-3 py-1">
277+
<span className="text-gray-600">{getMenuIcon(item.key)}</span>
278+
<span className="text-sm font-medium">{item.label}</span>
279+
</div>
280+
),
281+
onClick: item.onClick,
282+
style: {
283+
padding: "8px 16px",
284+
},
285+
})),
286+
style: {
287+
minWidth: "240px",
288+
borderRadius: "8px",
289+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
290+
},
291+
};
292+
293+
return (
294+
<TooltipProvider>
295+
<Tooltip>
296+
<TooltipTrigger asChild>
297+
<ConfigProvider
298+
getPopupContainer={() => document.body}
299+
theme={{
300+
components: {
301+
Dropdown: {
302+
paddingBlock: 4,
303+
},
304+
},
305+
}}
306+
>
307+
<Dropdown menu={menuProps} placement="topRight" trigger={["click"]}>
308+
<div className={isCollapsed ? "flex justify-center" : ""}>
309+
{buttonContent}
310+
</div>
311+
</Dropdown>
312+
</ConfigProvider>
313+
</TooltipTrigger>
314+
<TooltipContent side={isCollapsed ? "right" : "top"}>
315+
{t("chatLeftSidebar.settings")}
316+
</TooltipContent>
317+
</Tooltip>
318+
</TooltipProvider>
319+
);
320+
}
321+
322+
// Otherwise, show plain button for regular users (shouldn't reach here anymore)
323+
return (
324+
<TooltipProvider>
325+
<Tooltip>
326+
<TooltipTrigger asChild>
327+
<div className={isCollapsed ? "flex justify-center" : ""}>
328+
{buttonContent}
329+
</div>
330+
</TooltipTrigger>
331+
<TooltipContent side={isCollapsed ? "right" : "top"}>
332+
{t("chatLeftSidebar.settings")}
333+
</TooltipContent>
334+
</Tooltip>
335+
</TooltipProvider>
336+
);
337+
};
338+
240339
// Render dialog list items
241340
const renderDialogList = (dialogs: ConversationListItem[], title: string) => {
242341
if (dialogs.length === 0) return null;
@@ -461,25 +560,7 @@ export function ChatSidebar({
461560
) : null}
462561

463562
{/* Settings button */}
464-
<TooltipProvider>
465-
<Tooltip>
466-
<TooltipTrigger asChild>
467-
<div className="flex justify-center">
468-
<Button
469-
variant="ghost"
470-
size="icon"
471-
className="h-10 w-10 rounded-full hover:bg-slate-100"
472-
onClick={onSettingsClick}
473-
>
474-
<Settings className="h-6 w-6" />
475-
</Button>
476-
</div>
477-
</TooltipTrigger>
478-
<TooltipContent side="right">
479-
{t("chatLeftSidebar.settings")}
480-
</TooltipContent>
481-
</Tooltip>
482-
</TooltipProvider>
563+
{renderSettingsButton(true)}
483564
</>
484565
);
485566
};
@@ -628,14 +709,7 @@ export function ChatSidebar({
628709
</div>
629710
</ConfigProvider>
630711
) : null}
631-
<Button
632-
variant="ghost"
633-
size="icon"
634-
className="size-10 rounded-full hover:bg-slate-100"
635-
onClick={onSettingsClick}
636-
>
637-
<Settings className="size-5" />
638-
</Button>
712+
{renderSettingsButton(false)}
639713
</div>
640714
</div>
641715
) : (

frontend/app/[locale]/chat/internal/chatInterface.tsx

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,48 @@ export function ChatInterface() {
15331533
};
15341534
}, []);
15351535

1536+
// Handle settings click - not used when menu items are provided
1537+
const handleSettingsClick = () => {
1538+
// This function is kept for compatibility but not used
1539+
// Both admin and regular users now use dropdown menus
1540+
};
1541+
1542+
// Settings menu items based on user role
1543+
const settingsMenuItems = user?.role === "admin" ? [
1544+
// Admin has three options
1545+
{
1546+
key: "models",
1547+
label: t("chatLeftSidebar.settingsMenu.modelConfig"),
1548+
onClick: () => {
1549+
localStorage.setItem("show_page", "1");
1550+
router.push("/setup/models");
1551+
},
1552+
},
1553+
{
1554+
key: "knowledges",
1555+
label: t("chatLeftSidebar.settingsMenu.knowledgeConfig"),
1556+
onClick: () => {
1557+
router.push("/setup/knowledges");
1558+
},
1559+
},
1560+
{
1561+
key: "agents",
1562+
label: t("chatLeftSidebar.settingsMenu.agentConfig"),
1563+
onClick: () => {
1564+
router.push("/setup/agents");
1565+
},
1566+
},
1567+
] : [
1568+
// Regular user only has knowledge base configuration
1569+
{
1570+
key: "knowledges",
1571+
label: t("chatLeftSidebar.settingsMenu.knowledgeConfig"),
1572+
onClick: () => {
1573+
router.push("/setup/knowledges");
1574+
},
1575+
},
1576+
];
1577+
15361578
return (
15371579
<>
15381580
<div className="flex h-screen">
@@ -1546,13 +1588,8 @@ export function ChatInterface() {
15461588
onDialogClick={handleDialogClick}
15471589
onRename={handleConversationRename}
15481590
onDelete={handleConversationDeleteClick}
1549-
onSettingsClick={() => {
1550-
localStorage.setItem(
1551-
"show_page",
1552-
user?.role === "admin" ? "1" : "2"
1553-
);
1554-
router.push("/setup");
1555-
}}
1591+
onSettingsClick={handleSettingsClick}
1592+
settingsMenuItems={settingsMenuItems}
15561593
onDropdownOpenChange={(open: boolean, id: string | null) =>
15571594
setOpenDropdownId(open ? id : null)
15581595
}

frontend/public/locales/en/common.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
"chatLeftSidebar.noHistory": "No conversation history",
101101
"chatLeftSidebar.expandSidebar": "Expand Sidebar",
102102
"chatLeftSidebar.settings": "Settings",
103+
"chatLeftSidebar.settingsMenu.modelConfig": "Application & Model Configuration",
104+
"chatLeftSidebar.settingsMenu.knowledgeConfig": "Knowledge Base Configuration",
105+
"chatLeftSidebar.settingsMenu.agentConfig": "Agent Configuration",
103106
"chatLeftSidebar.confirmDeletionTitle": "Delete Conversation",
104107
"chatLeftSidebar.confirmDeletionDescription": "Are you sure you want to delete this conversation? This action cannot be undone.",
105108
"chatLeftSidebar.cancel": "Cancel",

frontend/public/locales/zh/common.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
"chatLeftSidebar.noHistory": "无历史对话",
101101
"chatLeftSidebar.expandSidebar": "展开边栏",
102102
"chatLeftSidebar.settings": "设置",
103+
"chatLeftSidebar.settingsMenu.modelConfig": "应用与模型配置",
104+
"chatLeftSidebar.settingsMenu.knowledgeConfig": "知识库配置",
105+
"chatLeftSidebar.settingsMenu.agentConfig": "智能体配置",
103106
"chatLeftSidebar.confirmDeletionTitle": "删除对话",
104107
"chatLeftSidebar.confirmDeletionDescription": "确定要删除这个对话吗?此操作无法撤销。",
105108
"chatLeftSidebar.cancel": "取消",

frontend/types/chat.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ export interface FilePreview {
249249
previewUrl?: string;
250250
}
251251

252+
// Settings menu item type for admin users
253+
export interface SettingsMenuItem {
254+
key: string;
255+
label: string;
256+
onClick: () => void;
257+
}
258+
252259
// Chat sidebar props type
253260
export interface ChatSidebarProps {
254261
conversationList: ConversationListItem[];
@@ -261,6 +268,7 @@ export interface ChatSidebarProps {
261268
onRename: (dialogId: number, title: string) => void;
262269
onDelete: (dialogId: number) => void;
263270
onSettingsClick: () => void;
271+
settingsMenuItems?: SettingsMenuItem[];
264272
onDropdownOpenChange: (open: boolean, id: string | null) => void;
265273
onToggleSidebar: () => void;
266274
expanded: boolean;

0 commit comments

Comments
 (0)