Skip to content

Commit 9ca150a

Browse files
authored
Merge pull request #2163 from ModelEngine-Group/xyc/frontend_refactor_2
2 parents 5b7f2d8 + 53ad0ff commit 9ca150a

1 file changed

Lines changed: 110 additions & 120 deletions

File tree

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

Lines changed: 110 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ import { useState, useEffect, useRef, useCallback } from "react";
22
import { useTranslation } from "react-i18next";
33
import { ExternalLink, Database, X, Server } from "lucide-react";
44

5-
import { StaticScrollArea } from "@/components/ui/scrollArea";
65
import { ImageItem, ChatRightPanelProps, SearchResult } from "@/types/chat";
7-
import { API_ENDPOINTS } from "@/services/api";
86
import { formatDate, formatUrl } from "@/lib/utils";
97
import { convertImageUrlToApiUrl, extractObjectNameFromUrl, storageService } from "@/services/storageService";
10-
import { message, Button, Tabs } from "antd";
8+
import { message, Button } from "antd";
119
import log from "@/lib/logger";
1210

1311

@@ -26,6 +24,7 @@ export function ChatRightPanel({
2624
const [processedImages, setProcessedImages] = useState<string[]>([]);
2725
const [viewingImage, setViewingImage] = useState<string | null>(null);
2826
const [imageData, setImageData] = useState<Record<string, ImageItem>>({});
27+
const [activeTab, setActiveTab] = useState<string>("sources");
2928

3029
// Reference to prevent duplicate loading
3130
const loadingImages = useRef<Set<string>>(new Set());
@@ -532,131 +531,122 @@ export function ChatRightPanel({
532531
)}
533532
</div>
534533

535-
<Tabs
536-
defaultActiveKey="sources"
537-
className="flex-1 flex flex-col overflow-hidden"
538-
style={{ maxWidth: "400px" }}
539-
items={[
540-
{
541-
key: "sources",
542-
label: (
543-
<span className="flex items-center justify-center px-3 py-1.5 text-sm font-medium">
544-
{t("chatRightPanel.sources")}
545-
{searchResults.length > 0 && (
546-
<span className="ml-1 bg-gray-200 inline-flex items-center justify-center rounded px-1 text-xs font-medium min-w-[20px] h-[18px]">
547-
{searchResults.length}
548-
</span>
534+
<div className="flex-1 flex flex-col" style={{ maxWidth: "400px", height: "100%" }}>
535+
{/* Tab Headers */}
536+
<div className="flex border-b bg-gray-50">
537+
<Button
538+
type={activeTab === "sources" ? "primary" : "text"}
539+
className={`flex-1 px-3 py-2 text-sm font-medium transition-colors rounded-none border-none ${
540+
activeTab === "sources"
541+
? "bg-white text-gray-900 border-b-2 border-blue-500"
542+
: "text-gray-500 hover:text-gray-700 hover:bg-gray-100"
543+
}`}
544+
onClick={() => setActiveTab("sources")}
545+
>
546+
<span className="flex items-center justify-center">
547+
{t("chatRightPanel.sources")}
548+
{searchResults.length > 0 && (
549+
<span className="ml-1 bg-gray-200 inline-flex items-center justify-center rounded px-1 text-xs font-medium min-w-[20px] h-[18px]">
550+
{searchResults.length}
551+
</span>
552+
)}
553+
</span>
554+
</Button>
555+
<Button
556+
type={activeTab === "images" ? "primary" : "text"}
557+
className={`flex-1 px-3 py-2 text-sm font-medium transition-colors rounded-none border-none ${
558+
activeTab === "images"
559+
? "bg-white text-gray-900 border-b-2 border-blue-500"
560+
: "text-gray-500 hover:text-gray-700 hover:bg-gray-100"
561+
}`}
562+
onClick={() => setActiveTab("images")}
563+
>
564+
<span className="flex items-center justify-center">
565+
{t("chatRightPanel.images")}
566+
{processedImages.length > 0 && (
567+
<span className="ml-1 bg-gray-200 inline-flex items-center justify-center rounded px-1 text-xs font-medium min-w-[20px] h-[18px]">
568+
{processedImages.length}
569+
</span>
570+
)}
571+
</span>
572+
</Button>
573+
</div>
574+
575+
{/* Tab Content */}
576+
<div className="flex-1 overflow-y-auto">
577+
{activeTab === "sources" && (
578+
<div className="p-4" style={{ maxWidth: "400px" }}>
579+
<div className="space-y-2" style={{ maxWidth: "100%" }}>
580+
{searchResults.length > 0 ? (
581+
<>
582+
<div className="space-y-3" style={{ maxWidth: "100%" }}>
583+
{searchResults.map((result, index) => (
584+
<SearchResultItem
585+
key={`result-${index}`}
586+
result={result}
587+
/>
588+
))}
589+
</div>
590+
</>
591+
) : (
592+
<div className="text-center text-gray-500 py-4 text-base">
593+
{t("chatRightPanel.noSearchResults")}
594+
</div>
549595
)}
550-
</span>
551-
),
552-
children: (
553-
<StaticScrollArea
554-
className="flex-1"
555-
style={{ maxWidth: "400px", overflow: "hidden" }}
556-
>
557-
<div
558-
className="p-4"
559-
style={{ maxWidth: "400px", overflow: "hidden" }}
560-
>
561-
<div
562-
className="space-y-2"
563-
style={{ maxWidth: "100%", overflow: "hidden" }}
564-
>
565-
{searchResults.length > 0 ? (
566-
<>
596+
</div>
597+
</div>
598+
)}
599+
600+
{activeTab === "images" && (
601+
<div className="p-4" style={{ maxWidth: "400px" }}>
602+
{processedImages.length > 0 ? (
603+
<>
604+
<div className="grid grid-cols-2 gap-2">
605+
{processedImages
606+
.slice(0, expandedImages ? undefined : maxInitialImages)
607+
.map((imageUrl: string, index: number) => (
567608
<div
568-
className="space-y-3"
569-
style={{ maxWidth: "100%", overflow: "hidden" }}
609+
key={`img-${index}`}
610+
className="relative border rounded-md overflow-hidden hover:border-blue-500 transition-colors cursor-pointer"
611+
onClick={() => handleImageClick(imageUrl)}
570612
>
571-
{searchResults.map((result, index) => (
572-
<SearchResultItem
573-
key={`result-${index}`}
574-
result={result}
575-
/>
576-
))}
613+
{renderImage(imageUrl, index)}
577614
</div>
578-
</>
579-
) : (
580-
<div className="text-center text-gray-500 py-4 text-base">
581-
{t("chatRightPanel.noSearchResults")}
582-
</div>
583-
)}
615+
))}
584616
</div>
585-
</div>
586-
</StaticScrollArea>
587-
),
588-
},
589-
{
590-
key: "images",
591-
label: (
592-
<span className="flex items-center justify-center px-3 py-1.5 text-sm font-medium">
593-
{t("chatRightPanel.images")}
594-
{processedImages.length > 0 && (
595-
<span className="ml-1 bg-gray-200 inline-flex items-center justify-center rounded px-1 text-xs font-medium min-w-[20px] h-[18px]">
596-
{processedImages.length}
597-
</span>
598-
)}
599-
</span>
600-
),
601-
children: (
602-
<StaticScrollArea
603-
className="flex-1"
604-
style={{ maxWidth: "400px", overflow: "hidden" }}
605-
>
606-
<div
607-
className="p-4"
608-
style={{ maxWidth: "400px", overflow: "hidden" }}
609-
>
610-
{processedImages.length > 0 ? (
611-
<>
612-
<div className="grid grid-cols-2 gap-2">
613-
{processedImages
614-
.slice(0, expandedImages ? undefined : maxInitialImages)
615-
.map((imageUrl: string, index: number) => (
616-
<div
617-
key={`img-${index}`}
618-
className="relative border rounded-md overflow-hidden hover:border-blue-500 transition-colors cursor-pointer"
619-
onClick={() => handleImageClick(imageUrl)}
620-
>
621-
{renderImage(imageUrl, index)}
622-
</div>
623-
))}
624-
</div>
625-
626-
{processedImages.length > maxInitialImages && (
627-
<div className="mt-4 text-center">
628-
<Button
629-
type="default"
630-
size="small"
631-
onClick={() => setExpandedImages(!expandedImages)}
632-
className="w-full border border-slate-300 hover:border-slate-400 hover:bg-white transition-colors duration-200"
633-
>
634-
{expandedImages
635-
? t("chatRightPanel.collapseImages")
636-
: t("chatRightPanel.expandImages", {
637-
count: processedImages.length,
638-
})}
639-
</Button>
640-
</div>
641-
)}
642-
</>
643-
) : (
644-
<div className="flex flex-col items-center justify-center p-6 text-center min-h-[200px]">
645-
<Database className="h-12 w-12 text-muted-foreground/40 mb-4" />
646-
<p className="text-lg font-medium mb-2">
647-
{t("chatRightPanel.noImages")}
648-
</p>
649-
<p className="text-sm text-muted-foreground">
650-
{t("chatRightPanel.noAssociatedImages")}
651-
</p>
617+
618+
{processedImages.length > maxInitialImages && (
619+
<div className="mt-4 text-center">
620+
<Button
621+
type="default"
622+
size="small"
623+
onClick={() => setExpandedImages(!expandedImages)}
624+
className="w-full"
625+
>
626+
{expandedImages
627+
? t("chatRightPanel.collapseImages")
628+
: t("chatRightPanel.expandImages", {
629+
count: processedImages.length,
630+
})}
631+
</Button>
652632
</div>
653633
)}
634+
</>
635+
) : (
636+
<div className="flex flex-col items-center justify-center p-6 text-center min-h-[200px]">
637+
<Database className="h-12 w-12 text-muted-foreground/40 mb-4" />
638+
<p className="text-lg font-medium mb-2">
639+
{t("chatRightPanel.noImages")}
640+
</p>
641+
<p className="text-sm text-muted-foreground">
642+
{t("chatRightPanel.noAssociatedImages")}
643+
</p>
654644
</div>
655-
</StaticScrollArea>
656-
),
657-
},
658-
]}
659-
/>
645+
)}
646+
</div>
647+
)}
648+
</div>
649+
</div>
660650
</div>
661651
);
662652
}

0 commit comments

Comments
 (0)