Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"leaflet": "^1.9.4",
"leaflet-draw": "^1.0.2",
"leaflet-easybutton": "^2.4.0",
"leaflet-groupedlayercontrol": "^0.6.1",
"leaflet-iconmaterial": "^1.1.0",
"leaflet.markercluster": "^1.5.3",
"papaparse": "^5.4.1",
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,17 @@ const alertStore = useAlertStore()
let showMobileNavigation = ref(false)
const paths = [
{
attrs: { to: '/' },
label: 'Map'
attrs: { to: '/hydrologic_processes' },
label: 'Hydrologic Processes'
},
// {
// attrs: { to: "/api" },
// label: "API",
// },
{
attrs: { to: '/perceptual_models' },
label: 'Perceptual Models'
},
{
attrs: { to: '/about' },
label: 'About'
Expand Down
206 changes: 2 additions & 204 deletions frontend/src/components/TheLeafletMap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import L from 'leaflet'
import 'leaflet-draw'
import 'leaflet.markercluster'
import { storeToRefs } from 'pinia'
import * as esriLeaflet from 'esri-leaflet'
import { onMounted, onUpdated } from 'vue'
import { useMapStore } from '@/stores/map'
Expand All @@ -21,24 +20,13 @@ import 'leaflet-draw/dist/leaflet.draw.css'
import 'leaflet.markercluster/dist/MarkerCluster.css'
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'

const emit = defineEmits(['onFilter'])

const mapStore = useMapStore()
const {
mapLoaded,
userTouchedFilter,
currentFilteredData,
selectedSpatialZones,
selectedTemporalZones,
selectedProcesses,
searchTerm
} = storeToRefs(mapStore)

onUpdated(() => {
mapStore.leaflet.invalidateSize()
})

onMounted(async () => {
onMounted(() => {
mapStore.leaflet = L.map('mapContainer', { minZoom: 2 }).setView([0, 11], 2)
mapStore.layerGroup = new L.LayerGroup()
mapStore.layerGroup.addTo(mapStore.leaflet)
Expand Down Expand Up @@ -77,198 +65,8 @@ onMounted(async () => {
Esri_WorldImagery.addTo(mapStore.leaflet)
Esri_Hydro_Reference_Overlay.addTo(mapStore.leaflet)

await mapStore.fetchPerceptualModelsGeojson()
const bounds = L.latLngBounds(mapStore.allAvailableCoordinates)
mapStore.leaflet.setMaxBounds(bounds)

const mixed = {
'Perceptual Models': mapStore.layerGroup,
'Esri Hydro Reference Overlay': Esri_Hydro_Reference_Overlay
}
L.control.layers(baselayers, mixed).addTo(mapStore.leaflet)

const drawnItems = new L.FeatureGroup()
mapStore.drawnItems = drawnItems
mapStore.leaflet.addLayer(drawnItems)
drawnItems.setZIndex(1000)

let currentRectangle = null

L.Control.RectangleToggle = L.Control.extend({
options: { position: 'topleft' },
onAdd: function () {
const container = L.DomUtil.create(
'div',
'leaflet-bar leaflet-control leaflet-control-custom draw-toggle-btn'
)
updateDrawButton(container)
let drawer = null
L.DomEvent.on(container, 'click', () => {
if (currentRectangle || drawer) {
drawnItems.clearLayers()
currentRectangle = null
mapStore.filterFeatures(
(feature) => {
if (feature.geometry.type === 'Point') {
const [lng, lat] = feature.geometry.coordinates
return currentRectangle.getBounds().contains([lat, lng])
}
return false
},
'remove',
'rectangle'
)
userTouchedFilter.value = false
emit('onFilter', {
selectedSpatialZones,
selectedTemporalZones,
selectedProcesses,
searchTerm,
filteredFeatures: currentFilteredData.value
})
updateDrawButton(container)
} else {
const drawer = new L.Draw.Rectangle(mapStore.leaflet, {
shapeOptions: {
color: '#3388ff',
weight: 2,
opacity: 0.8,
fillOpacity: 0.3
},
showArea: false
})
drawer.enable()
currentRectangle = {}
updateDrawButton(container)

const drawHandler = (e) => {
mapStore.leaflet.off(L.Draw.Event.CREATED, drawHandler)
drawnItems.clearLayers()
currentRectangle = e.layer
currentRectangle.feature = {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [
currentRectangle.getLatLngs()[0].map((latLng) => [latLng.lng, latLng.lat])
]
},
properties: {}
}
drawnItems.addLayer(currentRectangle)
mapStore.leaflet.fitBounds(currentRectangle.getBounds())

mapStore.filterFeatures(
(feature) => {
if (feature.geometry.type === 'Point') {
const [lng, lat] = feature.geometry.coordinates
return currentRectangle.getBounds().contains([lat, lng])
}
return false
},
'add',
'rectangle'
)

userTouchedFilter.value = true
emit('onFilter', {
selectedSpatialZones,
selectedTemporalZones,
selectedProcesses,
searchTerm,
filteredFeatures: currentFilteredData.value
})

updateDrawButton(container)
}

mapStore.leaflet.on(L.Draw.Event.CREATED, drawHandler)
mapStore.leaflet.once('draw:drawstop', () => {
// If no rectangle was drawn, reset the toggle state
if (!drawnItems.getLayers().length) {
currentRectangle = null
updateDrawButton(container)
mapStore.leaflet.off(L.Draw.Event.CREATED, drawHandler)
}
})
}
})

return container
}
})
mapStore.leaflet.addControl(new L.Control.RectangleToggle())

function updateDrawButton(container) {
if (currentRectangle) {
container.innerHTML = '<span class="material-icons">close</span>'
container.style.background = 'white'
container.title = 'Clear box'
} else {
container.style.backgroundImage = "url('/DrawIcon.ico')"
container.innerHTML = ''
container.title = 'Draw a box'
}
container.style.backgroundRepeat = 'no-repeat'
container.style.backgroundSize = '60% 60%'
container.style.backgroundPosition = 'center'
container.style.borderRadius = '4px'
container.style.width = '34px'
container.style.height = '34px'
container.style.cursor = 'pointer'
container.style.display = 'flex'
container.style.alignItems = 'center'
container.style.justifyContent = 'center'
}
L.drawLocal.draw.handlers.rectangle.tooltip.start = 'Click and drag to draw a box'
L.Control.ClearFilters = L.Control.extend({
options: { position: 'topleft' },
onAdd: function () {
const container = L.DomUtil.create(
'div',
'leaflet-bar leaflet-control leaflet-control-custom'
)
container.title = 'Reset Filters'

container.style.backgroundImage = "url('/ClearFilter.ico')"
container.style.backgroundRepeat = 'no-repeat'
container.style.backgroundSize = '60% 60%'
container.style.backgroundColor = 'white'
container.style.backgroundPosition = 'center'
container.style.borderRadius = '4px'
container.style.width = '34px'
container.style.height = '34px'
container.style.cursor = 'pointer'
container.style.display = 'flex'
container.style.alignItems = 'center'
container.style.justifyContent = 'center'

L.DomEvent.on(container, 'click', () => {
mapStore.clearAllFilters()
emit('onFilter', {
selectedSpatialZones,
selectedTemporalZones,
selectedProcesses,
searchTerm,
filteredFeatures: currentFilteredData.value
})
})

return container
}
})
mapStore.leaflet.addControl(new L.Control.ClearFilters())

mapStore.leaflet.on('click', function (e) {
mapClick(e)
})

mapLoaded.value = true
L.control.layers(baselayers).addTo(mapStore.leaflet)
})

async function mapClick() {
return
}
</script>

<style scoped>
Expand Down
13 changes: 11 additions & 2 deletions frontend/src/router/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import MapView from '../views/MapView.vue'
import PerceptualView from '../views/PerceptualView.vue'
import ApiView from '../views/ApiView.vue'

const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
name: 'map',
path: '/hydrologic_processes',
name: 'Hydrologic Processes',
component: MapView,
meta: {
showMap: true
}
},
{
path: '/perceptual_models',
name: 'Perceptual Models',
component: PerceptualView,
meta: {
showMap: true
}
},
{
path: '/about',
name: 'about',
Expand Down
Loading