diff --git a/frontend/src/Sidebar/ResultsContainer.jsx b/frontend/src/Sidebar/ResultsContainer.jsx
new file mode 100644
index 0000000..1e97309
--- /dev/null
+++ b/frontend/src/Sidebar/ResultsContainer.jsx
@@ -0,0 +1,55 @@
+import { useContext, useState, useEffect } from 'react'
+import { DataContext } from '../Layout'
+import BigButton from './BigButton'
+
+export default function ResultsContainer(){
+ const [ isFetchingData, setIsFetchingData ] = useState(false)
+ const [ progress, setProgress ] = useState(-1)
+ const { data } = useContext(DataContext)
+ useEffect(()=>{
+ data.queue.on('active',()=>{
+ setProgress( 100 * data.queryCountFinished / data.queryCount )
+ })
+ },[])
+ return (
+
+ )
+}
+
+function ProgressBar({percentDone}){
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/Sidebar/index.jsx b/frontend/src/Sidebar/index.jsx
index 642a6d4..7e7ab91 100644
--- a/frontend/src/Sidebar/index.jsx
+++ b/frontend/src/Sidebar/index.jsx
@@ -1,8 +1,9 @@
-import { useContext, useState } from 'react'
+import { useContext } from 'react'
import { DataContext } from '../Layout'
import FactorContainer from './FactorContainer'
import BigButton from './BigButton'
+import ResultsContainer from './ResultsContainer'
import FactorList from './FactorList'
import { restoreStateFromFile } from './restoreStateFromFile.js'
import './sidebar.css'
@@ -29,51 +30,7 @@ export default function SidebarContent(){
×
=
-
-
- )
-}
-
-function Results(){
- const [ results, setResults ] = useState(undefined)
- const [ isFetchingData, setIsFetchingData ] = useState(false)
- const { data } = useContext(DataContext)
- const numResults = data.travelTimeQueries.length
- return (
-
)
}
diff --git a/frontend/src/corridor.js b/frontend/src/corridor.js
index 47ba0f8..431efe4 100644
--- a/frontend/src/corridor.js
+++ b/frontend/src/corridor.js
@@ -29,6 +29,7 @@ export class Corridor extends Factor {
.then( () => {
// notify the layout that the path is ready to be rendered
logActivity('shortest path returned')
+ this.hasUpdated()
} )
}
get intersections(){ return [...this.#intersections.values()] }
diff --git a/frontend/src/dateRange.js b/frontend/src/dateRange.js
index bff9576..96b90ed 100644
--- a/frontend/src/dateRange.js
+++ b/frontend/src/dateRange.js
@@ -26,10 +26,12 @@ export class DateRange extends Factor {
}
setStartDate(inputDate){
this.#startDate = inputDate
+ this.hasUpdated()
return this.#startDate
}
setEndDate(inputDate){
this.#endDate = inputDate
+ this.hasUpdated()
return this.#endDate
}
static dateFormatted(datetime){
diff --git a/frontend/src/days.js b/frontend/src/days.js
index 933f921..b798cc2 100644
--- a/frontend/src/days.js
+++ b/frontend/src/days.js
@@ -30,10 +30,15 @@ export class Days extends Factor {
addDay(number){
if( daylist.map(d=>d.iso).includes(parseInt(number)) ){
this.#days.add(parseInt(number))
+ this.hasUpdated()
}
}
removeDay(number){
- this.#days.delete(parseInt(number))
+ let dayNum = parseInt(number)
+ if(this.#days.has(dayNum)){
+ this.#days.delete(dayNum)
+ this.hasUpdated()
+ }
}
hasDay(number){
return this.#days.has(parseInt(number))
diff --git a/frontend/src/factor.js b/frontend/src/factor.js
index c9d76d9..e46b1d2 100644
--- a/frontend/src/factor.js
+++ b/frontend/src/factor.js
@@ -27,4 +27,8 @@ export class Factor {
render(){ // this will be overwritten but must be implemented
return <>>
}
+ hasUpdated(){
+ // should be called when a factor has been updated
+ this.#dataContext.updateQueries()
+ }
}
\ No newline at end of file
diff --git a/frontend/src/holidayOption.js b/frontend/src/holidayOption.js
index f9c9d35..8a4773d 100644
--- a/frontend/src/holidayOption.js
+++ b/frontend/src/holidayOption.js
@@ -3,7 +3,7 @@ import { Factor } from './factor.js'
export class HolidayOption extends Factor {
#includeHolidays
#dataContext
- constructor(dataContext,includeHolidays){
+ constructor(dataContext, includeHolidays){
super(dataContext)
// store this here too to actually access the holiday data
this.#dataContext = dataContext
diff --git a/frontend/src/spatialData.js b/frontend/src/spatialData.js
index 93d1650..1533af4 100644
--- a/frontend/src/spatialData.js
+++ b/frontend/src/spatialData.js
@@ -53,6 +53,7 @@ export class SpatialData {
let days = new Days(this)
this.#factors.push(days)
days.activate()
+ this.updateQueries() // this is the only factor that starts out complete
return days
}
get segments(){
@@ -63,6 +64,7 @@ export class SpatialData {
}
dropFactor(factor){
this.#factors = this.#factors.filter(f => f != factor)
+ this.updateQueries()
}
deactivateOtherFactors(factor){
this.#factors.forEach( f => {
@@ -70,20 +72,37 @@ export class SpatialData {
} )
}
includeHolidays(){
- this.holidayOptions.forEach(f => this.dropFactor(f))
- this.#factors.push(new HolidayOption(this,true))
+ this.holidayOptions.forEach( factor => {
+ if(!factor.holidaysIncluded) this.dropFactor(factor)
+ } )
+ if(this.holidayOptions.length == 0){
+ this.#factors.push(new HolidayOption(this,true))
+ }
+ this.updateQueries()
}
excludeHolidays(){
- this.holidayOptions.forEach(f => this.dropFactor(f))
- this.#factors.push(new HolidayOption(this,false))
+ this.holidayOptions.forEach( factor => {
+ if(factor.holidaysIncluded) this.dropFactor(factor)
+ } )
+ if(this.holidayOptions.length == 0){
+ this.#factors.push(new HolidayOption(this,false))
+ }
+ this.updateQueries()
}
includeAndExcludeHolidays(){
- this.holidayOptions.forEach(f => this.dropFactor(f))
- this.#factors.push(new HolidayOption(this,true))
- this.#factors.push(new HolidayOption(this,false))
+ console.assert(this.holidayOptions.length == 1)
+ // add a factor for whatever the opposite of the existing one is
+ this.#factors.push(
+ new HolidayOption(
+ this,
+ ! this.holidayOptions[0].holidaysIncluded
+ )
+ )
+ this.updateQueries()
}
- get travelTimeQueries(){
- // is the crossproduct of all complete/valid factors
+ updateQueries(){
+ // this should be run any time the inputs change to keep the list fresh
+ // queries are the crossproduct of all complete/valid factors
const crossProduct = []
this.corridors.filter(c=>c.isComplete).forEach( corridor => {
this.timeRanges.filter(tr=>tr.isComplete).forEach( timeRange => {
@@ -104,17 +123,19 @@ export class SpatialData {
} )
} )
})
- // add new travelTimeRequests
+ // add any new travelTimeRequests
crossProduct.forEach( TTQ => {
if( ! this.#queries.has(TTQ.URI) ){
this.#queries.set(TTQ.URI,TTQ)
}
} )
- // remove old/modified travelTimeRequests
+ // remove any old/modified travelTimeRequests
let currentURIs = new Set(crossProduct.map(TTI=>TTI.URI))
let currentKeys = [...this.#queries.keys()]
currentKeys.filter( key => ! currentURIs.has(key) )
.forEach( key => this.#queries.delete(key) )
+ }
+ get travelTimeQueries(){
return [...this.#queries.values()].sort((a,b)=> a.URI < b.URI ? -1 : 1)
}
fetchAllResults(){
@@ -124,4 +145,15 @@ export class SpatialData {
.map( TTQ => () => TTQ.fetchData() )
)
}
+ get queue(){ return this.#queue }
+ get allQueriesHaveData(){
+ return ( // some queries, all with data
+ this.queryCount > 0
+ && this.queryCount == this.queryCountFinished
+ )
+ }
+ get queryCount(){ return this.#queries.size }
+ get queryCountFinished(){
+ return [...this.#queries.values()].filter(q=>q.hasData).length
+ }
}
diff --git a/frontend/src/timeRange.js b/frontend/src/timeRange.js
index ba0a628..22ef535 100644
--- a/frontend/src/timeRange.js
+++ b/frontend/src/timeRange.js
@@ -45,10 +45,12 @@ export class TimeRange extends Factor {
}
setStartTime(input){
this.#startTime = TimeRange.parseTime(input)
+ this.hasUpdated()
return this.#startTime
}
setEndTime(input){
this.#endTime = TimeRange.parseTime(input)
+ this.hasUpdated()
return this.#endTime
}
static timeFormatted(datetime){