Skip to content

Commit

Permalink
feat: staggered rendering of sites on map (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
spaasis authored Mar 27, 2024
1 parent e4c9c5d commit 9d7da5c
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 19 deletions.
9 changes: 5 additions & 4 deletions src/components/siteSelection/SiteMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import Feature from 'ol/Feature'
import Collection from 'ol/Collection'
import Map from 'ol/Map'
import { SelectEvent } from 'ol/interaction/Select'
import { computed } from 'vue'
interface IHoverData {
name: string
Expand All @@ -77,8 +78,8 @@ export default defineComponent({
const currentHoverFeature = ref(null as IHoverData | null)
const selectedFeatures = ref(new Collection())
const availableFeatures = searchParameterStore.availableSites.map((s) =>
s.createFeature()
const availableFeatures = computed(() =>
searchParameterStore.availableSites.map((s) => s.createFeature())
)
const mapCursor = ref('default')
Expand All @@ -99,7 +100,7 @@ export default defineComponent({
}
const addSelection = (id: number) => {
const feature = availableFeatures.find((f) => f.getId() === id)
const feature = availableFeatures.value.find((f) => f.getId() === id)
selectedFeatures.value.push(feature)
searchParameterStore.selectSite(id)
}
Expand Down Expand Up @@ -127,7 +128,7 @@ export default defineComponent({
dragBox.on('boxend', function () {
// features that intersect the box are selected
const extent = dragBox.getGeometry().getExtent()
const boxFeatures: Feature[] = availableFeatures.filter(
const boxFeatures: Feature[] = availableFeatures.value.filter(
(feature: Feature) => feature.getGeometry()?.intersectsExtent(extent)
)
Expand Down
7 changes: 5 additions & 2 deletions src/components/siteSelection/SiteSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { useSearchParameterStore } from '@/stores/searchParameterStore'
import { useWaterQualityStore } from '@/stores/waterQualityStore'
import { mapStores } from 'pinia'
import { defineComponent } from 'vue'
import { alphabeticCompare } from '@/helpers'
export default defineComponent({
components: {
Expand All @@ -85,13 +86,15 @@ export default defineComponent({
useWaterQualityStore
),
availableSites() {
return this.searchParameterStore.availableSites
return this.searchParameterStore.availableSites.toSorted((s1, s2) =>
alphabeticCompare(s1.name, s2.name)
)
},
selectedSites() {
return this.searchParameterStore.selectedSites
},
unSelectedSites() {
return this.searchParameterStore.availableSites.filter(
return this.availableSites.filter(
(s) => !this.selectedSites.find((ss) => ss.id === s.id)
)
},
Expand Down
15 changes: 8 additions & 7 deletions src/queries/Vesla/getVeslaSitesQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ const query =
'sites?api-version=1.0&\
$select=SiteId,Name,Latitude,Longitude,Depth&'

export async function getVeslaSites(ids: number[]) {
const chunks = chunkArray(ids, 200)
const sites: Site[] = []
//use a generator function to get at most 200 sites at once
//the staggered loading makes the UI more responsive when the user is loading hundreds of sites
export async function* getVeslaSites(ids: number[]) {
const uniqueIds = [...new Set(ids)] //first remove duplicates
const chunks = chunkArray(uniqueIds, 200)
for (const chunk of chunks) {
if (chunk.find((i) => i > 0)) {
const filter =
Expand All @@ -20,8 +22,9 @@ export async function getVeslaSites(ids: number[]) {
longitude: number
depth: number | null
}>
res.map((r) =>
sites.push(

yield res.map(
(r) =>
new Site(
r.siteId,
r.name,
Expand All @@ -30,9 +33,7 @@ export async function getVeslaSites(ids: number[]) {
r.depth,
SiteTypes.Vesla
)
)
)
}
}
return sites
}
13 changes: 7 additions & 6 deletions src/stores/searchParameterStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,20 @@ export const useSearchParameterStore = defineStore('searchParameter', {
async populateAvailableSites(veslaIds: number[]) {
const mainState = useMainStateStore()
this.loading = true
let sites: Site[] = []
this.availableSites = [] //reset previously loaded sites
const siteTypes = mainState.selectedSiteTypes
if (siteTypes.includes(SiteTypes.Vesla)) {
sites = await getVeslaSites(veslaIds)
const veslaSitesGenerator = getVeslaSites(veslaIds)
for await (const siteBatch of veslaSitesGenerator) {
this.availableSites.push(...siteBatch) //assumption: our API calls produce no duplicates
}
}
if (siteTypes.includes(SiteTypes.Mareograph)) {
sites.push(...(await getMareographs()))
this.availableSites.push(...(await getMareographs()))
}
if (siteTypes.includes(SiteTypes.FmiBuoy)) {
sites.push(...(await getBuoys()))
this.availableSites.push(...(await getBuoys()))
}
sites.sort((s1, s2) => alphabeticCompare(s1.name, s2.name))
this.availableSites = sites
this.loading = false
},
},
Expand Down

0 comments on commit 9d7da5c

Please sign in to comment.