@@ -2,146 +2,16 @@ import { useEffect, useState } from "react";
22import { apiRoute } from "./util" ;
33import { EventData } from "./types" ;
44import { Icon } from "@launchpad-ui/icons" ;
5+ import EventsTable from "./EventsTable" ;
56
67type Props = {
78 limit ?: number ;
89} ;
910
10- const clipboardLink = ( linkText : string , value : string , showNotification : ( message : string ) => void ) => {
11- return (
12- < a
13- href = "#"
14- onClick = { ( e ) => {
15- e . preventDefault ( ) ;
16- navigator . clipboard . writeText ( value ) . then ( ( ) => {
17- showNotification ( "Copied to clipboard!" ) ;
18- } ) . catch ( ( ) => {
19- showNotification ( "Failed to copy to clipboard" ) ;
20- } ) ;
21- } }
22- >
23- { linkText }
24- </ a >
25- ) ;
26- }
27-
28- const summaryRows = ( summaryEvent : EventData , showNotification : ( message : string ) => void ) => {
29- let rows = [ ] ;
30- for ( const [ key , value ] of Object . entries ( ( summaryEvent . data as any ) . features ) ) {
31- const rowId = summaryEvent . id + key ;
32- const counters = ( value as any ) . counters || [ ] ;
33-
34- for ( const counter of counters ) {
35- rows . push (
36- < tr key = { rowId } >
37- < td > { new Date ( summaryEvent . timestamp ) . toLocaleTimeString ( ) } </ td >
38- < td > summary</ td >
39- < td > < Icon name = "flag" size = "small" /> { key } </ td >
40- < td > evaluated as { String ( counter . value ) } </ td >
41- < td > { clipboardLink ( 'Copy to clipboard' , JSON . stringify ( summaryEvent . data ) , showNotification ) } </ td >
42- </ tr >
43- ) ;
44- }
45- }
46-
47- return rows ;
48- }
49-
50- const indexRows = ( indexEvent : EventData , showNotification : ( message : string ) => void ) => {
51- let eventText ;
52- if ( indexEvent . data . context ) {
53- eventText = ( indexEvent . data . context ?. kind || 'unknown' ) + ' context' ;
54- } else if ( indexEvent . data . user ) {
55- eventText = ( indexEvent . data . user . key || 'unknown' ) + ' user' ;
56- }
57- else {
58- eventText = 'unknown context' ;
59- }
60-
61- return [
62- < tr key = { indexEvent . id } >
63- < td > { new Date ( indexEvent . timestamp ) . toLocaleTimeString ( ) } </ td >
64- < td > index</ td >
65- < td > < Icon name = "metric-funnel" size = "small" /> { JSON . stringify ( indexEvent . data ) . length } bytes</ td >
66- < td > { eventText } </ td >
67- < td > { clipboardLink ( 'Copy to clipboard' , JSON . stringify ( indexEvent . data ) , showNotification ) } </ td >
68- </ tr >
69- ]
70- }
71-
72- const featureRows = ( featureEvent : EventData , showNotification : ( message : string ) => void ) => {
73- const data = featureEvent . data as any ; // Type assertion for feature event
74- const eventText = `evaluated as ${ String ( data . value ) } ` ;
75-
76- return [
77- < tr key = { featureEvent . id } className = "feature-row" >
78- < td > { new Date ( featureEvent . timestamp ) . toLocaleTimeString ( ) } </ td >
79- < td > feature</ td >
80- < td > { data . key || 'unknown' } </ td >
81- < td > { eventText } </ td >
82- < td > { clipboardLink ( 'Copy to clipboard' , JSON . stringify ( featureEvent . data ) , showNotification ) } </ td >
83- </ tr >
84- ] ;
85- }
86-
87- const customRows = ( event : EventData , showNotification : ( message : string ) => void ) => {
88- return [
89- < tr key = { event . id } >
90- < td > { new Date ( event . timestamp ) . toLocaleTimeString ( ) } </ td >
91- < td > { event . data . kind } </ td >
92- < td > < Icon name = "chart-histogram" size = "small" /> { event . data . key || 'unknown' } </ td >
93- < td > value is { ( event . data as any ) . metricValue } </ td >
94- < td > { clipboardLink ( 'Copy to clipboard' , JSON . stringify ( event . data ) , showNotification ) } </ td >
95- </ tr > ,
96- ] ;
97- }
98-
99-
100- // Return array of <tr>s:
101- // Time, Type, Key, Event, ViewAttributes
102- const renderEvent = ( event : EventData , showNotification : ( message : string ) => void ) => {
103- switch ( event . data . kind ) {
104- case 'summary' :
105- return summaryRows ( event , showNotification ) ;
106- case 'index' :
107- return indexRows ( event , showNotification ) ;
108- case 'feature' :
109- return featureRows ( event , showNotification ) ;
110- case 'custom' :
111- return customRows ( event , showNotification ) ;
112- default :
113- return [
114- < tr key = { event . id } >
115- < td > { ( ( ) => {
116- try {
117- const date = new Date ( event . timestamp ) ;
118- return isNaN ( date . getTime ( ) ) ? event . timestamp : date . toLocaleTimeString ( ) ;
119- } catch {
120- return event . timestamp ;
121- }
122- } ) ( ) } </ td >
123- < td > { event . data . kind } </ td >
124- < td > </ td >
125- < td > </ td >
126- < td > { clipboardLink ( 'Copy to clipboard' , JSON . stringify ( event . data ) , showNotification ) } </ td >
127- </ tr > ,
128- ] ;
129- }
130- } ;
131-
13211const EventsPage = ( { limit = 1000 } : Props ) => {
13312 const [ events , setEvents ] = useState < EventData [ ] > ( [ ] ) ;
134- const [ notification , setNotification ] = useState < string | null > ( null ) ;
135-
136- const [ isStreaming , setIsStreaming ] = useState < boolean > ( true ) ;
13713 const [ backlog , setBacklog ] = useState < EventData [ ] > ( [ ] ) ;
138-
139- const showNotification = ( message : string ) => {
140- setNotification ( message ) ;
141- setTimeout ( ( ) => {
142- setNotification ( null ) ;
143- } , 1500 ) ;
144- } ;
14+ const [ isStreaming , setIsStreaming ] = useState < boolean > ( true ) ;
14515
14616 useEffect ( ( ) => {
14717 const eventSource = new EventSource ( apiRoute ( '/events/tee' ) ) ;
@@ -188,37 +58,7 @@ const EventsPage = ({ limit = 1000 }: Props) => {
18858 }
18959 } ;
19060
191- return (
192- < div >
193- < h3 > Events Stream (limit: { limit } )</ h3 >
194- < button
195- className = { `streaming-toggle-button ${ isStreaming ? 'streaming' : 'not-streaming' } ` }
196- onClick = { ( ) => toggleStreaming ( ! isStreaming ) }
197- >
198- { isStreaming ? 'Streaming ON' : 'Streaming OFF' }
199- </ button >
200- < table className = "events-table" >
201- < thead >
202- < tr >
203- < th > Time</ th >
204- < th > Type</ th >
205- < th > Target</ th >
206- < th > Event</ th >
207- < th > Link</ th >
208- </ tr >
209- </ thead >
210- < tbody >
211- { events . map ( event => renderEvent ( event , showNotification ) ) }
212- </ tbody >
213- </ table >
214- { events . length === 0 && < p > No events received yet...</ p > }
215- { notification && (
216- < div className = { `copy-notification ${ notification ? 'show' : 'hide' } ` } >
217- { notification }
218- </ div >
219- ) }
220- </ div >
221- ) ;
61+ return < EventsTable events = { events } limit = { limit } onToggleStreaming = { toggleStreaming } /> ;
22262} ;
22363
22464export default EventsPage ;
0 commit comments