@@ -38,9 +38,8 @@ interface LogDetailModalProps {
3838 onClose : ( ) => void
3939}
4040
41- function JsonViewer ( { data, maxHeight = 300 } : { data : string ; maxHeight ?: number } ) {
41+ function JsonViewer ( { data } : { data : string } ) {
4242 const [ copied , setCopied ] = useState ( false )
43- const [ expanded , setExpanded ] = useState ( false )
4443
4544 const handleCopy = useCallback ( async ( ) => {
4645 try {
@@ -52,64 +51,14 @@ function JsonViewer({ data, maxHeight = 300 }: { data: string; maxHeight?: numbe
5251 }
5352 } , [ data ] )
5453
55- const lines = data . split ( '\n' )
56- const lineCount = lines . length
57- const isLong = lineCount > 20 || data . length > 2000
58-
59- const renderLine = ( line : string , index : number ) => {
60- let className = 'text-muted-foreground'
61-
62- if ( line . includes ( ':' ) ) {
63- const valueParts = line . split ( ':' )
64- const value = valueParts . slice ( 1 ) . join ( ':' ) . trim ( )
65-
66- if ( value . startsWith ( '"' ) || value . startsWith ( "'" ) ) {
67- className = 'text-green-500'
68- } else if ( value === 'true' || value === 'false' ) {
69- className = 'text-yellow-500'
70- } else if ( ! isNaN ( Number ( value ) ) ) {
71- className = 'text-blue-500'
72- } else if ( value === 'null' ) {
73- className = 'text-red-400'
74- }
75- }
76-
77- return (
78- < div key = { index } className = "flex" >
79- < span className = "w-8 text-right pr-2 text-muted-foreground/50 select-none text-xs" >
80- { index + 1 }
81- </ span >
82- < span className = { cn ( 'text-xs font-mono' , className ) } > { line } </ span >
83- </ div >
84- )
85- }
86-
8754 return (
8855 < div className = "relative" >
89- < div
90- className = { cn ( 'bg-muted/50 rounded-lg p-3 overflow-auto' , ! expanded && isLong ) }
91- style = { { maxHeight : expanded ? undefined : maxHeight } }
92- >
93- < pre className = "text-xs font-mono" >
94- { lines . slice ( 0 , expanded ? undefined : 20 ) . map ( renderLine ) }
95- { ! expanded && isLong && (
96- < div className = "text-muted-foreground text-center py-2" >
97- ... { lineCount - 20 } more lines
98- </ div >
99- ) }
56+ < div className = "bg-muted/50 rounded-lg p-3 overflow-x-auto" >
57+ < pre className = "text-xs font-mono whitespace-pre-wrap break-all" >
58+ { data }
10059 </ pre >
10160 </ div >
102- < div className = "absolute top-2 right-2 flex gap-1" >
103- { isLong && (
104- < Button
105- variant = "ghost"
106- size = "sm"
107- className = "h-6 px-2 text-xs"
108- onClick = { ( ) => setExpanded ( ! expanded ) }
109- >
110- { expanded ? 'Collapse' : 'Expand' }
111- </ Button >
112- ) }
61+ < div className = "absolute top-2 right-2" >
11362 < Button
11463 variant = "ghost"
11564 size = "sm"
@@ -140,9 +89,9 @@ export function LogDetailModal({ log, open, onClose }: LogDetailModalProps) {
14089
14190 return (
14291 < Dialog open = { open } onOpenChange = { ( v ) => ! v && onClose ( ) } >
143- < DialogContent className = "max-w-3xl max-h-[80vh] " >
144- < DialogHeader >
145- < DialogTitle className = "flex items-center justify-between" >
92+ < DialogContent className = "max-w-3xl w-[90vw] h-[85vh] max-h-[800px] p-0 flex flex-col " >
93+ < DialogHeader className = "px-6 pt-6 pb-4 shrink-0" >
94+ < DialogTitle className = "flex items-center justify-between flex-wrap gap-2 " >
14695 < span > { t ( 'logs.detail' ) } </ span >
14796 < div className = "flex gap-2" >
14897 < Button variant = "outline" size = "sm" onClick = { handleExport } >
@@ -155,38 +104,38 @@ export function LogDetailModal({ log, open, onClose }: LogDetailModalProps) {
155104 </ div >
156105 </ DialogTitle >
157106 </ DialogHeader >
158- < ScrollArea className = "flex-1" >
159- < div className = "space-y-4" >
107+ < ScrollArea className = "flex-1 px-6 pb-6 min-h-0 " >
108+ < div className = "space-y-4 pr-4 " >
160109 < div className = "grid grid-cols-2 gap-4" >
161- < div >
110+ < div className = "min-w-0" >
162111 < label className = "text-sm text-muted-foreground" > { t ( 'logs.time' ) } </ label >
163- < p className = "font-medium" > { log . timestamp } </ p >
112+ < p className = "font-medium break-all " > { log . timestamp } </ p >
164113 </ div >
165- < div >
114+ < div className = "min-w-0" >
166115 < label className = "text-sm text-muted-foreground" > { t ( 'logs.status' ) } </ label >
167- < p className = "font-medium flex items-center gap-2" >
116+ < p className = "font-medium flex items-center gap-2 flex-wrap " >
168117 < span
169118 className = { cn (
170- 'h-2 w-2 rounded-full' ,
119+ 'h-2 w-2 rounded-full shrink-0 ' ,
171120 log . status === 'success' ? 'bg-green-500' : 'bg-red-500'
172121 ) }
173122 />
174- { log . statusCode }
123+ < span className = "break-all" > { log . statusCode } </ span >
175124 </ p >
176125 </ div >
177- < div >
126+ < div className = "min-w-0" >
178127 < label className = "text-sm text-muted-foreground" > { t ( 'logs.provider' ) } </ label >
179- < p className = "font-medium" > { log . provider || '-' } </ p >
128+ < p className = "font-medium break-all " > { log . provider || '-' } </ p >
180129 </ div >
181- < div >
130+ < div className = "min-w-0" >
182131 < label className = "text-sm text-muted-foreground" > { t ( 'logs.model' ) } </ label >
183- < p className = "font-medium" > { log . model || '-' } </ p >
132+ < p className = "font-medium break-all " > { log . model || '-' } </ p >
184133 </ div >
185- < div >
134+ < div className = "min-w-0" >
186135 < label className = "text-sm text-muted-foreground" > { t ( 'logs.account' ) } </ label >
187- < p className = "font-medium" > { log . account || '-' } </ p >
136+ < p className = "font-medium break-all " > { log . account || '-' } </ p >
188137 </ div >
189- < div >
138+ < div className = "min-w-0" >
190139 < label className = "text-sm text-muted-foreground" > Duration</ label >
191140 < p className = "font-medium" > { log . duration ? `${ ( log . duration * 1000 ) . toFixed ( 0 ) } ms` : '-' } </ p >
192141 </ div >
@@ -195,17 +144,21 @@ export function LogDetailModal({ log, open, onClose }: LogDetailModalProps) {
195144 { log . userInput && (
196145 < div >
197146 < label className = "text-sm text-muted-foreground" > { t ( 'logs.userInput' ) } </ label >
198- < div className = "mt-1 p-3 bg-muted/50 rounded-lg overflow-auto max-h-[200px]" >
199- < p className = "text-sm whitespace-pre-wrap break-all" > { log . userInput } </ p >
147+ < div className = "mt-1 p-3 bg-muted/50 rounded-lg" >
148+ < pre className = "text-sm whitespace-pre-wrap break-all font-sans" >
149+ { log . userInput }
150+ </ pre >
200151 </ div >
201152 </ div >
202153 ) }
203154
204155 { log . error && (
205156 < div >
206157 < label className = "text-sm text-red-500" > Error</ label >
207- < div className = "mt-1 p-3 bg-red-500/10 rounded-lg border border-red-500/20 overflow-auto max-h-[200px]" >
208- < p className = "text-sm text-red-600 whitespace-pre-wrap break-all" > { log . error } </ p >
158+ < div className = "mt-1 p-3 bg-red-500/10 rounded-lg border border-red-500/20" >
159+ < pre className = "text-sm text-red-600 whitespace-pre-wrap break-all font-sans" >
160+ { log . error }
161+ </ pre >
209162 </ div >
210163 </ div >
211164 ) }
0 commit comments