forked from jsnbuchanan/crowd-funder-for-time-pwa
add requests for map tiles with counts of plans (commented out)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
id="QuickSearch"
|
||||
class="mt-8 mb-4 flex"
|
||||
v-on:keyup.enter="searchSelected()"
|
||||
:style="{ visibility: isSearchVisible ? 'visible' : 'hidden' }"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
@@ -40,38 +41,63 @@
|
||||
@click="
|
||||
projects = [];
|
||||
isLocalActive = true;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = false;
|
||||
isSearchVisible = true;
|
||||
searchLocal();
|
||||
"
|
||||
v-bind:class="computedLocalTabStyleClassNames()"
|
||||
>
|
||||
Nearby
|
||||
<!-- restore when the links don't jump around for different numbers
|
||||
<span
|
||||
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
|
||||
v-if="isLocalActive"
|
||||
>
|
||||
{{ localCount > -1 ? localCount : "?" }}
|
||||
</span>
|
||||
-->
|
||||
</a>
|
||||
</li>
|
||||
<!--
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
isRemoteActive = true;
|
||||
isLocalActive = false;
|
||||
isMappedActive = true;
|
||||
isRemoteActive = false;
|
||||
isSearchVisible = false;
|
||||
"
|
||||
v-bind:class="computedMappedTabStyleClassNames()"
|
||||
>
|
||||
Mapped
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
isLocalActive = false;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = true;
|
||||
isSearchVisible = true;
|
||||
searchAll();
|
||||
"
|
||||
v-bind:class="computedRemoteTabStyleClassNames()"
|
||||
>
|
||||
Anywhere
|
||||
<!-- restore when the links don't jump around for different numbers
|
||||
<span
|
||||
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
|
||||
v-if="isRemoteActive"
|
||||
>
|
||||
{{ remoteCount > -1 ? remoteCount : "?" }}
|
||||
</span>
|
||||
-->
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -89,6 +115,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isMappedActive">
|
||||
<div class="mt-4 h-96 w-5/6 mx-auto">
|
||||
<l-map
|
||||
ref="map"
|
||||
:center="[localCenterLat, localCenterLong]"
|
||||
:zoom="2"
|
||||
@moveend="onMoveEnd"
|
||||
@zoomend="onZoomEnd"
|
||||
@zoomstart="onZoomStart"
|
||||
>
|
||||
<l-tile-layer
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
layer-type="base"
|
||||
name="OpenStreetMap"
|
||||
/>
|
||||
</l-map>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Animation -->
|
||||
<div
|
||||
class="fixed left-6 bottom-24 text-center text-4xl leading-none bg-slate-400 text-white w-14 py-2.5 rounded-full"
|
||||
@@ -102,7 +147,7 @@
|
||||
<span v-if="searchBox"> None found in the selected area. </span>
|
||||
<!-- Otherwise there's no search area selected so we'll just leave the search box for them to click. -->
|
||||
</span>
|
||||
<span v-else>No projects were found with that search.</span>
|
||||
<span v-else-if="isRemoteActive">No projects were found with that search.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -144,7 +189,15 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { Map } from "leaflet";
|
||||
import * as L from "leaflet";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import {
|
||||
LMap,
|
||||
LTileLayer,
|
||||
LMarker,
|
||||
} from "@vue-leaflet/vue-leaflet";
|
||||
import { Router } from "vue-router";
|
||||
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
@@ -158,10 +211,13 @@ import { Contact } from "@/db/tables/contacts";
|
||||
import { BoundingBox } from "@/db/tables/settings";
|
||||
import { didInfo, getHeaders, PlanData } from "@/libs/endorserServer";
|
||||
import { OnboardPage, retrieveAccountDids } from "@/libs/util";
|
||||
import { LocationEvent } from "leaflet";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
InfiniteScroll,
|
||||
LMap,
|
||||
LTileLayer,
|
||||
OnboardingDialog,
|
||||
ProjectIcon,
|
||||
QuickNav,
|
||||
@@ -179,10 +235,16 @@ export default class DiscoverView extends Vue {
|
||||
projects: PlanData[] = [];
|
||||
isLoading = false;
|
||||
isLocalActive = true;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = false;
|
||||
isSearchVisible = true;
|
||||
localCenterLat = 0;
|
||||
localCenterLong = 0;
|
||||
localCount = -1;
|
||||
markers: { [key: string]: L.Marker } = {};
|
||||
remoteCount = -1;
|
||||
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
||||
zoomedSoDoNotMove = false;
|
||||
|
||||
// make this function available to the Vue template
|
||||
didInfo = didInfo;
|
||||
@@ -207,8 +269,13 @@ export default class DiscoverView extends Vue {
|
||||
|
||||
if (this.searchBox) {
|
||||
await this.searchLocal();
|
||||
|
||||
const bbox = this.searchBox.bbox;
|
||||
this.localCenterLat = (bbox.maxLat + bbox.minLat) / 2;
|
||||
this.localCenterLong = (bbox.eastLong + bbox.westLong) / 2;
|
||||
} else {
|
||||
this.isLocalActive = false;
|
||||
this.isMappedActive = false;
|
||||
this.isRemoteActive = true;
|
||||
await this.searchAll();
|
||||
}
|
||||
@@ -222,6 +289,9 @@ export default class DiscoverView extends Vue {
|
||||
public async searchSelected() {
|
||||
if (this.isLocalActive) {
|
||||
await this.searchLocal();
|
||||
} else if (this.isMappedActive) {
|
||||
this.isRemoteActive = true;
|
||||
await this.searchAll();
|
||||
} else {
|
||||
await this.searchAll();
|
||||
}
|
||||
@@ -406,12 +476,62 @@ export default class DiscoverView extends Vue {
|
||||
const latestProject = this.projects[this.projects.length - 1];
|
||||
if (this.isLocalActive) {
|
||||
this.searchLocal(latestProject["rowid"]);
|
||||
} else if (this.isMappedActive) {
|
||||
// don't do anything since mapped items only show a limited number
|
||||
} else if (this.isRemoteActive) {
|
||||
this.searchAll(latestProject["rowid"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onMoveEnd(event: LocationEvent) {
|
||||
if (this.zoomedSoDoNotMove) {
|
||||
this.zoomedSoDoNotMove = false;
|
||||
} else {
|
||||
// not part of a zoom so request tiles
|
||||
await this.requestTiles(event);
|
||||
}
|
||||
}
|
||||
|
||||
async onZoomEnd(event: LocationEvent) {
|
||||
await this.requestTiles(event);
|
||||
}
|
||||
|
||||
onZoomStart(event: LocationEvent) {
|
||||
this.zoomedSoDoNotMove = true;
|
||||
}
|
||||
|
||||
async requestTiles(event: LocationEvent) {
|
||||
const bounds = event.target.getBounds();
|
||||
const queryParams = [
|
||||
"minLocLat=" + bounds?.getSouthWest().lat,
|
||||
"maxLocLat=" + bounds?.getNorthEast().lat,
|
||||
"westLocLon=" + bounds?.getSouthWest().lng,
|
||||
"eastLocLon=" + bounds?.getNorthEast().lng,
|
||||
].join("&");
|
||||
const response = await fetch(this.apiServer + "/api/v2/report/planCountsByBBox?" + queryParams);
|
||||
if (response.status === 200) {
|
||||
const results = await response.json();
|
||||
if (results.data?.tiles?.length > 0) {
|
||||
Object.values(this.markers).forEach(marker => marker.remove());
|
||||
this.markers = {};
|
||||
for (const tile of results.data.tiles) {
|
||||
const pinLat = (tile.minFoundLat + tile.maxFoundLat) / 2;
|
||||
const pinLon = (tile.minFoundLon + tile.maxFoundLon) / 2;
|
||||
const numberIcon = L.divIcon({
|
||||
className: "numbered-marker",
|
||||
html: `<strong>${tile.recordCount}</strong>`,
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12], // coordinates of the tip of the icon relative to the top-left corner of the icon
|
||||
});
|
||||
const marker = L.marker([pinLat, pinLon], { icon: numberIcon });
|
||||
marker.addTo(event.target);
|
||||
this.markers["" + tile.indexLat + "x" + tile.indexLon] = marker;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle clicking on a project entry found in the list
|
||||
* @param id of the project
|
||||
@@ -441,6 +561,24 @@ export default class DiscoverView extends Vue {
|
||||
};
|
||||
}
|
||||
|
||||
public computedMappedTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
"py-3": true,
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isMappedActive,
|
||||
"text-black": this.isMappedActive,
|
||||
"border-black": this.isMappedActive,
|
||||
"font-semibold": this.isMappedActive,
|
||||
|
||||
"text-blue-600": !this.isMappedActive,
|
||||
"border-transparent": !this.isMappedActive,
|
||||
"hover:border-slate-400": !this.isMappedActive,
|
||||
};
|
||||
}
|
||||
|
||||
public computedRemoteTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
@@ -460,3 +598,18 @@ export default class DiscoverView extends Vue {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.numbered-marker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background: blue;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid white;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user