11import React , { useState , useEffect } from 'react' ;
2- import {
3- Dialog ,
4- DialogContent ,
5- DialogDescription ,
6- DialogHeader ,
7- DialogTitle ,
8- } from '../../ui/dialog' ;
92import { Button } from '../../ui/button' ;
103import {
114 Select ,
@@ -28,10 +21,9 @@ interface LogEntry {
2821
2922interface DevLogsProps {
3023 isOpen : boolean ;
31- onOpenChange : ( open : boolean ) => void ;
3224}
3325
34- export const DevLogs : React . FC < DevLogsProps > = ( { isOpen, onOpenChange } ) => {
26+ export const DevLogs : React . FC < DevLogsProps > = ( { isOpen } ) => {
3527 const [ logs , setLogs ] = useState < LogEntry [ ] > ( [ ] ) ;
3628 const [ filteredLogs , setFilteredLogs ] = useState < LogEntry [ ] > ( [ ] ) ;
3729 const [ selectedLevel , setSelectedLevel ] = useState < string > ( 'all' ) ;
@@ -116,111 +108,98 @@ export const DevLogs: React.FC<DevLogsProps> = ({ isOpen, onOpenChange }) => {
116108 } ;
117109
118110 return (
119- < Dialog open = { isOpen } onOpenChange = { onOpenChange } >
120- < DialogContent className = "max-w-4xl max-h-[80vh] overflow-hidden flex flex-col" >
121- < DialogHeader >
122- < DialogTitle > Developer Logs</ DialogTitle >
123- < DialogDescription >
124- View sync operation logs with timestamps and status information.
125- </ DialogDescription >
126- </ DialogHeader >
127-
128- < div className = "flex justify-between items-center mb-4 gap-4" >
129- < Select value = { selectedLevel } onValueChange = { setSelectedLevel } >
130- < SelectTrigger className = "w-[180px]" >
131- < SelectValue placeholder = "Filter by level" />
132- </ SelectTrigger >
133- < SelectContent >
134- < SelectItem value = "all" > All Levels</ SelectItem >
135- < SelectItem value = "INFO" > INFO</ SelectItem >
136- < SelectItem value = "WARN" > WARN</ SelectItem >
137- < SelectItem value = "ERROR" > ERROR</ SelectItem >
138- </ SelectContent >
139- </ Select >
111+ < >
112+ < div className = "flex justify-between items-center mb-4 gap-4" >
113+ < Select value = { selectedLevel } onValueChange = { setSelectedLevel } >
114+ < SelectTrigger className = "w-[180px]" >
115+ < SelectValue placeholder = "Filter by level" />
116+ </ SelectTrigger >
117+ < SelectContent >
118+ < SelectItem value = "all" > All Levels</ SelectItem >
119+ < SelectItem value = "INFO" > INFO</ SelectItem >
120+ < SelectItem value = "WARN" > WARN</ SelectItem >
121+ < SelectItem value = "ERROR" > ERROR</ SelectItem >
122+ </ SelectContent >
123+ </ Select >
140124
141- < div className = "flex gap-2" >
142- < Button
143- variant = "outline"
144- size = "sm"
145- onClick = { fetchLogs }
146- disabled = { isLoading }
147- >
148- { isLoading ? 'Refreshing...' : 'Refresh' }
149- </ Button >
150- < Button
151- variant = "outline"
152- size = "sm"
153- onClick = { copyAllLogs }
154- disabled = { filteredLogs . length === 0 }
155- >
156- Copy All
157- </ Button >
158- </ div >
125+ < div className = "flex gap-2" >
126+ < Button
127+ variant = "outline"
128+ size = "sm"
129+ onClick = { fetchLogs }
130+ disabled = { isLoading }
131+ >
132+ { isLoading ? 'Refreshing...' : 'Refresh' }
133+ </ Button >
134+ < Button
135+ variant = "outline"
136+ size = "sm"
137+ onClick = { copyAllLogs }
138+ disabled = { filteredLogs . length === 0 }
139+ >
140+ Copy All
141+ </ Button >
159142 </ div >
143+ </ div >
160144
161- < div className = "flex-1 overflow-y-auto border rounded-md p-4 bg-gray-50 dark:bg-gray-900" >
162- { isLoading ? (
163- < div className = "text-center py-8 text-gray-500" >
164- Loading logs...
165- </ div >
166- ) : filteredLogs . length === 0 ? (
167- < div className = "text-center py-8 text-gray-500" >
168- No logs available
169- </ div >
170- ) : (
171- < div className = "space-y-2" >
172- { filteredLogs . map ( ( log , index ) => (
173- < div
174- key = { index }
175- className = "p-3 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 hover:shadow-sm transition-shadow group"
176- >
177- < div className = "flex justify-between items-start gap-2" >
178- < div className = "flex-1 font-mono text-sm " >
179- < div className = "flex items-center gap-2 mb-1" >
180- < span className = "text-gray-500 dark:text-gray-400" >
181- { formatTimestamp ( log . timestamp ) }
182- </ span >
183- < span
184- className = { `font-semibold ${ getLevelColor (
185- log . level
186- ) } ` }
187- >
188- [ { log . level } ]
145+ < div className = "flex-1 overflow-y-auto border rounded-md p-4 bg-gray-50 dark:bg-gray-900" >
146+ { isLoading ? (
147+ < div className = "text-center py-8 text-gray-500" > Loading logs... </ div >
148+ ) : filteredLogs . length === 0 ? (
149+ < div className = "text-center py-8 text-gray-500" >
150+ No logs available
151+ </ div >
152+ ) : (
153+ < div className = "space-y-2" >
154+ { filteredLogs . map ( ( log , index ) => (
155+ < div
156+ key = { index }
157+ className = "p-3 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 hover:shadow-sm transition-shadow group"
158+ >
159+ < div className = "flex justify-between items-start gap-2" >
160+ < div className = "flex-1 font-mono text-sm" >
161+ < div className = "flex items-center gap-2 mb-1 " >
162+ < span className = "text-gray-500 dark: text-gray-400 " >
163+ { formatTimestamp ( log . timestamp ) }
164+ </ span >
165+ < span
166+ className = { `font-semibold ${ getLevelColor ( log . level ) } ` }
167+ >
168+ [ { log . level } ]
169+ </ span >
170+ { log . operation && (
171+ < span className = "text-purple-600 dark:text-purple-400 text-xs" >
172+ { log . operation }
189173 </ span >
190- { log . operation && (
191- < span className = "text-purple-600 dark:text-purple-400 text-xs" >
192- { log . operation }
193- </ span >
194- ) }
195- </ div >
196- < div className = "text-gray-800 dark:text-gray-200 break-words" >
197- { log . message }
198- </ div >
199- { log . syncId && (
200- < div className = "text-xs text-gray-500 dark:text-gray-400 mt-1" >
201- Sync ID: { log . syncId }
202- </ div >
203174 ) }
204175 </ div >
205- < Button
206- variant = "ghost"
207- size = "sm"
208- onClick = { ( ) => copyLog ( log , index ) }
209- className = "opacity-0 group-hover:opacity-100 transition-opacity"
210- >
211- { copiedIndex === index ? (
212- < CheckIcon className = "h-4 w-4 text-green-600" />
213- ) : (
214- < CopyIcon className = "h-4 w-4" />
215- ) }
216- </ Button >
176+ < div className = "text-gray-800 dark:text-gray-200 break-words" >
177+ { log . message }
178+ </ div >
179+ { log . syncId && (
180+ < div className = "text-xs text-gray-500 dark:text-gray-400 mt-1" >
181+ Sync ID: { log . syncId }
182+ </ div >
183+ ) }
217184 </ div >
185+ < Button
186+ variant = "ghost"
187+ size = "sm"
188+ onClick = { ( ) => copyLog ( log , index ) }
189+ className = "opacity-0 group-hover:opacity-100 transition-opacity"
190+ >
191+ { copiedIndex === index ? (
192+ < CheckIcon className = "h-4 w-4 text-green-600" />
193+ ) : (
194+ < CopyIcon className = "h-4 w-4" />
195+ ) }
196+ </ Button >
218197 </ div >
219- ) ) }
220- </ div >
221- ) }
222- </ div >
223- </ DialogContent >
224- </ Dialog >
198+ </ div >
199+ ) ) }
200+ </ div >
201+ ) }
202+ </ div >
203+ </ >
225204 ) ;
226205} ;
0 commit comments