add discovery of people's profiles, and update profile endpoints for latest server version
This commit is contained in:
@@ -13,14 +13,14 @@ export type BoundingBox = {
|
|||||||
*/
|
*/
|
||||||
export type Settings = {
|
export type Settings = {
|
||||||
// default entry is keyed with MASTER_SETTINGS_KEY; other entries are linked to an account with account ID
|
// default entry is keyed with MASTER_SETTINGS_KEY; other entries are linked to an account with account ID
|
||||||
id?: number; // this is only blank on input, when the database assigns it
|
id?: number; // this is erased for all those entries that are keyed with accountDid
|
||||||
|
|
||||||
// if supplied, this settings record overrides the master record when the user switches to this account
|
// if supplied, this settings record overrides the master record when the user switches to this account
|
||||||
accountDid?: string; // not used in the MASTER_SETTINGS_KEY entry
|
accountDid?: string; // not used in the MASTER_SETTINGS_KEY entry
|
||||||
// active Decentralized ID
|
// active Decentralized ID
|
||||||
activeDid?: string; // only used in the MASTER_SETTINGS_KEY entry
|
activeDid?: string; // only used in the MASTER_SETTINGS_KEY entry
|
||||||
|
|
||||||
apiServer?: string; // API server URL
|
apiServer: string; // API server URL
|
||||||
|
|
||||||
filterFeedByNearby?: boolean; // filter by nearby
|
filterFeedByNearby?: boolean; // filter by nearby
|
||||||
filterFeedByVisible?: boolean; // filter by visible users ie. anyone not hidden
|
filterFeedByVisible?: boolean; // filter by visible users ie. anyone not hidden
|
||||||
@@ -29,7 +29,7 @@ export type Settings = {
|
|||||||
firstName?: string; // user's full name, may be null if unwanted for a particular account
|
firstName?: string; // user's full name, may be null if unwanted for a particular account
|
||||||
hideRegisterPromptOnNewContact?: boolean;
|
hideRegisterPromptOnNewContact?: boolean;
|
||||||
isRegistered?: boolean;
|
isRegistered?: boolean;
|
||||||
imageServer?: string;
|
// imageServer?: string; // if we want to allow modification then we should make image functionality optional -- or at least customizable
|
||||||
lastName?: string; // deprecated - put all names in firstName
|
lastName?: string; // deprecated - put all names in firstName
|
||||||
|
|
||||||
lastAckedOfferToUserJwtId?: string; // the last JWT ID for offer-to-user that they've acknowledged seeing
|
lastAckedOfferToUserJwtId?: string; // the last JWT ID for offer-to-user that they've acknowledged seeing
|
||||||
|
|||||||
@@ -191,13 +191,9 @@ export interface PlanVerifiableCredential extends GenericVerifiableCredential {
|
|||||||
* Represents data about a project
|
* Represents data about a project
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* We should use PlanSummaryRecord instead.
|
* We should use PlanSummaryRecord instead, adding rowid to it.
|
||||||
**/
|
**/
|
||||||
export interface PlanData {
|
export interface PlanData {
|
||||||
/**
|
|
||||||
* Name of the project
|
|
||||||
**/
|
|
||||||
name: string;
|
|
||||||
/**
|
/**
|
||||||
* Description of the project
|
* Description of the project
|
||||||
**/
|
**/
|
||||||
@@ -211,6 +207,10 @@ export interface PlanData {
|
|||||||
* The DID of the issuer
|
* The DID of the issuer
|
||||||
*/
|
*/
|
||||||
issuerDid: string;
|
issuerDid: string;
|
||||||
|
/**
|
||||||
|
* Name of the project
|
||||||
|
**/
|
||||||
|
name: string;
|
||||||
/**
|
/**
|
||||||
* The identifier of the project -- different from jwtId, needs to be fixed
|
* The identifier of the project -- different from jwtId, needs to be fixed
|
||||||
**/
|
**/
|
||||||
|
|||||||
7
src/libs/partnerServer.ts
Normal file
7
src/libs/partnerServer.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export interface UserProfile {
|
||||||
|
description: string;
|
||||||
|
locLat?: number;
|
||||||
|
locLon?: number;
|
||||||
|
issuerDid: string;
|
||||||
|
rowid?: string;
|
||||||
|
}
|
||||||
@@ -82,13 +82,12 @@
|
|||||||
<div v-else class="text-center">
|
<div v-else class="text-center">
|
||||||
<div class @click="openImageDialog()">
|
<div class @click="openImageDialog()">
|
||||||
<fa
|
<fa
|
||||||
icon="camera"
|
icon="image-portrait"
|
||||||
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-l"
|
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-l"
|
||||||
/>
|
/>
|
||||||
<fa
|
<fa
|
||||||
icon="image-portrait"
|
icon="camera"
|
||||||
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-r"
|
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-r"
|
||||||
@click="openImageDialog()"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -250,16 +249,15 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
id="sectionSearchLocation"
|
id="sectionSearchLocation"
|
||||||
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
class="flex justify-between bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
||||||
>
|
>
|
||||||
<!-- label -->
|
<!-- label -->
|
||||||
<div class="mb-2 font-bold">Location for Searches</div>
|
<span class="mb-2 font-bold">Location for Searches</span>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'search-area' }"
|
:to="{ name: 'search-area' }"
|
||||||
class="block w-full text-center text-m bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2 mt-6"
|
class="text-m bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2"
|
||||||
>
|
>
|
||||||
Set Search Area…
|
{{ isSearchAreasSet ? "Change" : "Set" }} Search Area…
|
||||||
<!-- If already set, change button label to "Change Search Area" -->
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -285,10 +283,7 @@
|
|||||||
:class="{ 'bg-slate-100': loadingProfile || savingProfile }"
|
:class="{ 'bg-slate-100': loadingProfile || savingProfile }"
|
||||||
></textarea>
|
></textarea>
|
||||||
|
|
||||||
<div
|
<div class="flex items-center mb-4" @click="toggleUserProfileLocation">
|
||||||
class="flex items-center mb-4"
|
|
||||||
@click="toggleUserProfileLocation"
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
@@ -680,7 +675,7 @@
|
|||||||
<h2 class="text-slate-500 text-sm font-bold mb-2">
|
<h2 class="text-slate-500 text-sm font-bold mb-2">
|
||||||
Notification Push Server
|
Notification Push Server
|
||||||
</h2>
|
</h2>
|
||||||
<div id="sectionNotificationPushServer" class="px-3 py-4">
|
<div class="px-3 py-4">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="block w-full rounded border border-slate-400 px-3 py-2"
|
class="block w-full rounded border border-slate-400 px-3 py-2"
|
||||||
@@ -757,7 +752,7 @@
|
|||||||
{{ DEFAULT_PARTNER_API_SERVER }}
|
{{ DEFAULT_PARTNER_API_SERVER }}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div id="sectionImageServerURL" class="mt-2">
|
<div class="mt-2">
|
||||||
<span class="text-slate-500 text-sm font-bold">Image Server URL</span>
|
<span class="text-slate-500 text-sm font-bold">Image Server URL</span>
|
||||||
|
|
||||||
<span class="text-sm">{{ DEFAULT_IMAGE_API_SERVER }}</span>
|
<span class="text-sm">{{ DEFAULT_IMAGE_API_SERVER }}</span>
|
||||||
@@ -930,6 +925,7 @@ import {
|
|||||||
DIRECT_PUSH_TITLE,
|
DIRECT_PUSH_TITLE,
|
||||||
retrieveAccountMetadata,
|
retrieveAccountMetadata,
|
||||||
} from "@/libs/util";
|
} from "@/libs/util";
|
||||||
|
import { UserProfile } from "@/libs/partnerServer";
|
||||||
|
|
||||||
const inputImportFileNameRef = ref<Blob>();
|
const inputImportFileNameRef = ref<Blob>();
|
||||||
|
|
||||||
@@ -964,9 +960,9 @@ export default class AccountViewView extends Vue {
|
|||||||
givenName = "";
|
givenName = "";
|
||||||
hideRegisterPromptOnNewContact = false;
|
hideRegisterPromptOnNewContact = false;
|
||||||
imageLimits: ImageRateLimits | null = null;
|
imageLimits: ImageRateLimits | null = null;
|
||||||
imageServer = "";
|
|
||||||
includeUserProfileLocation = false;
|
includeUserProfileLocation = false;
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
|
isSearchAreasSet = false;
|
||||||
limitsMessage = "";
|
limitsMessage = "";
|
||||||
loadingLimits = false;
|
loadingLimits = false;
|
||||||
loadingProfile = true;
|
loadingProfile = true;
|
||||||
@@ -975,8 +971,8 @@ export default class AccountViewView extends Vue {
|
|||||||
notifyingReminder = false;
|
notifyingReminder = false;
|
||||||
notifyingReminderMessage = "";
|
notifyingReminderMessage = "";
|
||||||
notifyingReminderTime = "";
|
notifyingReminderTime = "";
|
||||||
partnerApiServer = "";
|
partnerApiServer = DEFAULT_PARTNER_API_SERVER;
|
||||||
partnerApiServerInput = "";
|
partnerApiServerInput = DEFAULT_PARTNER_API_SERVER;
|
||||||
passkeyExpirationDescription = "";
|
passkeyExpirationDescription = "";
|
||||||
passkeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
passkeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
||||||
previousPasskeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
previousPasskeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
||||||
@@ -997,8 +993,8 @@ export default class AccountViewView extends Vue {
|
|||||||
subscription: PushSubscription | null = null;
|
subscription: PushSubscription | null = null;
|
||||||
warnIfProdServer = false;
|
warnIfProdServer = false;
|
||||||
warnIfTestServer = false;
|
warnIfTestServer = false;
|
||||||
webPushServer = "";
|
webPushServer = DEFAULT_PUSH_SERVER;
|
||||||
webPushServerInput = "";
|
webPushServerInput = DEFAULT_PUSH_SERVER;
|
||||||
userProfileDesc = "";
|
userProfileDesc = "";
|
||||||
userProfileLatitude = 0;
|
userProfileLatitude = 0;
|
||||||
userProfileLongitude = 0;
|
userProfileLongitude = 0;
|
||||||
@@ -1021,7 +1017,7 @@ export default class AccountViewView extends Vue {
|
|||||||
try {
|
try {
|
||||||
const headers = await getHeaders(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
const response = await this.axios.get(
|
const response = await this.axios.get(
|
||||||
this.apiServer + "/api/partner/user-profile/" + this.activeDid,
|
this.apiServer + "/api/partner/userProfile/" + this.activeDid,
|
||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -1127,14 +1123,15 @@ export default class AccountViewView extends Vue {
|
|||||||
this.hideRegisterPromptOnNewContact =
|
this.hideRegisterPromptOnNewContact =
|
||||||
!!settings.hideRegisterPromptOnNewContact;
|
!!settings.hideRegisterPromptOnNewContact;
|
||||||
this.isRegistered = !!settings?.isRegistered;
|
this.isRegistered = !!settings?.isRegistered;
|
||||||
this.imageServer = settings.imageServer || "";
|
this.isSearchAreasSet = !!settings.searchBoxes;
|
||||||
this.notifyingNewActivity = !!settings.notifyingNewActivityTime;
|
this.notifyingNewActivity = !!settings.notifyingNewActivityTime;
|
||||||
this.notifyingNewActivityTime = settings.notifyingNewActivityTime || "";
|
this.notifyingNewActivityTime = settings.notifyingNewActivityTime || "";
|
||||||
this.notifyingReminder = !!settings.notifyingReminderTime;
|
this.notifyingReminder = !!settings.notifyingReminderTime;
|
||||||
this.notifyingReminderMessage = settings.notifyingReminderMessage || "";
|
this.notifyingReminderMessage = settings.notifyingReminderMessage || "";
|
||||||
this.notifyingReminderTime = settings.notifyingReminderTime || "";
|
this.notifyingReminderTime = settings.notifyingReminderTime || "";
|
||||||
this.partnerApiServer = settings.partnerApiServer || "";
|
this.partnerApiServer = settings.partnerApiServer || this.partnerApiServer;
|
||||||
this.partnerApiServerInput = settings.partnerApiServer || "";
|
this.partnerApiServerInput =
|
||||||
|
settings.partnerApiServer || this.partnerApiServerInput;
|
||||||
this.profileImageUrl = settings.profileImageUrl;
|
this.profileImageUrl = settings.profileImageUrl;
|
||||||
this.showContactGives = !!settings.showContactGivesInline;
|
this.showContactGives = !!settings.showContactGivesInline;
|
||||||
this.passkeyExpirationMinutes =
|
this.passkeyExpirationMinutes =
|
||||||
@@ -1144,8 +1141,8 @@ export default class AccountViewView extends Vue {
|
|||||||
this.showShortcutBvc = !!settings.showShortcutBvc;
|
this.showShortcutBvc = !!settings.showShortcutBvc;
|
||||||
this.warnIfProdServer = !!settings.warnIfProdServer;
|
this.warnIfProdServer = !!settings.warnIfProdServer;
|
||||||
this.warnIfTestServer = !!settings.warnIfTestServer;
|
this.warnIfTestServer = !!settings.warnIfTestServer;
|
||||||
this.webPushServer = settings.webPushServer || "";
|
this.webPushServer = settings.webPushServer || this.webPushServer;
|
||||||
this.webPushServerInput = settings.webPushServer || "";
|
this.webPushServerInput = settings.webPushServer || this.webPushServerInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
// call fn, copy text to the clipboard, then redo fn after 2 seconds
|
// call fn, copy text to the clipboard, then redo fn after 2 seconds
|
||||||
@@ -1793,15 +1790,25 @@ export default class AccountViewView extends Vue {
|
|||||||
this.savingProfile = true;
|
this.savingProfile = true;
|
||||||
try {
|
try {
|
||||||
const headers = await getHeaders(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
const payload = {
|
const payload: UserProfile = {
|
||||||
description: this.userProfileDesc,
|
description: this.userProfileDesc,
|
||||||
};
|
};
|
||||||
if (this.userProfileLatitude && this.userProfileLongitude) {
|
if (this.userProfileLatitude && this.userProfileLongitude) {
|
||||||
payload.locLat = this.userProfileLatitude;
|
payload.locLat = this.userProfileLatitude;
|
||||||
payload.locLon = this.userProfileLongitude;
|
payload.locLon = this.userProfileLongitude;
|
||||||
|
} else if (this.includeUserProfileLocation) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "toast",
|
||||||
|
title: "",
|
||||||
|
text: "No profile location is saved.",
|
||||||
|
},
|
||||||
|
3000,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const response = await this.axios.post(
|
const response = await this.axios.post(
|
||||||
this.apiServer + "/api/partner/user-profile",
|
this.apiServer + "/api/partner/userProfile",
|
||||||
payload,
|
payload,
|
||||||
{ headers },
|
{ headers },
|
||||||
);
|
);
|
||||||
@@ -1845,6 +1852,7 @@ export default class AccountViewView extends Vue {
|
|||||||
if (!this.includeUserProfileLocation) {
|
if (!this.includeUserProfileLocation) {
|
||||||
this.userProfileLatitude = 0;
|
this.userProfileLatitude = 0;
|
||||||
this.userProfileLongitude = 0;
|
this.userProfileLongitude = 0;
|
||||||
|
this.zoom = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1866,6 +1874,7 @@ export default class AccountViewView extends Vue {
|
|||||||
eraseLatLong() {
|
eraseLatLong() {
|
||||||
this.userProfileLatitude = 0;
|
this.userProfileLatitude = 0;
|
||||||
this.userProfileLongitude = 0;
|
this.userProfileLongitude = 0;
|
||||||
|
this.zoom = 2;
|
||||||
this.includeUserProfileLocation = false;
|
this.includeUserProfileLocation = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||||
<!-- Heading -->
|
<!-- Heading -->
|
||||||
<h1 id="ViewHeading" class="text-4xl text-center font-light">
|
<h1 id="ViewHeading" class="text-4xl text-center font-light">
|
||||||
Discover Projects
|
Discover Projects & People
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<OnboardingDialog ref="onboardingDialog" />
|
<OnboardingDialog ref="onboardingDialog" />
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
<div
|
<div
|
||||||
id="QuickSearch"
|
id="QuickSearch"
|
||||||
class="mt-8 mb-4 flex"
|
class="mt-8 mb-4 flex"
|
||||||
v-on:keyup.enter="searchSelected()"
|
|
||||||
:style="{ visibility: isSearchVisible ? 'visible' : 'hidden' }"
|
:style="{ visibility: isSearchVisible ? 'visible' : 'hidden' }"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -23,16 +22,54 @@
|
|||||||
v-model="searchTerms"
|
v-model="searchTerms"
|
||||||
placeholder="Search…"
|
placeholder="Search…"
|
||||||
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
|
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
|
||||||
|
v-on:keyup.enter="searchSelected()"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@click="searchSelected()"
|
|
||||||
class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400"
|
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>
|
<fa icon="magnifying-glass" class="fa-fw"></fa>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Result Tabs -->
|
<!-- 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">
|
<div class="text-center text-slate-500 border-b border-slate-300">
|
||||||
<ul class="flex flex-wrap justify-center gap-4 -mb-px">
|
<ul class="flex flex-wrap justify-center gap-4 -mb-px">
|
||||||
<li>
|
<li>
|
||||||
@@ -40,9 +77,10 @@
|
|||||||
href="#"
|
href="#"
|
||||||
@click="
|
@click="
|
||||||
projects = [];
|
projects = [];
|
||||||
|
userProfiles = [];
|
||||||
isLocalActive = true;
|
isLocalActive = true;
|
||||||
isMappedActive = false;
|
isMappedActive = false;
|
||||||
isRemoteActive = false;
|
isAnywhereActive = false;
|
||||||
isSearchVisible = true;
|
isSearchVisible = true;
|
||||||
tempSearchBox = null;
|
tempSearchBox = null;
|
||||||
searchLocal();
|
searchLocal();
|
||||||
@@ -65,15 +103,17 @@
|
|||||||
href="#"
|
href="#"
|
||||||
@click="
|
@click="
|
||||||
projects = [];
|
projects = [];
|
||||||
|
userProfiles = [];
|
||||||
isLocalActive = false;
|
isLocalActive = false;
|
||||||
isMappedActive = true;
|
isMappedActive = true;
|
||||||
isRemoteActive = false;
|
isAnywhereActive = false;
|
||||||
isSearchVisible = false;
|
isSearchVisible = false;
|
||||||
searchTerms = '';
|
searchTerms = '';
|
||||||
tempSearchBox = null;
|
tempSearchBox = null;
|
||||||
"
|
"
|
||||||
v-bind:class="computedMappedTabStyleClassNames()"
|
v-bind:class="computedMappedTabStyleClassNames()"
|
||||||
>
|
>
|
||||||
|
<!-- search is triggered when map component gets to "ready" state -->
|
||||||
Mapped
|
Mapped
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -82,9 +122,10 @@
|
|||||||
href="#"
|
href="#"
|
||||||
@click="
|
@click="
|
||||||
projects = [];
|
projects = [];
|
||||||
|
userProfiles = [];
|
||||||
isLocalActive = false;
|
isLocalActive = false;
|
||||||
isMappedActive = false;
|
isMappedActive = false;
|
||||||
isRemoteActive = true;
|
isAnywhereActive = true;
|
||||||
isSearchVisible = true;
|
isSearchVisible = true;
|
||||||
tempSearchBox = null;
|
tempSearchBox = null;
|
||||||
searchAll();
|
searchAll();
|
||||||
@@ -95,7 +136,7 @@
|
|||||||
<!-- restore when the links don't jump around for different numbers
|
<!-- restore when the links don't jump around for different numbers
|
||||||
<span
|
<span
|
||||||
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
|
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 : "?" }}
|
{{ remoteCount > -1 ? remoteCount : "?" }}
|
||||||
</span>
|
</span>
|
||||||
@@ -143,13 +184,13 @@
|
|||||||
>
|
>
|
||||||
<fa icon="spinner" class="fa-spin-pulse"></fa>
|
<fa icon="spinner" class="fa-spin-pulse"></fa>
|
||||||
</div>
|
</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">
|
<p class="text-lg text-slate-500">
|
||||||
<span v-if="isLocalActive">
|
<span v-if="isLocalActive">
|
||||||
<span v-if="searchBox"> None found in the selected area. </span>
|
<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. -->
|
<!-- Otherwise there's no search area selected so we'll just leave the search box for them to click. -->
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="isRemoteActive"
|
<span v-else-if="isAnywhereActive"
|
||||||
>No projects were found with that search.</span
|
>No projects were found with that search.</span
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
@@ -158,35 +199,68 @@
|
|||||||
<!-- Results List -->
|
<!-- Results List -->
|
||||||
<InfiniteScroll @reached-bottom="loadMoreData">
|
<InfiniteScroll @reached-bottom="loadMoreData">
|
||||||
<ul id="listDiscoverResults">
|
<ul id="listDiscoverResults">
|
||||||
<li
|
<!-- Projects List -->
|
||||||
class="border-b border-slate-300"
|
<template v-if="isProjectsActive">
|
||||||
v-for="project in projects"
|
<li
|
||||||
:key="project.handleId"
|
class="border-b border-slate-300"
|
||||||
>
|
v-for="project in projects"
|
||||||
<a
|
:key="project.handleId"
|
||||||
@click="onClickLoadProject(project.handleId)"
|
|
||||||
class="block py-4 flex gap-4 cursor-pointer"
|
|
||||||
>
|
>
|
||||||
<div>
|
<a
|
||||||
<ProjectIcon
|
@click="onClickLoadItem(project.handleId)"
|
||||||
:entityId="project.handleId"
|
class="block py-4 flex gap-4 cursor-pointer"
|
||||||
:iconSize="48"
|
>
|
||||||
:imageUrl="project.image"
|
<div>
|
||||||
class="block border border-slate-300 rounded-md max-h-12 max-w-12"
|
<ProjectIcon
|
||||||
/>
|
:entityId="project.handleId"
|
||||||
</div>
|
:iconSize="48"
|
||||||
|
:imageUrl="project.image"
|
||||||
<div class="grow">
|
class="block border border-slate-300 rounded-md max-h-12 max-w-12"
|
||||||
<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>
|
||||||
</div>
|
|
||||||
</a>
|
<div class="grow">
|
||||||
</li>
|
<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.issuerDid)"
|
||||||
|
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="profile.locLat && profile.locLon" class="mt-1 text-xs text-slate-500">
|
||||||
|
<fa icon="location-dot" class="fa-fw"></fa>
|
||||||
|
{{ profile.locLat.toFixed(2) }}, {{ profile.locLon.toFixed(2) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
</InfiniteScroll>
|
</InfiniteScroll>
|
||||||
</section>
|
</section>
|
||||||
@@ -197,14 +271,14 @@ import "leaflet/dist/leaflet.css";
|
|||||||
import * as L from "leaflet";
|
import * as L from "leaflet";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { LMap, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
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 QuickNav from "@/components/QuickNav.vue";
|
||||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||||
import ProjectIcon from "@/components/ProjectIcon.vue";
|
import ProjectIcon from "@/components/ProjectIcon.vue";
|
||||||
import OnboardingDialog from "@/components/OnboardingDialog.vue";
|
import OnboardingDialog from "@/components/OnboardingDialog.vue";
|
||||||
import TopMessage from "@/components/TopMessage.vue";
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { NotificationIface } from "@/constants/app";
|
import { DEFAULT_PARTNER_API_SERVER, NotificationIface } from "@/constants/app";
|
||||||
import {
|
import {
|
||||||
db,
|
db,
|
||||||
logConsoleAndDb,
|
logConsoleAndDb,
|
||||||
@@ -218,8 +292,19 @@ import {
|
|||||||
getHeaders,
|
getHeaders,
|
||||||
PlanData,
|
PlanData,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
|
import { UserProfile } from "@/libs/partnerServer";
|
||||||
import { OnboardPage, retrieveAccountDids } from "@/libs/util";
|
import { OnboardPage, retrieveAccountDids } from "@/libs/util";
|
||||||
|
|
||||||
|
interface Tile {
|
||||||
|
indexLat: number;
|
||||||
|
indexLon: number;
|
||||||
|
minFoundLat: number;
|
||||||
|
maxFoundLat: number;
|
||||||
|
minFoundLon: number;
|
||||||
|
maxFoundLon: number;
|
||||||
|
recordCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
InfiniteScroll,
|
InfiniteScroll,
|
||||||
@@ -233,25 +318,31 @@ import { OnboardPage, retrieveAccountDids } from "@/libs/util";
|
|||||||
})
|
})
|
||||||
export default class DiscoverView extends Vue {
|
export default class DiscoverView extends Vue {
|
||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
|
$router!: Router;
|
||||||
|
$route!: RouteLocationNormalizedLoaded;
|
||||||
|
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
allContacts: Array<Contact> = [];
|
allContacts: Array<Contact> = [];
|
||||||
allMyDids: Array<string> = [];
|
allMyDids: Array<string> = [];
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
searchTerms = "";
|
|
||||||
projects: PlanData[] = [];
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
isLocalActive = true;
|
isLocalActive = true;
|
||||||
isMappedActive = false;
|
isMappedActive = false;
|
||||||
isRemoteActive = false;
|
isAnywhereActive = false;
|
||||||
|
isProjectsActive = true;
|
||||||
|
isPeopleActive = false;
|
||||||
isSearchVisible = true;
|
isSearchVisible = true;
|
||||||
localCenterLat = 0;
|
localCenterLat = 0;
|
||||||
localCenterLong = 0;
|
localCenterLong = 0;
|
||||||
localCount = -1;
|
localCount = -1;
|
||||||
markers: { [key: string]: L.Marker } = {};
|
markers: { [key: string]: L.Marker } = {};
|
||||||
|
partnerApiServer = DEFAULT_PARTNER_API_SERVER;
|
||||||
|
projects: PlanData[] = [];
|
||||||
remoteCount = -1;
|
remoteCount = -1;
|
||||||
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
||||||
|
searchTerms = "";
|
||||||
tempSearchBox: BoundingBox | null = null;
|
tempSearchBox: BoundingBox | null = null;
|
||||||
|
userProfiles: UserProfile[] = [];
|
||||||
zoomedSoDoNotMove = false;
|
zoomedSoDoNotMove = false;
|
||||||
|
|
||||||
// make this function available to the Vue template
|
// make this function available to the Vue template
|
||||||
@@ -261,13 +352,15 @@ export default class DiscoverView extends Vue {
|
|||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
this.activeDid = (settings.activeDid as string) || "";
|
this.activeDid = (settings.activeDid as string) || "";
|
||||||
this.apiServer = (settings.apiServer as string) || "";
|
this.apiServer = (settings.apiServer as string) || "";
|
||||||
|
this.partnerApiServer =
|
||||||
|
(settings.partnerApiServer as string) || this.partnerApiServer;
|
||||||
this.searchBox = settings.searchBoxes?.[0] || null;
|
this.searchBox = settings.searchBoxes?.[0] || null;
|
||||||
|
|
||||||
this.allContacts = await db.contacts.toArray();
|
this.allContacts = await db.contacts.toArray();
|
||||||
|
|
||||||
this.allMyDids = await retrieveAccountDids();
|
this.allMyDids = await retrieveAccountDids();
|
||||||
|
|
||||||
this.searchTerms = (this.$route as Router).query["searchText"] || "";
|
this.searchTerms = this.$route.query["searchText"]?.toString() || "";
|
||||||
|
|
||||||
if (!settings.finishedOnboarding) {
|
if (!settings.finishedOnboarding) {
|
||||||
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
||||||
@@ -284,7 +377,7 @@ export default class DiscoverView extends Vue {
|
|||||||
} else {
|
} else {
|
||||||
this.isLocalActive = false;
|
this.isLocalActive = false;
|
||||||
this.isMappedActive = false;
|
this.isMappedActive = false;
|
||||||
this.isRemoteActive = true;
|
this.isAnywhereActive = true;
|
||||||
await this.searchAll();
|
await this.searchAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,8 +391,8 @@ export default class DiscoverView extends Vue {
|
|||||||
if (this.isLocalActive) {
|
if (this.isLocalActive) {
|
||||||
await this.searchLocal();
|
await this.searchLocal();
|
||||||
} else if (this.isMappedActive) {
|
} else if (this.isMappedActive) {
|
||||||
this.isRemoteActive = true;
|
const mapRef = this.$refs.projectMap as L.Map;
|
||||||
await this.searchAll();
|
this.requestTiles(mapRef.leafletObject); // not ideal because I found this from experimentation, not documentation
|
||||||
} else {
|
} else {
|
||||||
await this.searchAll();
|
await this.searchAll();
|
||||||
}
|
}
|
||||||
@@ -311,6 +404,7 @@ export default class DiscoverView extends Vue {
|
|||||||
if (!beforeId) {
|
if (!beforeId) {
|
||||||
// this was an initial search so clear any previous results
|
// this was an initial search so clear any previous results
|
||||||
this.projects = [];
|
this.projects = [];
|
||||||
|
this.userProfiles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let queryParams = "claimContents=" + encodeURIComponent(this.searchTerms);
|
let queryParams = "claimContents=" + encodeURIComponent(this.searchTerms);
|
||||||
@@ -319,62 +413,62 @@ export default class DiscoverView extends Vue {
|
|||||||
queryParams = queryParams + `&beforeId=${beforeId}`;
|
queryParams = queryParams + `&beforeId=${beforeId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const endpoint = this.isProjectsActive
|
||||||
|
? this.apiServer + "/api/v2/report/plans"
|
||||||
|
: this.partnerApiServer + "/api/partner/userProfile";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(endpoint + "?" + queryParams, {
|
||||||
this.apiServer + "/api/v2/report/plans?" + queryParams,
|
method: "GET",
|
||||||
{
|
headers: await getHeaders(this.activeDid),
|
||||||
method: "GET",
|
});
|
||||||
headers: await getHeaders(this.activeDid),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
const details = await response.text();
|
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;
|
throw details;
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await response.json();
|
const results = await response.json();
|
||||||
|
|
||||||
const plans: PlanData[] = results.data;
|
if (this.isProjectsActive) {
|
||||||
if (plans) {
|
const plans: PlanData[] = results.data;
|
||||||
for (const plan of plans) {
|
if (plans) {
|
||||||
const { name, description, handleId, image, issuerDid, rowid } = plan;
|
for (const plan of plans) {
|
||||||
this.projects.push({
|
const { name, description, handleId, image, issuerDid, rowid } = plan;
|
||||||
name,
|
this.projects.push({
|
||||||
description,
|
name,
|
||||||
handleId,
|
description,
|
||||||
image,
|
handleId,
|
||||||
issuerDid,
|
image,
|
||||||
rowid,
|
issuerDid,
|
||||||
});
|
rowid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.remoteCount = this.projects.length;
|
||||||
|
} else {
|
||||||
|
throw JSON.stringify(results);
|
||||||
}
|
}
|
||||||
this.remoteCount = this.projects.length;
|
|
||||||
} else {
|
} else {
|
||||||
throw JSON.stringify(results);
|
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
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error("Error with feed load:", e);
|
console.error("Error with search all:", e);
|
||||||
// this sometimes gives different information
|
// 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(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
type: "danger",
|
type: "danger",
|
||||||
title: "Error",
|
title: "Error Searching",
|
||||||
text: e.userMessage || "There was a problem retrieving projects.",
|
text: e.userMessage || "There was a problem retrieving " + (this.isProjectsActive ? "projects" : "profiles") + ".",
|
||||||
},
|
},
|
||||||
5000,
|
5000,
|
||||||
);
|
);
|
||||||
@@ -392,12 +486,14 @@ export default class DiscoverView extends Vue {
|
|||||||
|
|
||||||
if (!searchBox) {
|
if (!searchBox) {
|
||||||
this.projects = [];
|
this.projects = [];
|
||||||
|
this.userProfiles = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!beforeId) {
|
if (!beforeId) {
|
||||||
// this was an initial search so clear any previous results
|
// this was an initial search so clear any previous results
|
||||||
this.projects = [];
|
this.projects = [];
|
||||||
|
this.userProfiles = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const claimContents =
|
const claimContents =
|
||||||
@@ -407,70 +503,71 @@ export default class DiscoverView extends Vue {
|
|||||||
claimContents,
|
claimContents,
|
||||||
"minLocLat=" + searchBox.minLat,
|
"minLocLat=" + searchBox.minLat,
|
||||||
"maxLocLat=" + searchBox.maxLat,
|
"maxLocLat=" + searchBox.maxLat,
|
||||||
"westLocLon=" + searchBox.westLong,
|
"minLocLon=" + searchBox.westLong,
|
||||||
"eastLocLon=" + searchBox.eastLong,
|
"maxLocLon=" + searchBox.eastLong,
|
||||||
].join("&");
|
].join("&");
|
||||||
|
|
||||||
if (beforeId) {
|
if (beforeId) {
|
||||||
queryParams = queryParams + `&beforeId=${beforeId}`;
|
queryParams = queryParams + `&beforeId=${beforeId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const endpoint = this.isProjectsActive
|
||||||
|
? this.apiServer + "/api/v2/report/plansByLocation"
|
||||||
|
: this.partnerApiServer + "/api/partner/userProfile";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const response = await fetch(
|
const response = await fetch(endpoint + "?" + queryParams, {
|
||||||
this.apiServer + "/api/v2/report/plansByLocation?" + queryParams,
|
method: "GET",
|
||||||
{
|
headers: await getHeaders(this.activeDid),
|
||||||
method: "GET",
|
});
|
||||||
headers: await getHeaders(this.activeDid),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
const details = await response.text();
|
const details = await response.text();
|
||||||
console.error("Problem with nearby search:", details);
|
throw details;
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: "There was a problem accessing the server.",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
|
||||||
throw await response.text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await response.json();
|
const results = await response.json();
|
||||||
|
|
||||||
if (results.data) {
|
if (this.isProjectsActive) {
|
||||||
if (beforeId) {
|
if (results.data) {
|
||||||
const plans: PlanData[] = results.data;
|
if (beforeId) {
|
||||||
for (const plan of plans) {
|
const plans: PlanData[] = results.data;
|
||||||
const { name, description, handleId, issuerDid, rowid } = plan;
|
for (const plan of plans) {
|
||||||
this.projects.push({
|
const { name, description, handleId, issuerDid, rowid } = plan;
|
||||||
name,
|
this.projects.push({
|
||||||
description,
|
name,
|
||||||
handleId,
|
description,
|
||||||
issuerDid,
|
handleId,
|
||||||
rowid,
|
issuerDid,
|
||||||
});
|
rowid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.projects = results.data;
|
||||||
}
|
}
|
||||||
|
this.localCount = this.projects.length;
|
||||||
} else {
|
} else {
|
||||||
this.projects = results.data;
|
throw JSON.stringify(results);
|
||||||
}
|
}
|
||||||
this.localCount = this.projects.length;
|
|
||||||
} else {
|
} else {
|
||||||
throw JSON.stringify(results);
|
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
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error("Error with feed load:", e);
|
console.error("Error with search local:", e);
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
group: "alert",
|
group: "alert",
|
||||||
type: "danger",
|
type: "danger",
|
||||||
title: "Error",
|
title: "Error",
|
||||||
text: e.userMessage || "There was a problem retrieving projects.",
|
text: e.userMessage || "There was a problem retrieving " + (this.isProjectsActive ? "projects" : "profiles") + ".",
|
||||||
},
|
},
|
||||||
5000,
|
5000,
|
||||||
);
|
);
|
||||||
@@ -484,14 +581,21 @@ export default class DiscoverView extends Vue {
|
|||||||
* @param payload is the flag from the InfiniteScroll indicating if it should load
|
* @param payload is the flag from the InfiniteScroll indicating if it should load
|
||||||
**/
|
**/
|
||||||
async loadMoreData(payload: boolean) {
|
async loadMoreData(payload: boolean) {
|
||||||
if (this.projects.length > 0 && payload) {
|
if (payload) {
|
||||||
const latestProject = this.projects[this.projects.length - 1];
|
if (this.isProjectsActive && this.projects.length > 0) {
|
||||||
if (this.isLocalActive) {
|
const latestProject = this.projects[this.projects.length - 1];
|
||||||
this.searchLocal(latestProject["rowid"]);
|
if (this.isLocalActive || this.isMappedActive) {
|
||||||
} else if (this.isMappedActive) {
|
this.searchLocal(latestProject.rowid);
|
||||||
this.searchLocal(latestProject["rowid"]);
|
} else if (this.isAnywhereActive) {
|
||||||
} else if (this.isRemoteActive) {
|
this.searchAll(latestProject.rowid);
|
||||||
this.searchAll(latestProject["rowid"]);
|
}
|
||||||
|
} else if (!this.isProjectsActive && 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 || "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,7 +607,7 @@ export default class DiscoverView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tried but failed to use other vue-leaflet methods update:zoom and update:bounds
|
// 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 */) {
|
onMoveStart(/* event: L.LocationEvent */) {
|
||||||
// don't remove markers because they follow the map when moving (and the experience is jarring)
|
// don't remove markers because they follow the map when moving (and the experience is jarring)
|
||||||
@@ -540,9 +644,10 @@ export default class DiscoverView extends Vue {
|
|||||||
"westLocLon=" + bounds?.getSouthWest().lng,
|
"westLocLon=" + bounds?.getSouthWest().lng,
|
||||||
"eastLocLon=" + bounds?.getNorthEast().lng,
|
"eastLocLon=" + bounds?.getNorthEast().lng,
|
||||||
].join("&");
|
].join("&");
|
||||||
const response = await fetch(
|
const endpoint = this.isProjectsActive
|
||||||
this.apiServer + "/api/v2/report/planCountsByBBox?" + queryParams,
|
? this.apiServer + "/api/v2/report/planCountsByBBox"
|
||||||
);
|
: this.partnerApiServer + "/api/partner/userProfileCountsByBBox";
|
||||||
|
const response = await fetch(endpoint + "?" + queryParams);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
Object.values(this.markers).forEach((marker) => marker.remove());
|
Object.values(this.markers).forEach((marker) => marker.remove());
|
||||||
this.markers = {};
|
this.markers = {};
|
||||||
@@ -601,14 +706,16 @@ export default class DiscoverView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle clicking on a project entry found in the list
|
* Handle clicking on a project or profile entry found in the list
|
||||||
* @param id of the project
|
* @param id of the project or profile
|
||||||
**/
|
**/
|
||||||
onClickLoadProject(id: string) {
|
onClickLoadItem(id: string) {
|
||||||
const route = {
|
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() {
|
public computedLocalTabStyleClassNames() {
|
||||||
@@ -654,14 +761,50 @@ export default class DiscoverView extends Vue {
|
|||||||
"rounded-t-lg": true,
|
"rounded-t-lg": true,
|
||||||
"border-b-2": true,
|
"border-b-2": true,
|
||||||
|
|
||||||
active: this.isRemoteActive,
|
active: this.isAnywhereActive,
|
||||||
"text-black": this.isRemoteActive,
|
"text-black": this.isAnywhereActive,
|
||||||
"border-black": this.isRemoteActive,
|
"border-black": this.isAnywhereActive,
|
||||||
"font-semibold": this.isRemoteActive,
|
"font-semibold": this.isAnywhereActive,
|
||||||
|
|
||||||
"text-blue-600": !this.isRemoteActive,
|
"text-blue-600": !this.isAnywhereActive,
|
||||||
"border-transparent": !this.isRemoteActive,
|
"border-transparent": !this.isAnywhereActive,
|
||||||
"hover:border-slate-400": !this.isRemoteActive,
|
"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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,9 @@
|
|||||||
maxlength="5000"
|
maxlength="5000"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="text-xs text-slate-500 italic -mt-3 mb-4">
|
<div class="text-xs text-slate-500 italic -mt-3 mb-4">
|
||||||
If you want to be contacted, be sure to include your contact information.
|
If you want to be contacted, be sure to include your contact information
|
||||||
|
-- just remember that this information is public and saved in a public
|
||||||
|
history.
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-slate-500 italic -mt-3 mb-4">
|
<div class="text-xs text-slate-500 italic -mt-3 mb-4">
|
||||||
{{ fullClaim.description?.length }}/5000 max. characters
|
{{ fullClaim.description?.length }}/5000 max. characters
|
||||||
|
|||||||
Reference in New Issue
Block a user