11import { useEffect , useState } from "react" ;
22import { apiRoute } from "./util" ;
33import { EventData } from "./types" ;
4- import Event from "./Event" ;
54
65type Props = {
6+ limit ?: number ;
77} ;
88
9+ const clipboardLink = ( linkText : string , value : string ) => {
10+ return (
11+ < a
12+ href = "#"
13+ onClick = { ( e ) => {
14+ e . preventDefault ( ) ;
15+ navigator . clipboard . writeText ( value ) ;
16+ } }
17+ >
18+ { linkText }
19+ </ a >
20+ ) ;
21+ }
922
23+ const summaryRows = ( summaryEvent : any ) => {
24+ let parsed ;
25+ try {
26+ parsed = JSON . parse ( summaryEvent . data ) ;
27+ } catch ( error ) {
28+ console . error ( 'Failed to parse event data as JSON:' , error ) ;
29+ return < div > Error. See console.</ div > ;
30+ }
31+ console . log ( 'parsed' , parsed ) ;
32+
33+ let rows = [ ] ;
34+ for ( const [ key , value ] of Object . entries ( parsed . features ) ) {
35+ const rowId = summaryEvent . id + key ;
36+ const counters = ( value as any ) . counters || [ ] ;
37+
38+ for ( const counter of counters ) {
39+ rows . push (
40+ < tr key = { rowId } >
41+ < td > { new Date ( summaryEvent . timestamp ) . toLocaleTimeString ( ) } </ td >
42+ < td > summary</ td >
43+ < td > { key } </ td >
44+ < td > evaluated as { String ( counter . value ) } </ td >
45+ < td > { clipboardLink ( 'copy to clipboard' , JSON . stringify ( parsed ) ) } </ td >
46+ </ tr >
47+ ) ;
48+ }
49+ }
50+
51+ return rows ;
52+ }
53+
54+ // Return array of <tr>s:
55+ // Time, Type, Key, Event, ViewAttributes
1056const renderEvent = ( event : EventData ) => {
1157 let parsed ;
1258 try {
@@ -16,10 +62,22 @@ const renderEvent = (event: EventData) => {
1662 return < div > Error. See console.</ div > ;
1763 }
1864
19- return < Event event = { event } /> ;
65+ if ( parsed . kind === 'summary' ) {
66+ return summaryRows ( event ) ;
67+ }
68+
69+ return [
70+ < tr key = { event . id } >
71+ < td > { event . timestamp } </ td >
72+ < td > { parsed . kind } </ td >
73+ < td > </ td >
74+ < td > { parsed . kind } </ td >
75+ < td > </ td >
76+ </ tr > ,
77+ ] ;
2078} ;
2179
22- const EventsPage = ( { } : Props ) => {
80+ const EventsPage = ( { limit = 1000 } : Props ) => {
2381 const [ events , setEvents ] = useState < EventData [ ] > ( [ ] ) ;
2482
2583 useEffect ( ( ) => {
@@ -34,7 +92,7 @@ const EventsPage = ({}: Props) => {
3492 timestamp : Date . now ( ) ,
3593 data : event . data
3694 } ;
37- setEvents ( prevEvents => [ ...prevEvents , newEvent ] ) ;
95+ setEvents ( prevEvents => [ newEvent , ...prevEvents ] . slice ( 0 , limit ) ) ;
3896 } ) ;
3997
4098 return ( ) => {
@@ -45,12 +103,21 @@ const EventsPage = ({}: Props) => {
45103
46104 return (
47105 < div >
48- < h3 > Events Stream</ h3 >
49- < ul >
50- { events . map ( event => (
51- < li key = { event . id } > { renderEvent ( event ) } </ li >
52- ) ) }
53- </ ul >
106+ < h3 > Events Stream (limit: { limit } )</ h3 >
107+ < table className = "events-table" >
108+ < thead >
109+ < tr >
110+ < th > Time</ th >
111+ < th > Type</ th >
112+ < th > Key</ th >
113+ < th > Event</ th >
114+ < th > Link</ th >
115+ </ tr >
116+ </ thead >
117+ < tbody >
118+ { events . map ( event => renderEvent ( event ) ) }
119+ </ tbody >
120+ </ table >
54121 { events . length === 0 && < p > No events received yet...</ p > }
55122 </ div >
56123 ) ;
0 commit comments