Skip to content

Commit

Permalink
Add geographic search
Browse files Browse the repository at this point in the history
  • Loading branch information
jlpereira committed Mar 27, 2023
1 parent 9f32a4b commit fe1d86a
Show file tree
Hide file tree
Showing 15 changed files with 249 additions and 84 deletions.
36 changes: 32 additions & 4 deletions src/components/Map/VMap.global.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ const props = defineProps({
}
})
const emit = defineEmits(['geojson:ready', 'geojson'])
const emit = defineEmits([
'geojson:ready',
'geojson',
'add:layer',
'draw:start'
])
let mapObject
let observeMap
Expand Down Expand Up @@ -129,11 +134,12 @@ onMounted(() => {
drawText: false,
drawCircle: false,
drawPolyline: false,
drawCircleMarker: false,
drawMarker: false,
cutPolygon: false
})
mapObject.on('pm:create', () => {
mapObject.on('pm:create', (e) => {
const fg = L.featureGroup()
drawnItems.eachLayer((layer) => {
Expand All @@ -146,13 +152,33 @@ onMounted(() => {
})
emit('geojson', fg.toGeoJSON())
emit('add:layer', convertGeoJSONWithPointRadius(e.layer))
})
mapObject.on('pm:drawstart', (e) => {
clearDrawLayers()
emit('draw:start', e)
})
}
tiles.osm.addTo(mapObject)
initEvents()
})
function clearDrawLayers() {
drawnItems.clearLayers()
}
function convertGeoJSONWithPointRadius(layer) {
const layerJson = layer.toGeoJSON()
if (typeof layer.getRadius === 'function') {
layerJson.properties.radius = layer.getRadius()
}
return layerJson
}
const resizeMap = () => {
if (!geoJSONGroup) return
const bounds = geoJSONGroup.getBounds()
Expand Down Expand Up @@ -194,6 +220,8 @@ const setGeoJSON = (geojson) => {
emit('geojson:ready', geoJSONGroup)
}
</script>
<style></style>
defineExpose({
clearDrawLayers
})
</script>
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<tbody class="normal-case">
<tbody class="normal-case text-xs">
<slot />
</tbody>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<td class="px-6 py-4">
<td class="px-4 py-4">
<slot />
</td>
</template>
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<th class="px-6 py-3">
<th class="px-4 py-3">
<slot />
</th>
</template>
Expand Down
File renamed without changes.
52 changes: 37 additions & 15 deletions src/modules/otus/components/Panel/PanelMap/PanelMap.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
<template>
<VCard>
<VSpinner v-if="isLoading" />
<VMap
ref="map"
class="h-96 max-h-96"
:zoom="zoom"
:geojson="geojson"
@geojson:ready="isLoading = false"
/>
<div v-if="false" class="text-sm flex flex-row justify-around">
<div class="relative">
<VMap
ref="map"
class="h-96 max-h-96"
:zoom="zoom"
:geojson="geojson"
@geojson:ready="isLoading = false"
/>

<VButton
class="h-6 text-sm absolute right-3 top-3 z-[3000]"
primary
@click="() => (isOtuSearchVisible = true)"
>
Search
</VButton>
<OtuSearch
v-if="isOtuSearchVisible"
:otu="otu"
@close="() => (isOtuSearchVisible = false)"
/>
</div>
<div
v-if="false"
class="text-sm flex flex-row justify-around"
>
<div class="flex flex-row items-center p-2">
<div class="w-3 h-3 bg-map-georeference m-1" />
<span>Georeference</span>
</div>
<div class="flex flex-row items-center p-2 ">
<div class="flex flex-row items-center p-2">
<div class="w-3 h-3 m-1 bg-map-asserted" />
<span>Asserted distribution</span>
</div>
Expand All @@ -22,33 +40,37 @@
</template>

<script setup>
import { ref, watch } from "vue"
import { ref, watch } from 'vue'
import TaxonWorks from '../../../services/TaxonWorks'
import OtuSearch from '../../Search/OtuSearch.vue'
const props = defineProps({
otuId: {
type: [String, Number],
required: true
},
otu: {
type: Object,
required: true
}
})
const zoom = 2
const geojson = ref(undefined)
const isLoading = ref(true)
const isOtuSearchVisible = ref(false)
watch(
() => props.otuId,
(newId, oldId) => {
if(newId === oldId) return
if (newId === oldId) return
isLoading.value = true
TaxonWorks.getOtuDistribution(props.otuId).then(({ data }) => {
geojson.value = data.request_too_large
? null
: data
geojson.value = data.request_too_large ? null : data
})
},
{ immediate: true }
)
</script>
45 changes: 45 additions & 0 deletions src/modules/otus/components/Search/ListResults.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<VTable v-if="list.length">
<VTableHeader>
<VTableHeaderRow>
<VTableHeaderCell
class="w-full flex justify-between box-border items-center"
>
<span>OTU</span>
<IconClose
class="opacity-30 cursor-pointer"
@click="emit('close:table')"
/>
</VTableHeaderCell>
</VTableHeaderRow>
</VTableHeader>
<VTableBody>
<VTableBodyRow
v-for="otu in list"
:key="otu.id"
>
<VTableBodyCell>
<RouterLink
v-html="otu.object_tag"
:to="{ name: 'otus-id', params: { id: otu.id } }"
@click="() => emit('close')"
/>
</VTableBodyCell>
</VTableBodyRow>
</VTableBody>
</VTable>
<div class="text-lg text-center text-base-lighter align-middle p-4">
No OTUs found in this area
</div>
</template>

<script setup>
const props = defineProps({
list: {
type: Array,
default: () => []
}
})
const emit = defineEmits(['close', 'close:table'])
</script>
101 changes: 101 additions & 0 deletions src/modules/otus/components/Search/OtuSearch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<template>
<div
ref="root"
class="w-screen h-screen fixed top-0 left-0 z-[5000]"
>
<VSpinner v-if="isLoading" />
<SearchBar
:label="otu.object_tag"
@search="loadOTUs"
@close="() => emit('close')"
/>
<div class="relative">
<VMap
ref="mapRef"
class="w-screen h-screen"
controls
@draw:start="() => (geojson = {})"
@add:layer="
($event) => {
geoJson = JSON.stringify($event.geometry)
}
"
:zoom="4"
/>
<div
class="h-screen md:w-96 absolute top-0 bg-base-background z-[2000] overflow-auto ease-in-out duration-300 w-full"
:class="{
'md:-right-96 -right-full': !isTableVisible,
'right-0': isTableVisible
}"
>
<ListResults
v-if="isTableVisible"
:list="list"
@close="() => emit('close')"
@close:table="() => (isTableVisible = false)"
/>
</div>
</div>
</div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { makeAPIRequest } from '@/utils/request'
import SearchBar from './SearchBar.vue'
import ListResults from './ListResults.vue'
const props = defineProps({
otu: {
type: Array,
default: () => []
}
})
const root = ref()
const emit = defineEmits(['close'])
const geoJson = ref({})
const mapRef = ref(null)
const list = ref([])
const isTableVisible = ref(false)
const isLoading = ref()
onMounted(() => {
document.addEventListener('keyup', handleKeyboard)
document.body.classList.add('overflow-hidden')
})
onUnmounted(() => {
document.removeEventListener('keyup', handleKeyboard)
document.body.classList.remove('overflow-hidden')
})
const handleKeyboard = ({ key }) => {
switch (key) {
case 'Escape':
emit('close')
break
}
}
function loadOTUs() {
const payload = {
geo_json: geoJson.value,
taxon_name_id: [props.otu.taxon_name_id],
descendants: true
}
isLoading.value = true
makeAPIRequest
.get('/otus.json', { params: payload })
.then(({ data }) => {
list.value = data
isTableVisible.value = true
})
.finally((_) => {
isLoading.value = false
})
}
</script>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div
class="bottom-0 w-screen bg-base-foreground z-[1000] left-0 p-4 text-sm flex flex-row justify-between align-middle box-border"
class="bottom-0 w-screen bg-base-foreground z-[1000] left-0 p-4 text-sm flex flex-row justify-between align-middle box-border border-b border-base-muted"
>
<div>
<VButton
Expand All @@ -9,6 +9,10 @@
>
Search
</VButton>
<span
class="ml-2"
v-html="label"
/>
</div>
<IconClose
class="cursor-pointer"
Expand All @@ -19,4 +23,11 @@

<script setup>
const emit = defineEmits(['search', 'close'])
const props = defineProps({
label: {
type: String,
required: true
}
})
</script>
Loading

0 comments on commit fe1d86a

Please sign in to comment.