Skip to content

Commit 26b13b1

Browse files
authored
Fixes08 (#38)
* update table size * add slider * close button
1 parent 3377a9a commit 26b13b1

File tree

3 files changed

+118
-66
lines changed

3 files changed

+118
-66
lines changed

dashboard/log-analyzer/src/app/globals.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,32 @@
162162
font-size: inherit !important;
163163
font-weight: normal !important;
164164
}
165+
166+
@keyframes slide-in-from-right {
167+
from {
168+
transform: translateX(100%);
169+
}
170+
to {
171+
transform: translateX(0);
172+
}
173+
}
174+
175+
@keyframes slide-out-to-right {
176+
from {
177+
transform: translateX(0);
178+
}
179+
to {
180+
transform: translateX(100%);
181+
}
182+
}
183+
184+
.animate-slide-in-from-right {
185+
animation: slide-in-from-right 0.3s ease-in-out;
186+
}
187+
188+
.animate-slide-out-to-right {
189+
animation: slide-out-to-right 0.3s ease-in-out;
190+
}
165191

166192
}
167193

dashboard/log-analyzer/src/components/logs/LogDetailPanel.tsx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { LogEntry } from "@/lib/types";
44
import { X } from "lucide-react";
55
import { Button } from "@/components/ui/button";
66
import { cn } from "@/lib/utils";
7+
import { useEffect, useState } from "react";
78

89
interface LogDetailPanelProps {
910
log: LogEntry | null;
@@ -12,6 +13,29 @@ interface LogDetailPanelProps {
1213
}
1314

1415
export function LogDetailPanel({ log, onClose, isOpen }: LogDetailPanelProps) {
16+
const [hasShownBefore, setHasShownBefore] = useState(false);
17+
const [isClosing, setIsClosing] = useState(false);
18+
const [isAnimatingIn, setIsAnimatingIn] = useState(false);
19+
20+
useEffect(() => {
21+
if (isOpen && !hasShownBefore) {
22+
setIsAnimatingIn(true);
23+
setHasShownBefore(true);
24+
setTimeout(() => {
25+
setIsAnimatingIn(false);
26+
}, 300);
27+
}
28+
}, [isOpen, hasShownBefore]);
29+
30+
const handleClose = () => {
31+
setIsClosing(true);
32+
setTimeout(() => {
33+
setIsClosing(false);
34+
setHasShownBefore(false);
35+
onClose();
36+
}, 300);
37+
};
38+
1539
if (!log) return null;
1640

1741
const formatDate = (timestamp: string) => {
@@ -32,27 +56,30 @@ export function LogDetailPanel({ log, onClose, isOpen }: LogDetailPanelProps) {
3256

3357
return (
3458
<div className={cn(
35-
"fixed top-0 right-0 h-screen w-[600px] bg-[--background-secondary] transform transition-transform duration-300 ease-in-out z-50",
36-
isOpen ? "translate-x-0" : "translate-x-full"
59+
"fixed top-0 right-0 h-screen w-[600px] bg-[--background-secondary] z-50",
60+
isAnimatingIn ? "animate-slide-in-from-right" : "",
61+
isClosing ? "animate-slide-out-to-right" : "",
62+
!isOpen && !isClosing ? "translate-x-full" : "translate-x-0",
63+
"transition-transform duration-300 ease-in-out"
3764
)}>
3865
<div className="pt-[30px] h-full flex flex-col">
3966
{/* Header */}
4067
<div className="pr-8 flex justify-end mb-6">
4168
<Button
4269
variant="ghost"
43-
className="group relative h-10 w-10 flex items-center justify-center hover:w-auto hover:py-3 hover:px-3.5 hover:bg-[#357AF6] hover:rounded-lg rounded-lg bg-white border border-[var(--border-gray)] hover:border-white hover:bg-transparent"
44-
onClick={onClose}
70+
className="group relative h-10 w-10 flex items-center justify-center hover:w-auto hover:py-3 hover:px-3.5 hover:bg-white hover:rounded-lg rounded-lg bg-white border border-[var(--border-gray)] hover:border-[var(--border-gray)]"
71+
onClick={handleClose}
4572
>
46-
<span className="text-sm text-white opacity-0 group-hover:opacity-100 whitespace-nowrap">
73+
<span className="text-sm text-[#357AF6] opacity-0 group-hover:opacity-100 whitespace-nowrap mr-6">
4774
Close
4875
</span>
49-
<X className="h-4 w-4 text-gray-500 group-hover:text-white absolute group-hover:relative" />
76+
<X className="h-4 w-4 text-gray-500 group-hover:text-[#357AF6] absolute right-3" />
5077
</Button>
5178
</div>
5279

5380
{/* Request Info */}
5481
<div className="px-8 mb-6 text-white">
55-
<div className="flex items-center gap-4 mb-[26px]">
82+
<div className="flex items-center gap-2 mb-[26px]">
5683
<span>{log.request_method}</span>
5784
<span>{log.request_path}</span>
5885
<span className={`inline-flex items-center rounded-sm px-2 py-1 text-xs font-medium

dashboard/log-analyzer/src/components/logs/LogTable.tsx

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,23 @@ export function LogTable({ logs = [], onSort, sortColumn, sortOrder, observerRef
5959
) : (
6060
<>
6161
<div className="sticky top-0 z-10 bg-white">
62-
<Table className="border-collapse w-full table-fixed">
63-
<TableHeader className="table-header">
64-
<TableRow>
65-
<TableHead className="w-[10%] truncate">ID</TableHead>
62+
<Table className="border-collapse w-full table-fixed p-0">
63+
<TableHeader className="table-header p-0 m-0">
64+
<TableRow className="p-0 m-0">
6665
<TableHead
67-
className="w-[120px] max-w-[120px] truncate"
66+
className="w-[15%] whitespace-nowrap px-4 py-3 text-left"
6867
onClick={() => onSort('timestamp')}
6968
onMouseEnter={() => setHoveredColumn('timestamp')}
7069
onMouseLeave={() => setHoveredColumn(null)}
7170
>
7271
Time{renderSortIndicator('timestamp')}
7372
</TableHead>
74-
<TableHead className="w-[80px] max-w-[80px] truncate">Level</TableHead>
75-
<TableHead className="w-[120px] max-w-[120px] truncate">Service</TableHead>
76-
<TableHead className="w-[80px] max-w-[80px] truncate">Method</TableHead>
77-
<TableHead className="w-[14%] truncate">Path</TableHead>
78-
<TableHead className="w-[80px] max-w-[80px] truncate">Status</TableHead>
79-
<TableHead className="w-[30%] truncate">Message</TableHead>
73+
<TableHead className="w-[8%] whitespace-nowrap px-4 py-3 text-left">Level</TableHead>
74+
<TableHead className="w-[12%] whitespace-nowrap px-4 py-3 text-left">Service</TableHead>
75+
<TableHead className="w-[8%] whitespace-nowrap px-4 py-3 text-left">Method</TableHead>
76+
<TableHead className="w-[8%] whitespace-nowrap px-4 py-3 text-left">Status</TableHead>
77+
<TableHead className="w-[14%] px-4 py-3 text-left">Path</TableHead>
78+
<TableHead className="w-[35%] px-4 py-3 text-left">Message</TableHead>
8079
</TableRow>
8180
</TableHeader>
8281
</Table>
@@ -92,57 +91,57 @@ export function LogTable({ logs = [], onSort, sortColumn, sortOrder, observerRef
9291
) : (
9392
<div className="flex-1 overflow-auto min-h-0">
9493
<div className="h-full">
95-
<Table className="border-collapse w-full table-fixed">
94+
<Table className="border-collapse w-full table-fixed p-0">
9695
<TableBody>
9796
{logs?.map((log, index) => (
98-
<React.Fragment key={log.request_id || index}>
99-
{hasMore && index === logs.length - 6 && (
100-
<tr ref={observerRef} />
101-
)}
102-
<TableRow
103-
className="table-row cursor-pointer hover:bg-muted/50"
104-
onClick={() => handleRowClick(log)}
105-
>
106-
<TableCell className="w-[10%] truncate">{log.request_id}</TableCell>
107-
<TableCell className="w-[120px] max-w-[120px] truncate">
108-
{new Date(log.timestamp).toLocaleDateString('en-GB', {
109-
day: '2-digit',
110-
month: '2-digit',
111-
year: '2-digit',
112-
hour: '2-digit',
113-
minute: '2-digit',
114-
second: '2-digit',
115-
hour12: false
116-
}).replace(',', '')}
117-
</TableCell>
118-
<TableCell className="w-[80px] max-w-[80px] truncate">
119-
<span className={`inline-flex items-center rounded-sm px-2 py-1 text-xs font-medium
120-
${log.level === 'ERROR' ? 'bg-[var(--bg-pill-error)] text-[var(--text-pill-error)]' :
121-
log.level === 'WARN' ? 'bg-[var(--bg-pill-warn)] text-[var(--text-pill-warn)]' :
122-
log.level === 'INFO' ? 'bg-[var(--bg-pill-info)] text-[var(--text-pill-info)]' :
123-
log.level === 'DEBUG' ? 'bg-[var(--bg-pill-debug)] text-[var(--text-pill-debug)]' :
124-
'bg-[var(--bg-pill-default)] text-[var(--text-pill-default)]'}`
125-
}>
126-
{log.level}
127-
</span>
128-
</TableCell>
129-
<TableCell className="w-[120px] max-w-[120px] truncate">{log.service}</TableCell>
130-
<TableCell className="w-[80px] max-w-[80px] truncate">{log.request_method}</TableCell>
131-
<TableCell className="w-[14%] truncate">{log.request_path}</TableCell>
132-
<TableCell className="w-[80px] max-w-[80px] truncate">
133-
<span className={`inline-flex items-center rounded-sm px-2 py-1 text-xs font-medium
134-
${log.status_code >= 400 ? 'bg-[var(--bg-pill-error)] text-[var(--text-pill-error)]' :
135-
log.status_code >= 300 ? 'bg-[var(--bg-pill-warn)] text-[var(--text-pill-warn)]' :
136-
log.status_code >= 200 ? 'bg-[var(--bg-pill-success)] text-[var(--text-pill-success)]' :
137-
'bg-[var(--bg-pill-info)] text-[var(--text-pill-info)]'}`
138-
}>
139-
{log.status_code}
140-
</span>
141-
</TableCell>
142-
<TableCell className="w-[30%] truncate">{log.message}</TableCell>
143-
</TableRow>
144-
</React.Fragment>
97+
<TableRow
98+
key={index}
99+
className="table-row cursor-pointer hover:bg-muted/50 p-0 m-0"
100+
onClick={() => handleRowClick(log)}
101+
>
102+
<TableCell className="w-[15%] whitespace-nowrap px-4 py-3 text-left truncate">
103+
{new Date(log.timestamp).toLocaleDateString('en-GB', {
104+
day: '2-digit',
105+
month: '2-digit',
106+
year: '2-digit',
107+
hour: '2-digit',
108+
minute: '2-digit',
109+
second: '2-digit',
110+
hour12: false
111+
}).replace(',', '')}
112+
</TableCell>
113+
<TableCell className="w-[8%] whitespace-nowrap px-4 py-3 text-left">
114+
<span className={`inline-flex items-center rounded-sm px-2 py-1 text-xs font-medium
115+
${log.level === 'ERROR' ? 'bg-[var(--bg-pill-error)] text-[var(--text-pill-error)]' :
116+
log.level === 'WARN' ? 'bg-[var(--bg-pill-warn)] text-[var(--text-pill-warn)]' :
117+
log.level === 'INFO' ? 'bg-[var(--bg-pill-info)] text-[var(--text-pill-info)]' :
118+
log.level === 'DEBUG' ? 'bg-[var(--bg-pill-debug)] text-[var(--text-pill-debug)]' :
119+
'bg-[var(--bg-pill-default)] text-[var(--text-pill-default)]'}`
120+
}>
121+
{log.level}
122+
</span>
123+
</TableCell>
124+
<TableCell className="w-[12%] whitespace-nowrap px-4 py-3 text-left">{log.service}</TableCell>
125+
<TableCell className="w-[8%] whitespace-nowrap px-4 py-3 text-left">{log.request_method}</TableCell>
126+
<TableCell className="w-[8%] whitespace-nowrap px-4 py-3 text-left">
127+
<span className={`inline-flex items-center rounded-sm px-2 py-1 text-xs font-medium
128+
${log.status_code >= 400 ? 'bg-[var(--bg-pill-error)] text-[var(--text-pill-error)]' :
129+
log.status_code >= 300 ? 'bg-[var(--bg-pill-warn)] text-[var(--text-pill-warn)]' :
130+
log.status_code >= 200 ? 'bg-[var(--bg-pill-success)] text-[var(--text-pill-success)]' :
131+
'bg-[var(--bg-pill-info)] text-[var(--text-pill-info)]'}`
132+
}>
133+
{log.status_code}
134+
</span>
135+
</TableCell>
136+
<TableCell className="w-[14%] truncate px-4 py-3 text-left">{log.request_path}</TableCell>
137+
<TableCell className="w-[35%] truncate px-4 py-3 text-left">{log.message}</TableCell>
138+
</TableRow>
145139
))}
140+
{hasMore && (
141+
<TableRow ref={observerRef}>
142+
<TableCell colSpan={7} className="p-0 h-4" />
143+
</TableRow>
144+
)}
146145
</TableBody>
147146
</Table>
148147
</div>

0 commit comments

Comments
 (0)