forked from jsnbuchanan/crowd-funder-for-time-pwa
Merge changes
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||
<!-- Heading -->
|
||||
<h1 id="ViewHeading" class="text-4xl text-center font-light">
|
||||
Discover Projects
|
||||
Discover Projects & People
|
||||
</h1>
|
||||
|
||||
<OnboardingDialog ref="onboardingDialog" />
|
||||
@@ -15,7 +15,6 @@
|
||||
<div
|
||||
id="QuickSearch"
|
||||
class="mt-8 mb-4 flex"
|
||||
v-on:keyup.enter="searchSelected()"
|
||||
:style="{ visibility: isSearchVisible ? 'visible' : 'hidden' }"
|
||||
>
|
||||
<input
|
||||
@@ -23,16 +22,54 @@
|
||||
v-model="searchTerms"
|
||||
placeholder="Search…"
|
||||
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
|
||||
v-on:keyup.enter="searchSelected()"
|
||||
/>
|
||||
<button
|
||||
@click="searchSelected()"
|
||||
class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400"
|
||||
@click="searchSelected()"
|
||||
>
|
||||
<fa icon="magnifying-glass" class="fa-fw"></fa>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Result Tabs -->
|
||||
<!-- Top Level Selection -->
|
||||
<div class="text-center text-slate-500 border-b border-slate-300 mb-4">
|
||||
<ul class="flex flex-wrap justify-center gap-4 -mb-px">
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isProjectsActive = true;
|
||||
isPeopleActive = false;
|
||||
searchSelected();
|
||||
"
|
||||
v-bind:class="computedProjectsTabStyleClassNames()"
|
||||
>
|
||||
Projects
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isProjectsActive = false;
|
||||
isPeopleActive = true;
|
||||
searchSelected();
|
||||
"
|
||||
v-bind:class="computedPeopleTabStyleClassNames()"
|
||||
>
|
||||
People
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Secondary Tabs -->
|
||||
<div class="text-center text-slate-500 border-b border-slate-300">
|
||||
<ul class="flex flex-wrap justify-center gap-4 -mb-px">
|
||||
<li>
|
||||
@@ -40,9 +77,10 @@
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isLocalActive = true;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = false;
|
||||
isAnywhereActive = false;
|
||||
isSearchVisible = true;
|
||||
tempSearchBox = null;
|
||||
searchLocal();
|
||||
@@ -65,15 +103,17 @@
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isLocalActive = false;
|
||||
isMappedActive = true;
|
||||
isRemoteActive = false;
|
||||
isAnywhereActive = false;
|
||||
isSearchVisible = false;
|
||||
searchTerms = '';
|
||||
tempSearchBox = null;
|
||||
"
|
||||
v-bind:class="computedMappedTabStyleClassNames()"
|
||||
>
|
||||
<!-- search is triggered when map component gets to "ready" state -->
|
||||
Mapped
|
||||
</a>
|
||||
</li>
|
||||
@@ -82,9 +122,10 @@
|
||||
href="#"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isLocalActive = false;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = true;
|
||||
isAnywhereActive = true;
|
||||
isSearchVisible = true;
|
||||
tempSearchBox = null;
|
||||
searchAll();
|
||||
@@ -95,7 +136,7 @@
|
||||
<!-- 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"
|
||||
v-if="isAnywhereActive"
|
||||
>
|
||||
{{ remoteCount > -1 ? remoteCount : "?" }}
|
||||
</span>
|
||||
@@ -143,13 +184,16 @@
|
||||
>
|
||||
<fa icon="spinner" class="fa-spin-pulse"></fa>
|
||||
</div>
|
||||
<div v-else-if="projects.length === 0" class="text-center mt-8">
|
||||
<div
|
||||
v-else-if="projects.length === 0 && userProfiles.length === 0"
|
||||
class="text-center mt-8"
|
||||
>
|
||||
<p class="text-lg text-slate-500">
|
||||
<span v-if="isLocalActive">
|
||||
<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-if="isRemoteActive"
|
||||
<span v-else-if="isAnywhereActive"
|
||||
>No projects were found with that search.</span
|
||||
>
|
||||
</p>
|
||||
@@ -158,35 +202,89 @@
|
||||
<!-- Results List -->
|
||||
<InfiniteScroll @reached-bottom="loadMoreData">
|
||||
<ul id="listDiscoverResults">
|
||||
<li
|
||||
class="border-b border-slate-300"
|
||||
v-for="project in projects"
|
||||
:key="project.handleId"
|
||||
>
|
||||
<a
|
||||
@click="onClickLoadProject(project.handleId)"
|
||||
class="block py-4 flex gap-4 cursor-pointer"
|
||||
<!-- Projects List -->
|
||||
<template v-if="isProjectsActive">
|
||||
<li
|
||||
class="border-b border-slate-300"
|
||||
v-for="project in projects"
|
||||
:key="project.handleId"
|
||||
>
|
||||
<div>
|
||||
<ProjectIcon
|
||||
:entityId="project.handleId"
|
||||
:iconSize="48"
|
||||
:imageUrl="project.image"
|
||||
class="block border border-slate-300 rounded-md max-h-12 max-w-12"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grow">
|
||||
<h2 class="text-base font-semibold">{{ project.name }}</h2>
|
||||
<div class="text-sm">
|
||||
<fa icon="user" class="fa-fw text-slate-400"></fa>
|
||||
{{
|
||||
didInfo(project.issuerDid, activeDid, allMyDids, allContacts)
|
||||
}}
|
||||
<a
|
||||
@click="onClickLoadItem(project.handleId)"
|
||||
class="block py-4 flex gap-4 cursor-pointer"
|
||||
>
|
||||
<div>
|
||||
<ProjectIcon
|
||||
:entityId="project.handleId"
|
||||
:iconSize="48"
|
||||
:imageUrl="project.image"
|
||||
class="block border border-slate-300 rounded-md max-h-12 max-w-12"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<div class="grow">
|
||||
<h2 class="text-base font-semibold">{{ project.name }}</h2>
|
||||
<div class="text-sm">
|
||||
<fa icon="user" class="fa-fw text-slate-400"></fa>
|
||||
{{
|
||||
didInfo(
|
||||
project.issuerDid,
|
||||
activeDid,
|
||||
allMyDids,
|
||||
allContacts,
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<!-- Profiles List -->
|
||||
<template v-else>
|
||||
<li
|
||||
class="border-b border-slate-300"
|
||||
v-for="profile in userProfiles"
|
||||
:key="profile.issuerDid"
|
||||
>
|
||||
<a
|
||||
@click="onClickLoadItem(profile?.rowId || '')"
|
||||
class="block py-4 flex gap-4 cursor-pointer"
|
||||
>
|
||||
<div class="grow">
|
||||
<div class="text-sm">
|
||||
<fa icon="user" class="fa-fw text-slate-400"></fa>
|
||||
{{
|
||||
didInfo(
|
||||
profile.issuerDid,
|
||||
activeDid,
|
||||
allMyDids,
|
||||
allContacts,
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
<p
|
||||
v-if="profile.description"
|
||||
class="mt-1 text-sm text-slate-600"
|
||||
>
|
||||
{{ profile.description }}
|
||||
</p>
|
||||
<div
|
||||
v-if="isAnywhereActive && profile.locLat && profile.locLon"
|
||||
class="mt-1 text-xs text-slate-500"
|
||||
>
|
||||
<fa icon="location-dot" class="fa-fw"></fa>
|
||||
{{
|
||||
(profile.locLat > 0 ? "North" : "South") +
|
||||
" in " +
|
||||
(profile.locLon > 0 ? "Eastern" : "Western") +
|
||||
" Hemisphere"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</InfiniteScroll>
|
||||
</section>
|
||||
@@ -197,7 +295,7 @@ import "leaflet/dist/leaflet.css";
|
||||
import * as L from "leaflet";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { LMap, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
||||
import { Router } from "vue-router";
|
||||
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
|
||||
|
||||
import QuickNav from "../components/QuickNav.vue";
|
||||
import InfiniteScroll from "../components/InfiniteScroll.vue";
|
||||
@@ -220,6 +318,16 @@ import {
|
||||
} from "../libs/endorserServer";
|
||||
import { OnboardPage, retrieveAccountDids } from "../libs/util";
|
||||
|
||||
interface Tile {
|
||||
indexLat: number;
|
||||
indexLon: number;
|
||||
minFoundLat: number;
|
||||
maxFoundLat: number;
|
||||
minFoundLon: number;
|
||||
maxFoundLon: number;
|
||||
recordCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
InfiniteScroll,
|
||||
@@ -233,25 +341,31 @@ import { OnboardPage, retrieveAccountDids } from "../libs/util";
|
||||
})
|
||||
export default class DiscoverView extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
$router!: Router;
|
||||
$route!: RouteLocationNormalizedLoaded;
|
||||
|
||||
activeDid = "";
|
||||
allContacts: Array<Contact> = [];
|
||||
allMyDids: Array<string> = [];
|
||||
apiServer = "";
|
||||
searchTerms = "";
|
||||
projects: PlanData[] = [];
|
||||
isLoading = false;
|
||||
isLocalActive = true;
|
||||
isMappedActive = false;
|
||||
isRemoteActive = false;
|
||||
isAnywhereActive = false;
|
||||
isProjectsActive = true;
|
||||
isPeopleActive = false;
|
||||
isSearchVisible = true;
|
||||
localCenterLat = 0;
|
||||
localCenterLong = 0;
|
||||
localCount = -1;
|
||||
markers: { [key: string]: L.Marker } = {};
|
||||
partnerApiServer = DEFAULT_PARTNER_API_SERVER;
|
||||
projects: PlanData[] = [];
|
||||
remoteCount = -1;
|
||||
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
||||
searchTerms = "";
|
||||
tempSearchBox: BoundingBox | null = null;
|
||||
userProfiles: UserProfile[] = [];
|
||||
zoomedSoDoNotMove = false;
|
||||
|
||||
// make this function available to the Vue template
|
||||
@@ -261,13 +375,15 @@ export default class DiscoverView extends Vue {
|
||||
const settings = await retrieveSettingsForActiveAccount();
|
||||
this.activeDid = (settings.activeDid as string) || "";
|
||||
this.apiServer = (settings.apiServer as string) || "";
|
||||
this.partnerApiServer =
|
||||
(settings.partnerApiServer as string) || this.partnerApiServer;
|
||||
this.searchBox = settings.searchBoxes?.[0] || null;
|
||||
|
||||
this.allContacts = await db.contacts.toArray();
|
||||
|
||||
this.allMyDids = await retrieveAccountDids();
|
||||
|
||||
this.searchTerms = (this.$route as Router).query["searchText"] || "";
|
||||
this.searchTerms = this.$route.query["searchText"]?.toString() || "";
|
||||
|
||||
if (!settings.finishedOnboarding) {
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
||||
@@ -284,7 +400,7 @@ export default class DiscoverView extends Vue {
|
||||
} else {
|
||||
this.isLocalActive = false;
|
||||
this.isMappedActive = false;
|
||||
this.isRemoteActive = true;
|
||||
this.isAnywhereActive = true;
|
||||
await this.searchAll();
|
||||
}
|
||||
}
|
||||
@@ -298,8 +414,8 @@ export default class DiscoverView extends Vue {
|
||||
if (this.isLocalActive) {
|
||||
await this.searchLocal();
|
||||
} else if (this.isMappedActive) {
|
||||
this.isRemoteActive = true;
|
||||
await this.searchAll();
|
||||
const mapRef = this.$refs.projectMap as L.Map;
|
||||
this.requestTiles(mapRef.leafletObject); // not ideal because I found this from experimentation, not documentation
|
||||
} else {
|
||||
await this.searchAll();
|
||||
}
|
||||
@@ -311,6 +427,7 @@ export default class DiscoverView extends Vue {
|
||||
if (!beforeId) {
|
||||
// this was an initial search so clear any previous results
|
||||
this.projects = [];
|
||||
this.userProfiles = [];
|
||||
}
|
||||
|
||||
let queryParams = "claimContents=" + encodeURIComponent(this.searchTerms);
|
||||
@@ -319,62 +436,58 @@ export default class DiscoverView extends Vue {
|
||||
queryParams = queryParams + `&beforeId=${beforeId}`;
|
||||
}
|
||||
|
||||
const endpoint = this.isProjectsActive
|
||||
? this.apiServer + "/api/v2/report/plans"
|
||||
: this.partnerApiServer + "/api/partner/userProfile";
|
||||
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const response = await fetch(
|
||||
this.apiServer + "/api/v2/report/plans?" + queryParams,
|
||||
{
|
||||
method: "GET",
|
||||
headers: await getHeaders(this.activeDid),
|
||||
},
|
||||
);
|
||||
const response = await fetch(endpoint + "?" + queryParams, {
|
||||
method: "GET",
|
||||
headers: await getHeaders(this.activeDid),
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
const details = await response.text();
|
||||
console.error("Problem with full search:", details);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `There was a problem accessing the server.`,
|
||||
},
|
||||
3000,
|
||||
);
|
||||
|
||||
throw details;
|
||||
}
|
||||
|
||||
const results = await response.json();
|
||||
|
||||
const plans: PlanData[] = results.data;
|
||||
if (plans) {
|
||||
for (const plan of plans) {
|
||||
const { name, description, handleId, image, issuerDid, rowid } = plan;
|
||||
this.projects.push({
|
||||
name,
|
||||
description,
|
||||
handleId,
|
||||
image,
|
||||
issuerDid,
|
||||
rowid,
|
||||
});
|
||||
if (this.isProjectsActive) {
|
||||
this.userProfiles = [];
|
||||
const plans: PlanData[] = results.data;
|
||||
if (plans) {
|
||||
this.projects.push(...plans);
|
||||
this.remoteCount = this.projects.length;
|
||||
} else {
|
||||
throw JSON.stringify(results);
|
||||
}
|
||||
this.remoteCount = this.projects.length;
|
||||
} else {
|
||||
throw JSON.stringify(results);
|
||||
this.projects = [];
|
||||
const profiles: UserProfile[] = results.data;
|
||||
if (profiles) {
|
||||
this.userProfiles.push(...profiles);
|
||||
this.remoteCount = this.userProfiles.length;
|
||||
} else {
|
||||
throw JSON.stringify(results);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (e: any) {
|
||||
console.error("Error with feed load:", e);
|
||||
console.error("Error with search all:", e);
|
||||
// this sometimes gives different information
|
||||
console.error("Error with feed load (error added): " + e);
|
||||
console.error("Error with search all (error added): " + e);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: e.userMessage || "There was a problem retrieving projects.",
|
||||
title: "Error Searching",
|
||||
text:
|
||||
e.userMessage ||
|
||||
"There was a problem retrieving " +
|
||||
(this.isProjectsActive ? "projects" : "profiles") +
|
||||
".",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
@@ -392,12 +505,14 @@ export default class DiscoverView extends Vue {
|
||||
|
||||
if (!searchBox) {
|
||||
this.projects = [];
|
||||
this.userProfiles = [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (!beforeId) {
|
||||
// this was an initial search so clear any previous results
|
||||
this.projects = [];
|
||||
this.userProfiles = [];
|
||||
}
|
||||
|
||||
const claimContents =
|
||||
@@ -407,70 +522,64 @@ export default class DiscoverView extends Vue {
|
||||
claimContents,
|
||||
"minLocLat=" + searchBox.minLat,
|
||||
"maxLocLat=" + searchBox.maxLat,
|
||||
"westLocLon=" + searchBox.westLong,
|
||||
"eastLocLon=" + searchBox.eastLong,
|
||||
"minLocLon=" + searchBox.westLong,
|
||||
"maxLocLon=" + searchBox.eastLong,
|
||||
].join("&");
|
||||
|
||||
if (beforeId) {
|
||||
queryParams = queryParams + `&beforeId=${beforeId}`;
|
||||
}
|
||||
|
||||
const endpoint = this.isProjectsActive
|
||||
? this.apiServer + "/api/v2/report/plansByLocation"
|
||||
: this.partnerApiServer + "/api/partner/userProfile";
|
||||
|
||||
try {
|
||||
this.isLoading = true;
|
||||
const response = await fetch(
|
||||
this.apiServer + "/api/v2/report/plansByLocation?" + queryParams,
|
||||
{
|
||||
method: "GET",
|
||||
headers: await getHeaders(this.activeDid),
|
||||
},
|
||||
);
|
||||
const response = await fetch(endpoint + "?" + queryParams, {
|
||||
method: "GET",
|
||||
headers: await getHeaders(this.activeDid),
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
const details = await response.text();
|
||||
console.error("Problem with nearby search:", details);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: "There was a problem accessing the server.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
throw await response.text();
|
||||
throw details;
|
||||
}
|
||||
|
||||
const results = await response.json();
|
||||
|
||||
if (results.data) {
|
||||
if (beforeId) {
|
||||
const plans: PlanData[] = results.data;
|
||||
for (const plan of plans) {
|
||||
const { name, description, handleId, issuerDid, rowid } = plan;
|
||||
this.projects.push({
|
||||
name,
|
||||
description,
|
||||
handleId,
|
||||
issuerDid,
|
||||
rowid,
|
||||
});
|
||||
}
|
||||
if (this.isProjectsActive) {
|
||||
this.userProfiles = [];
|
||||
const plans: PlanData[] = results.data;
|
||||
if (plans) {
|
||||
this.projects.push(...plans);
|
||||
this.localCount = this.projects.length;
|
||||
} else {
|
||||
this.projects = results.data;
|
||||
throw JSON.stringify(results);
|
||||
}
|
||||
this.localCount = this.projects.length;
|
||||
} else {
|
||||
throw JSON.stringify(results);
|
||||
this.projects = [];
|
||||
const profiles: UserProfile[] = results.data;
|
||||
if (profiles) {
|
||||
this.userProfiles.push(...profiles);
|
||||
this.localCount = this.userProfiles.length;
|
||||
} else {
|
||||
throw JSON.stringify(results);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (e: any) {
|
||||
console.error("Error with feed load:", e);
|
||||
console.error("Error with search local:", e);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: e.userMessage || "There was a problem retrieving projects.",
|
||||
text:
|
||||
e.userMessage ||
|
||||
"There was a problem retrieving " +
|
||||
(this.isProjectsActive ? "projects" : "profiles") +
|
||||
".",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
@@ -484,26 +593,38 @@ export default class DiscoverView extends Vue {
|
||||
* @param payload is the flag from the InfiniteScroll indicating if it should load
|
||||
**/
|
||||
async loadMoreData(payload: boolean) {
|
||||
if (this.projects.length > 0 && payload) {
|
||||
const latestProject = this.projects[this.projects.length - 1];
|
||||
if (this.isLocalActive) {
|
||||
this.searchLocal(latestProject["rowid"]);
|
||||
} else if (this.isMappedActive) {
|
||||
this.searchLocal(latestProject["rowid"]);
|
||||
} else if (this.isRemoteActive) {
|
||||
this.searchAll(latestProject["rowid"]);
|
||||
if (payload) {
|
||||
if (this.isProjectsActive && this.projects.length > 0) {
|
||||
const latestProject = this.projects[this.projects.length - 1];
|
||||
if (this.isLocalActive || this.isMappedActive) {
|
||||
this.searchLocal(latestProject.rowId);
|
||||
} else if (this.isAnywhereActive) {
|
||||
this.searchAll(latestProject.rowId);
|
||||
}
|
||||
} else if (this.isPeopleActive && this.userProfiles.length > 0) {
|
||||
const latestProfile = this.userProfiles[this.userProfiles.length - 1];
|
||||
if (this.isLocalActive || this.isMappedActive) {
|
||||
this.searchLocal(latestProfile.rowId || "");
|
||||
} else if (this.isAnywhereActive) {
|
||||
this.searchAll(latestProfile.rowId || "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearMarkers() {
|
||||
Object.values(this.markers).forEach((marker) => marker.remove());
|
||||
this.markers = {};
|
||||
}
|
||||
|
||||
async onMapReady(map: L.Map) {
|
||||
// doing this here instead of the l-map element avoids a recentering after the first drag
|
||||
// doing this here instead of on the l-map element avoids a recentering after a drag then zoom at startup
|
||||
map.setView([this.localCenterLat, this.localCenterLong], 2);
|
||||
this.requestTiles(map);
|
||||
}
|
||||
|
||||
// Tried but failed to use other vue-leaflet methods update:zoom and update:bounds
|
||||
// To access the from this.$refs, use this.$refs.projectMap.mapObject
|
||||
// To access the from this.$refs, use this.$refs.projectMap.leafletObject (or maybe mapObject)
|
||||
|
||||
onMoveStart(/* event: L.LocationEvent */) {
|
||||
// don't remove markers because they follow the map when moving (and the experience is jarring)
|
||||
@@ -521,8 +642,7 @@ export default class DiscoverView extends Vue {
|
||||
|
||||
onZoomStart(/* event: L.LocationEvent */) {
|
||||
// remove markers because otherwise they jump around at zoom end
|
||||
Object.values(this.markers).forEach((marker) => marker.remove());
|
||||
this.markers = {};
|
||||
this.clearMarkers();
|
||||
|
||||
this.zoomedSoDoNotMove = true;
|
||||
}
|
||||
@@ -540,15 +660,15 @@ export default class DiscoverView extends Vue {
|
||||
"westLocLon=" + bounds?.getSouthWest().lng,
|
||||
"eastLocLon=" + bounds?.getNorthEast().lng,
|
||||
].join("&");
|
||||
const response = await fetch(
|
||||
this.apiServer + "/api/v2/report/planCountsByBBox?" + queryParams,
|
||||
);
|
||||
const endpoint = this.isProjectsActive
|
||||
? this.apiServer + "/api/v2/report/planCountsByBBox"
|
||||
: this.partnerApiServer + "/api/partner/userProfileCountsByBBox";
|
||||
const response = await fetch(endpoint + "?" + queryParams);
|
||||
if (response.status === 200) {
|
||||
Object.values(this.markers).forEach((marker) => marker.remove());
|
||||
this.markers = {};
|
||||
this.clearMarkers();
|
||||
const results = await response.json();
|
||||
if (results.data?.tiles?.length > 0) {
|
||||
for (const tile of results.data.tiles) {
|
||||
for (const tile: Tile of results.data.tiles) {
|
||||
const pinLat = (tile.minFoundLat + tile.maxFoundLat) / 2;
|
||||
const pinLon = (tile.minFoundLon + tile.maxFoundLon) / 2;
|
||||
const numberIcon = L.divIcon({
|
||||
@@ -569,10 +689,22 @@ export default class DiscoverView extends Vue {
|
||||
};
|
||||
this.searchLocal();
|
||||
});
|
||||
this.markers["" + tile.indexLat + "X" + tile.indexLon] = marker;
|
||||
this.markers[
|
||||
"" +
|
||||
tile.indexLat +
|
||||
"X" +
|
||||
tile.indexLon +
|
||||
"_" +
|
||||
tile.minFoundLat +
|
||||
"X" +
|
||||
tile.minFoundLon +
|
||||
"-" +
|
||||
tile.maxFoundLat +
|
||||
"X" +
|
||||
tile.maxFoundLon
|
||||
] = marker;
|
||||
}
|
||||
}
|
||||
await this.searchLocal();
|
||||
} else {
|
||||
throw {
|
||||
message: "Got an error loading projects on the map.",
|
||||
@@ -601,14 +733,16 @@ export default class DiscoverView extends Vue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle clicking on a project entry found in the list
|
||||
* @param id of the project
|
||||
* Handle clicking on a project or profile entry found in the list
|
||||
* @param id of the project or profile
|
||||
**/
|
||||
onClickLoadProject(id: string) {
|
||||
onClickLoadItem(id: string) {
|
||||
const route = {
|
||||
path: "/project/" + encodeURIComponent(id),
|
||||
path: this.isProjectsActive
|
||||
? "/project/" + encodeURIComponent(id)
|
||||
: "/userProfile/" + encodeURIComponent(id),
|
||||
};
|
||||
(this.$router as Router).push(route);
|
||||
this.$router.push(route);
|
||||
}
|
||||
|
||||
public computedLocalTabStyleClassNames() {
|
||||
@@ -654,14 +788,50 @@ export default class DiscoverView extends Vue {
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isRemoteActive,
|
||||
"text-black": this.isRemoteActive,
|
||||
"border-black": this.isRemoteActive,
|
||||
"font-semibold": this.isRemoteActive,
|
||||
active: this.isAnywhereActive,
|
||||
"text-black": this.isAnywhereActive,
|
||||
"border-black": this.isAnywhereActive,
|
||||
"font-semibold": this.isAnywhereActive,
|
||||
|
||||
"text-blue-600": !this.isRemoteActive,
|
||||
"border-transparent": !this.isRemoteActive,
|
||||
"hover:border-slate-400": !this.isRemoteActive,
|
||||
"text-blue-600": !this.isAnywhereActive,
|
||||
"border-transparent": !this.isAnywhereActive,
|
||||
"hover:border-slate-400": !this.isAnywhereActive,
|
||||
};
|
||||
}
|
||||
|
||||
public computedProjectsTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
"py-3": true,
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isProjectsActive,
|
||||
"text-black": this.isProjectsActive,
|
||||
"border-black": this.isProjectsActive,
|
||||
"font-semibold": this.isProjectsActive,
|
||||
|
||||
"text-blue-600": !this.isProjectsActive,
|
||||
"border-transparent": !this.isProjectsActive,
|
||||
"hover:border-slate-400": !this.isProjectsActive,
|
||||
};
|
||||
}
|
||||
|
||||
public computedPeopleTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
"py-3": true,
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isPeopleActive,
|
||||
"text-black": this.isPeopleActive,
|
||||
"border-black": this.isPeopleActive,
|
||||
"font-semibold": this.isPeopleActive,
|
||||
|
||||
"text-blue-600": !this.isPeopleActive,
|
||||
"border-transparent": !this.isPeopleActive,
|
||||
"hover:border-slate-400": !this.isPeopleActive,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user