@@ -8,26 +8,21 @@ import { Component } from "react"
88
99import { login } from "./api/auth"
1010import { getDataModel } from "./api/datamodel"
11- import { nrMeasurementsApi } from "./api/measurement"
11+ import { createNrMeasurementsEventSource } from "./api/measurement"
1212import { getReport , getReportsOverview } from "./api/report"
1313import { AppUI } from "./AppUI"
14- import { registeredURLSearchParams } from "./hooks/url_search_query"
14+ import { registeredURLSearchParams , toSearchString } from "./hooks/url_search_query"
1515import { showURLAvailabilityMessages } from "./messages"
16+ import { clearStoredSession , loadStoredSession , storeSession } from "./session_storage"
1617import { theme } from "./theme"
17- import { isValidISODate , toISODateStringInCurrentTZ } from "./utils"
18+ import { endOfDayFromISODateString , reportUuidFromPath , toISODateStringInCurrentTZ } from "./utils"
1819import { SnackbarAlerts } from "./widgets/SnackbarAlerts"
1920
2021class App extends Component {
2122 constructor ( props ) {
2223 super ( props )
23- const pathname = history . location . pathname
24- const reportUuid = decodeURI ( pathname . slice ( 1 , pathname . length ) )
25- const reportDateISOString = registeredURLSearchParams ( ) . get ( "report_date" ) || ""
26- let reportDate = null
27- if ( isValidISODate ( reportDateISOString ) ) {
28- reportDate = new Date ( reportDateISOString )
29- reportDate . setHours ( 23 , 59 , 59 )
30- }
24+ const reportUuid = reportUuidFromPath ( history . location . pathname )
25+ const reportDate = endOfDayFromISODateString ( registeredURLSearchParams ( ) . get ( "report_date" ) || "" )
3126 this . state = {
3227 dataModel : { } ,
3328 lastUpdate : new Date ( ) ,
@@ -47,8 +42,7 @@ class App extends Component {
4742
4843 onHistory ( { location, action } ) {
4944 if ( action === Action . Pop ) {
50- const pathname = location . pathname
51- const reportUuid = pathname . slice ( 1 , pathname . length )
45+ const reportUuid = reportUuidFromPath ( location . pathname )
5246 this . setState ( { reportUuid : reportUuid , loading : true } , ( ) => this . reload ( ) )
5347 }
5448 }
@@ -153,8 +147,7 @@ class App extends Component {
153147 parsed . delete ( "report_date" )
154148 date = null
155149 }
156- const search = parsed . toString ( ) . replaceAll ( "%2C" , "," ) // No need to encode commas
157- history . replace ( { search : search . length > 0 ? "?" + search : "" } )
150+ history . replace ( { search : toSearchString ( parsed ) } )
158151 this . setState ( { reportDate : date , loading : true } , ( ) => this . reload ( ) )
159152 }
160153
@@ -171,40 +164,38 @@ class App extends Component {
171164 }
172165
173166 historyPush ( target ) {
174- const search = registeredURLSearchParams ( ) . toString ( ) . replaceAll ( "%2C" , "," ) // No need to encode commas
175- history . push ( target + ( search . length > 0 ? "?" + search : "" ) )
167+ history . push ( target + toSearchString ( registeredURLSearchParams ( ) ) )
176168 }
177169
178170 connectToNrMeasurementsEventSource ( ) {
179- this . source = new EventSource ( nrMeasurementsApi )
180- this . source . addEventListener ( "init" , ( message ) => {
181- const newNrMeasurements = Number ( message . data )
182- if ( this . state . nrMeasurementsStreamConnected ) {
183- this . setState ( { nrMeasurements : newNrMeasurements } )
184- } else {
171+ this . source = createNrMeasurementsEventSource ( {
172+ onInit : ( newNrMeasurements ) => {
173+ if ( this . state . nrMeasurementsStreamConnected ) {
174+ this . setState ( { nrMeasurements : newNrMeasurements } )
175+ } else {
176+ this . showMessage ( {
177+ severity : "success" ,
178+ title : "Connected to server" ,
179+ description : "Successfully reconnected to server" ,
180+ } )
181+ this . setState ( { nrMeasurements : newNrMeasurements , nrMeasurementsStreamConnected : true } , ( ) =>
182+ this . reload ( ) ,
183+ )
184+ }
185+ } ,
186+ onDelta : ( newNrMeasurements ) => {
187+ if ( newNrMeasurements !== this . state . nrMeasurements ) {
188+ this . setState ( { nrMeasurements : newNrMeasurements } , ( ) => this . reload ( ) )
189+ }
190+ } ,
191+ onError : ( ) => {
185192 this . showMessage ( {
186- severity : "success " ,
187- title : "Connected to server " ,
188- description : "Successfully reconnected to server" ,
193+ severity : "error " ,
194+ title : "Server unreachable " ,
195+ description : "Trying to reconnect to server... " ,
189196 } )
190- this . setState ( { nrMeasurements : newNrMeasurements , nrMeasurementsStreamConnected : true } , ( ) =>
191- this . reload ( ) ,
192- )
193- }
194- } )
195- this . source . addEventListener ( "delta" , ( message ) => {
196- const newNrMeasurements = Number ( message . data )
197- if ( newNrMeasurements !== this . state . nrMeasurements ) {
198- this . setState ( { nrMeasurements : newNrMeasurements } , ( ) => this . reload ( ) )
199- }
200- } )
201- this . source . addEventListener ( "error" , ( ) => {
202- this . showMessage ( {
203- severity : "error" ,
204- title : "Server unreachable" ,
205- description : "Trying to reconnect to server..." ,
206- } )
207- this . setState ( { nrMeasurementsStreamConnected : false } )
197+ this . setState ( { nrMeasurementsStreamConnected : false } )
198+ } ,
208199 } )
209200 }
210201
@@ -228,47 +219,32 @@ class App extends Component {
228219 }
229220
230221 initUserSession ( ) {
231- // Check if there is a session expiration datetime in the local storage. If so, restore the session as long as
232- // it has not expired. Otherwise, nothing needs to be done.
233- const sessionExpirationDateTimeISOString = localStorage . getItem ( "session_expiration_datetime" )
234- if ( sessionExpirationDateTimeISOString ) {
235- const sessionExpirationDateTime = new Date ( sessionExpirationDateTimeISOString )
236- if ( sessionExpirationDateTime < new Date ( ) ) {
237- // The session expired while the user was away. Reset it and notify the user of the expired session.
238- this . onUserSessionExpiration ( )
239- } else {
240- // Session is still active, restore it from local storage.
241- this . setUserSession (
242- localStorage . getItem ( "user" ) ,
243- localStorage . getItem ( "email" ) ,
244- sessionExpirationDateTime ,
245- )
246- }
247- } else {
222+ const stored = loadStoredSession ( )
223+ if ( ! stored ) {
248224 this . showMessage ( {
249225 severity : "info" ,
250226 title : "Not logged in" ,
251227 description : "Editing is not possible until you are logged in" ,
252228 } )
229+ } else if ( stored . sessionExpirationDateTime < new Date ( ) ) {
230+ this . onUserSessionExpiration ( )
231+ } else {
232+ this . setUserSession ( stored . user , stored . email , stored . sessionExpirationDateTime )
253233 }
254234 }
255235
256236 setUserSession ( username , email , sessionExpirationDateTime ) {
257237 if ( username ) {
258238 const emailAddress = email ?. includes ( "@" ) ? email : null
259239 this . setState ( { user : username , email : emailAddress } )
260- localStorage . setItem ( "user" , username )
261- localStorage . setItem ( "email" , emailAddress )
262- localStorage . setItem ( "session_expiration_datetime" , sessionExpirationDateTime . toISOString ( ) )
240+ storeSession ( username , emailAddress , sessionExpirationDateTime )
263241 this . sessionExpirationTimeoutId = setTimeout (
264242 ( ) => this . onUserSessionExpiration ( ) ,
265243 sessionExpirationDateTime - Date . now ( ) ,
266244 )
267245 } else {
268246 this . setState ( { user : null , email : null } )
269- localStorage . removeItem ( "user" )
270- localStorage . removeItem ( "email" )
271- localStorage . removeItem ( "session_expiration_datetime" )
247+ clearStoredSession ( )
272248 clearTimeout ( this . sessionExpirationTimeoutId )
273249 }
274250 }
0 commit comments