@@ -36,6 +36,78 @@ const MARKER_COLORS = [
3636 "#26A69A" , // Darker Teal
3737] ;
3838
39+ const ODRD_FILTERS = [ "createVehicle" , "getVehicle" , "updateVehicle" , "createTrip" , "getTrip" , "updateTrip" ] ;
40+
41+ function FilterBar ( { availableFilters, filterState, clickHandler } ) {
42+ const [ isOpen , setIsOpen ] = React . useState ( false ) ;
43+ const filterBarRef = React . useRef ( null ) ;
44+
45+ React . useEffect ( ( ) => {
46+ function handleClickOutside ( event ) {
47+ if ( filterBarRef . current && ! filterBarRef . current . contains ( event . target ) ) {
48+ log ( "Clicked outside FilterBar, closing menu." ) ;
49+ setIsOpen ( false ) ;
50+ }
51+ }
52+ if ( isOpen ) {
53+ log ( "Filter menu is open, adding click outside listener." ) ;
54+ document . addEventListener ( "mousedown" , handleClickOutside ) ;
55+ }
56+ return ( ) => {
57+ document . removeEventListener ( "mousedown" , handleClickOutside ) ;
58+ } ;
59+ } , [ isOpen ] ) ;
60+
61+ if ( ! availableFilters || availableFilters . length === 0 ) {
62+ return null ;
63+ }
64+
65+ const handleButtonClick = ( ) => {
66+ log ( `Filter button clicked. Menu will be ${ ! isOpen ? "opened" : "closed" } .` ) ;
67+ setIsOpen ( ! isOpen ) ;
68+ } ;
69+
70+ const activeFilterCount = availableFilters . filter ( ( type ) => filterState [ type ] ) . length ;
71+ const totalFilterCount = availableFilters . length ;
72+ const buttonText = `Filter Log Types (${ activeFilterCount } /${ totalFilterCount } )` ;
73+ const isFiltered = activeFilterCount !== totalFilterCount ;
74+
75+ return (
76+ < div style = { { position : "relative" , display : "inline-block" } } ref = { filterBarRef } >
77+ < button
78+ className = { `toggle-button ${ isOpen || isFiltered ? "toggle-button-active" : "" } ` }
79+ onClick = { handleButtonClick }
80+ >
81+ { buttonText }
82+ </ button >
83+ { isOpen && (
84+ < div className = "filter-menu" >
85+ { availableFilters . map ( ( filterType ) => (
86+ < label key = { filterType } className = "filter-menu-item" >
87+ < input type = "checkbox" checked = { ! ! filterState [ filterType ] } onChange = { ( ) => clickHandler ( filterType ) } />
88+ { filterType }
89+ </ label >
90+ ) ) }
91+ </ div >
92+ ) }
93+ </ div >
94+ ) ;
95+ }
96+
97+ function TripIdFilter ( { value, onChange } ) {
98+ return (
99+ < div style = { { marginLeft : "10px" } } >
100+ < input
101+ type = "text"
102+ placeholder = "Filter by Trip ID"
103+ value = { value }
104+ onChange = { onChange }
105+ className = "trip-id-filter-input"
106+ />
107+ </ div >
108+ ) ;
109+ }
110+
39111class App extends React . Component {
40112 constructor ( props ) {
41113 super ( props ) ;
@@ -55,6 +127,21 @@ class App extends React.Component {
55127 featuredObject : { msg : "Click a table row to select object" } ,
56128 extraColumns : [ ] ,
57129 toggleOptions : Object . fromEntries ( ALL_TOGGLES . map ( ( t ) => [ t . id , false ] ) ) ,
130+ logTypeFilters : {
131+ createVehicle : true ,
132+ getVehicle : true ,
133+ updateVehicle : true ,
134+ createTrip : true ,
135+ getTrip : true ,
136+ updateTrip : true ,
137+ createDeliveryVehicle : true ,
138+ getDeliveryVehicle : true ,
139+ updateDeliveryVehicle : true ,
140+ createTask : true ,
141+ getTask : true ,
142+ updateTask : true ,
143+ } ,
144+ tripIdFilter : "" ,
58145 uploadedDatasets : [ null , null , null , null , null ] ,
59146 activeDatasetIndex : null ,
60147 activeMenuIndex : null ,
@@ -176,7 +263,9 @@ class App extends React.Component {
176263 this . setState ( ( prevState ) => {
177264 const minDate = new Date ( prevState . timeRange . minTime ) ;
178265 const maxDate = new Date ( prevState . timeRange . maxTime ) ;
179- const logs = this . state . currentLogData . tripLogs . getLogs_ ( minDate , maxDate ) . value ( ) ;
266+ const logs = this . state . currentLogData . tripLogs
267+ . getLogs_ ( minDate , maxDate , prevState . logTypeFilters , prevState . tripIdFilter )
268+ . value ( ) ;
180269 if ( logs . length > 0 ) {
181270 const firstRow = logs [ 0 ] ;
182271 setTimeout ( ( ) => this . focusOnSelectedRow ( ) , 0 ) ;
@@ -194,7 +283,12 @@ class App extends React.Component {
194283 selectLastRow = ( ) => {
195284 const minDate = new Date ( this . state . timeRange . minTime ) ;
196285 const maxDate = new Date ( this . state . timeRange . maxTime ) ;
197- const logsWrapper = this . state . currentLogData . tripLogs . getLogs_ ( minDate , maxDate ) ;
286+ const logsWrapper = this . state . currentLogData . tripLogs . getLogs_ (
287+ minDate ,
288+ maxDate ,
289+ this . state . logTypeFilters ,
290+ this . state . tripIdFilter
291+ ) ;
198292 const logs = logsWrapper . value ( ) ;
199293 if ( logs . length > 0 ) {
200294 const lastRow = logs [ logs . length - 1 ] ;
@@ -206,17 +300,25 @@ class App extends React.Component {
206300 } ;
207301
208302 handleRowChange = async ( direction ) => {
209- const { featuredObject } = this . state ;
303+ const { featuredObject, logTypeFilters , tripIdFilter } = this . state ;
210304 const minDate = new Date ( this . state . timeRange . minTime ) ;
211305 const maxDate = new Date ( this . state . timeRange . maxTime ) ;
212- const logs = this . state . currentLogData . tripLogs . getLogs_ ( minDate , maxDate ) . value ( ) ;
306+ const logs = this . state . currentLogData . tripLogs . getLogs_ ( minDate , maxDate , logTypeFilters , tripIdFilter ) . value ( ) ;
213307 let newFeaturedObject = featuredObject ;
214308 const currentIndex = logs . findIndex ( ( log ) => log . timestamp === featuredObject . timestamp ) ;
215- if ( direction === "next" && currentIndex < logs . length - 1 ) {
309+
310+ if ( currentIndex === - 1 ) {
311+ if ( logs . length > 0 ) {
312+ newFeaturedObject = logs [ 0 ] ;
313+ } else {
314+ return ;
315+ }
316+ } else if ( direction === "next" && currentIndex < logs . length - 1 ) {
216317 newFeaturedObject = logs [ currentIndex + 1 ] ;
217318 } else if ( direction === "previous" && currentIndex > 0 ) {
218319 newFeaturedObject = logs [ currentIndex - 1 ] ;
219320 }
321+
220322 if ( newFeaturedObject !== featuredObject ) {
221323 this . setState ( { featuredObject : newFeaturedObject } , ( ) => {
222324 this . focusOnSelectedRow ( ) ;
@@ -789,6 +891,22 @@ class App extends React.Component {
789891 this . updateToggleState ( newValue , id , toggle . columns ) ;
790892 }
791893
894+ handleLogTypeFilterChange = ( filterType ) => {
895+ log ( `Filter toggled for: ${ filterType } ` ) ;
896+ this . setState ( ( prevState ) => ( {
897+ logTypeFilters : {
898+ ...prevState . logTypeFilters ,
899+ [ filterType ] : ! prevState . logTypeFilters [ filterType ] ,
900+ } ,
901+ } ) ) ;
902+ } ;
903+
904+ handleTripIdFilterChange = ( event ) => {
905+ const value = event . target . value ;
906+ log ( `Trip ID filter changed to: "${ value } "` ) ;
907+ this . setState ( { tripIdFilter : value } ) ;
908+ } ;
909+
792910 render ( ) {
793911 const {
794912 featuredObject,
@@ -798,8 +916,11 @@ class App extends React.Component {
798916 extraColumns,
799917 dynamicMarkerLocations,
800918 visibleToggles,
919+ logTypeFilters,
920+ tripIdFilter,
801921 } = this . state ;
802922 const selectedEventTime = featuredObject ?. timestamp ? new Date ( featuredObject . timestamp ) . getTime ( ) : null ;
923+ const availableFilters = currentLogData . solutionType === "ODRD" ? ODRD_FILTERS : [ ] ;
803924
804925 return (
805926 < div className = "app-container" >
@@ -821,6 +942,8 @@ class App extends React.Component {
821942 setRenderMarkerOnMap = { this . setRenderMarkerOnMap }
822943 focusSelectedRow = { this . focusOnSelectedRow }
823944 initialMapBounds = { this . state . initialMapBounds }
945+ logTypeFilters = { logTypeFilters }
946+ tripIdFilter = { tripIdFilter }
824947 />
825948 </ div >
826949 < TimeSlider
@@ -832,12 +955,22 @@ class App extends React.Component {
832955 onRowSelect = { ( row , rowIndex ) => this . onSelectionChange ( row , rowIndex ) }
833956 centerOnLocation = { this . centerOnLocation }
834957 focusSelectedRow = { this . focusOnSelectedRow }
958+ logTypeFilters = { logTypeFilters }
959+ tripIdFilter = { tripIdFilter }
835960 />
836- < ToggleBar
837- toggles = { visibleToggles }
838- toggleState = { toggleOptions }
839- clickHandler = { ( id ) => this . toggleClickHandler ( id ) }
840- />
961+ < div className = "togglebar-button-group" >
962+ < ToggleBar
963+ toggles = { visibleToggles }
964+ toggleState = { toggleOptions }
965+ clickHandler = { ( id ) => this . toggleClickHandler ( id ) }
966+ />
967+ < FilterBar
968+ availableFilters = { availableFilters }
969+ filterState = { logTypeFilters }
970+ clickHandler = { this . handleLogTypeFilterChange }
971+ />
972+ < TripIdFilter value = { tripIdFilter } onChange = { this . handleTripIdFilterChange } />
973+ </ div >
841974 < div className = "nav-controls" >
842975 < div className = "button-row" >
843976 < div className = "playback-controls" >
@@ -883,6 +1016,8 @@ class App extends React.Component {
8831016 onSelectionChange = { ( rowData , rowIndex ) => this . onSelectionChange ( rowData , rowIndex ) }
8841017 setFocusOnRowFunction = { this . setFocusOnRowFunction }
8851018 centerOnLocation = { this . centerOnLocation }
1019+ logTypeFilters = { logTypeFilters }
1020+ tripIdFilter = { tripIdFilter }
8861021 />
8871022 </ div >
8881023 </ div >
0 commit comments