forked from jsnbuchanan/crowd-funder-for-time-pwa
show more succinct info in feed, targeted toward user's visibility
This commit is contained in:
@@ -352,10 +352,54 @@ export function removeVisibleToDids(input: any): any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export function contactForDid(
|
||||||
always returns text, maybe UNNAMED_VISIBLE or UNKNOWN_ENTITY
|
did: string | undefined,
|
||||||
|
contacts: Contact[],
|
||||||
|
): Contact | undefined {
|
||||||
|
return isEmptyOrHiddenDid(did)
|
||||||
|
? undefined
|
||||||
|
: R.find((c) => c.did === did, contacts);
|
||||||
|
}
|
||||||
|
|
||||||
Similar logic is found in endorser-mobile.
|
/**
|
||||||
|
*
|
||||||
|
* Similar logic is found in endorser-mobile.
|
||||||
|
*
|
||||||
|
* @param did
|
||||||
|
* @param activeDid
|
||||||
|
* @param contact
|
||||||
|
* @param allMyDids
|
||||||
|
* @return { known: boolean, displayName: string } where known is true if the display name is some easily-recogizable name, false if it's a generic name like "Someone Anonymous"
|
||||||
|
*/
|
||||||
|
export function didInfoForContact(
|
||||||
|
did: string | undefined,
|
||||||
|
activeDid: string | undefined,
|
||||||
|
contact?: Contact,
|
||||||
|
allMyDids: string[] = [],
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
): { known: boolean; displayName: string } {
|
||||||
|
if (!did) return { displayName: "Someone Anonymous", known: false };
|
||||||
|
if (contact) {
|
||||||
|
return {
|
||||||
|
displayName: contact.name || "Contact With No Name",
|
||||||
|
known: !!contact.name,
|
||||||
|
};
|
||||||
|
} else if (did === activeDid) {
|
||||||
|
return { displayName: "You", known: true };
|
||||||
|
} else {
|
||||||
|
const myId = R.find(R.equals(did), allMyDids);
|
||||||
|
return myId
|
||||||
|
? { displayName: "You (Alt ID)", known: true }
|
||||||
|
: isHiddenDid(did)
|
||||||
|
? { displayName: "Someone Outside Your Network", known: false }
|
||||||
|
: { displayName: "Someone Outside Contacts", known: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
always returns text, maybe something like "unnamed" or "unknown"
|
||||||
|
|
||||||
|
Now that we're using more informational didInfoForContact under the covers, we might want to consolidate.
|
||||||
**/
|
**/
|
||||||
export function didInfo(
|
export function didInfo(
|
||||||
did: string | undefined,
|
did: string | undefined,
|
||||||
@@ -363,19 +407,8 @@ export function didInfo(
|
|||||||
allMyDids: string[],
|
allMyDids: string[],
|
||||||
contacts: Contact[],
|
contacts: Contact[],
|
||||||
): string {
|
): string {
|
||||||
if (!did) return "Someone Anonymous";
|
const contact = contactForDid(did, contacts);
|
||||||
|
return didInfoForContact(did, activeDid, contact, allMyDids).displayName;
|
||||||
const contact = R.find((c) => c.did === did, contacts);
|
|
||||||
if (contact) {
|
|
||||||
return contact.name || "Contact With No Name";
|
|
||||||
} else {
|
|
||||||
const myId = R.find(R.equals(did), allMyDids);
|
|
||||||
return myId
|
|
||||||
? `You${myId !== activeDid ? " (Alt ID)" : ""}`
|
|
||||||
: isHiddenDid(did)
|
|
||||||
? "Someone Outside Your Network"
|
|
||||||
: "Someone Outside Contacts";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,12 +28,6 @@ const enterOrStart = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
|
||||||
path: "/",
|
|
||||||
name: "home",
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "home" */ "../views/HomeView.vue"),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/account",
|
path: "/account",
|
||||||
name: "account",
|
name: "account",
|
||||||
@@ -96,6 +90,12 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "help" */ "../views/HelpView.vue"),
|
import(/* webpackChunkName: "help" */ "../views/HelpView.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
name: "home",
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "home" */ "../views/HomeView.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/help-notifications",
|
path: "/help-notifications",
|
||||||
name: "help-notifications",
|
name: "help-notifications",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Profile"></QuickNav>
|
<QuickNav selected="Profile" />
|
||||||
<TopMessage />
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
|
|||||||
@@ -868,7 +868,7 @@ export default class ContactsView extends Vue {
|
|||||||
(contact.name || "That unnamed person") +
|
(contact.name || "That unnamed person") +
|
||||||
" has been registered.",
|
" has been registered.",
|
||||||
},
|
},
|
||||||
-1,
|
5000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1190,7 +1190,7 @@ export default class ContactsView extends Vue {
|
|||||||
title: "Done",
|
title: "Done",
|
||||||
text: "Successfully logged time to the server.",
|
text: "Successfully logged time to the server.",
|
||||||
},
|
},
|
||||||
-1,
|
5000,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fromDid === identity.did) {
|
if (fromDid === identity.did) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Home"></QuickNav>
|
<QuickNav selected="Home" />
|
||||||
<TopMessage />
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
and go click on that new app.
|
and go click on that new app.
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
v-else-if="userAgentInfo.getBrowser().name.startsWith('Chrome')"
|
v-else-if="userAgentInfo.getBrowser()?.name?.startsWith('Chrome')"
|
||||||
>
|
>
|
||||||
You should see a prompt to install, or you can click on the
|
You should see a prompt to install, or you can click on the
|
||||||
top-right dots
|
top-right dots
|
||||||
@@ -105,14 +105,8 @@
|
|||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<!-- activeDid && isRegistered -->
|
<!-- activeDid && isRegistered -->
|
||||||
<div class="flex justify-between mb-4">
|
<div class="mb-4">
|
||||||
<h2 class="text-xl font-bold">Record Something Given</h2>
|
<h2 class="text-xl font-bold">Record Something Given By:</h2>
|
||||||
<button
|
|
||||||
@click="openGiftedPrompts()"
|
|
||||||
class="block text-center text-md font-bold bg-blue-500 text-white px-2 py-3 rounded-md"
|
|
||||||
>
|
|
||||||
Ideas...
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
|
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
|
||||||
@@ -145,21 +139,20 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Ideally, this button should only be visible when the active account has more than 7 or 11 contacts in their list (we want to limit the grid count above to 8 or 12 accounts to keep it compact) -->
|
<div class="flex justify-between">
|
||||||
<router-link
|
<router-link
|
||||||
v-if="allContacts.length >= 7"
|
v-if="allContacts.length >= 7"
|
||||||
:to="{ name: 'contact-gives' }"
|
:to="{ name: 'contact-gives' }"
|
||||||
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
|
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
|
||||||
>
|
>
|
||||||
Show More Contacts…
|
Choose From All Contacts
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<button
|
||||||
<!-- If there are no contacts, show this instead: -->
|
@click="openGiftedPrompts()"
|
||||||
<div
|
class="block text-center text-md font-bold bg-slate-500 text-white px-2 py-3 rounded-md"
|
||||||
class="rounded border border-dashed border-slate-300 bg-slate-100 px-4 py-3 text-center italic text-slate-500"
|
>
|
||||||
v-if="allContacts.length === 0"
|
Ideas...
|
||||||
>
|
</button>
|
||||||
(No contacts to show.)
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -185,16 +178,24 @@
|
|||||||
class="border-b border-dashed border-slate-400 text-orange-400 pb-2 mb-2 font-bold uppercase text-sm"
|
class="border-b border-dashed border-slate-400 text-orange-400 pb-2 mb-2 font-bold uppercase text-sm"
|
||||||
v-if="record.jwtId == feedLastViewedClaimId"
|
v-if="record.jwtId == feedLastViewedClaimId"
|
||||||
>
|
>
|
||||||
You've seen all the following before
|
You've already seen all the following
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-12">
|
<div class="grid grid-cols-12">
|
||||||
<span class="col-span-11 justify-self-start">
|
<span class="col-span-11 justify-self-start">
|
||||||
<fa
|
<span>
|
||||||
icon="gift"
|
<fa
|
||||||
class="col-span-1 pt-1 pr-2 text-slate-500"
|
v-if="record.giver.known || record.receiver.known"
|
||||||
></fa>
|
icon="circle-user"
|
||||||
{{ this.giveDescription(record) }}
|
class="col-span-1 pt-1 pl-0 pr-3 text-slate-500"
|
||||||
|
/>
|
||||||
|
<fa
|
||||||
|
v-else
|
||||||
|
icon="gift"
|
||||||
|
class="col-span-1 pt-1 pl-3 pr-0 text-slate-500"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
{{ giveDescription(record) }}
|
||||||
<a @click="onClickLoadClaim(record.jwtId)">
|
<a @click="onClickLoadClaim(record.jwtId)">
|
||||||
<fa
|
<fa
|
||||||
icon="circle-info"
|
icon="circle-info"
|
||||||
@@ -243,7 +244,8 @@ import { Contact } from "@/db/tables/contacts";
|
|||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import {
|
import {
|
||||||
didInfo,
|
contactForDid,
|
||||||
|
didInfoForContact,
|
||||||
GiverInputInfo,
|
GiverInputInfo,
|
||||||
GiveServerRecord,
|
GiveServerRecord,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
@@ -257,6 +259,17 @@ interface Notification {
|
|||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GiveRecordWithContactInfo extends GiveServerRecord {
|
||||||
|
giver: {
|
||||||
|
displayName: string;
|
||||||
|
known: boolean;
|
||||||
|
};
|
||||||
|
receiver: {
|
||||||
|
displayName: string;
|
||||||
|
known: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
GiftedDialog,
|
GiftedDialog,
|
||||||
@@ -274,7 +287,7 @@ export default class HomeView extends Vue {
|
|||||||
allContacts: Array<Contact> = [];
|
allContacts: Array<Contact> = [];
|
||||||
allMyDids: Array<string> = [];
|
allMyDids: Array<string> = [];
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
feedData: GiveServerRecord[] = [];
|
feedData: GiveRecordWithContactInfo[] = [];
|
||||||
feedPreviousOldestId?: string;
|
feedPreviousOldestId?: string;
|
||||||
feedLastViewedClaimId?: string;
|
feedLastViewedClaimId?: string;
|
||||||
isCreatingIdentifier = false;
|
isCreatingIdentifier = false;
|
||||||
@@ -388,7 +401,37 @@ export default class HomeView extends Vue {
|
|||||||
await this.retrieveGives(this.apiServer, this.feedPreviousOldestId)
|
await this.retrieveGives(this.apiServer, this.feedPreviousOldestId)
|
||||||
.then(async (results) => {
|
.then(async (results) => {
|
||||||
if (results.data.length > 0) {
|
if (results.data.length > 0) {
|
||||||
this.feedData = this.feedData.concat(results.data);
|
// include the descriptions of the giver and receiver
|
||||||
|
const newFeedData: GiveRecordWithContactInfo = results.data.map(
|
||||||
|
(record: GiveServerRecord) => {
|
||||||
|
// similar code is in endorser-mobile utility.ts
|
||||||
|
// claim.claim happen for some claims wrapped in a Verifiable Credential
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const claim = (record.fullClaim as any).claim || record.fullClaim;
|
||||||
|
// agent.did is for legacy data, before March 2023
|
||||||
|
const giverDid =
|
||||||
|
claim.agent?.identifier || (claim.agent as any)?.did; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
// recipient.did is for legacy data, before March 2023
|
||||||
|
const recipientDid =
|
||||||
|
claim.recipient?.identifier || (claim.recipient as any)?.did; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
return {
|
||||||
|
...record,
|
||||||
|
giver: didInfoForContact(
|
||||||
|
giverDid,
|
||||||
|
this.activeDid,
|
||||||
|
contactForDid(giverDid, this.allContacts),
|
||||||
|
this.allMyDids,
|
||||||
|
),
|
||||||
|
receiver: didInfoForContact(
|
||||||
|
recipientDid,
|
||||||
|
this.activeDid,
|
||||||
|
contactForDid(recipientDid, this.allContacts),
|
||||||
|
this.allMyDids,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.feedData = this.feedData.concat(newFeedData);
|
||||||
this.feedPreviousOldestId =
|
this.feedPreviousOldestId =
|
||||||
results.data[results.data.length - 1].jwtId;
|
results.data[results.data.length - 1].jwtId;
|
||||||
// The following update is only done on the first load.
|
// The following update is only done on the first load.
|
||||||
@@ -449,46 +492,52 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
giveDescription(giveRecord: GiveServerRecord) {
|
giveDescription(giveRecord: GiveRecordWithContactInfo) {
|
||||||
// similar code is in endorser-mobile utility.ts
|
// similar code is in endorser-mobile utility.ts
|
||||||
// claim.claim happen for some claims wrapped in a Verifiable Credential
|
// claim.claim happen for some claims wrapped in a Verifiable Credential
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const claim = (giveRecord.fullClaim as any).claim || giveRecord.fullClaim;
|
const claim = (giveRecord.fullClaim as any).claim || giveRecord.fullClaim;
|
||||||
// agent.did is for legacy data, before March 2023
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const giverDid = claim.agent?.identifier || (claim.agent as any)?.did;
|
|
||||||
const giverInfo = didInfo(
|
|
||||||
giverDid,
|
|
||||||
this.activeDid,
|
|
||||||
this.allMyDids,
|
|
||||||
this.allContacts,
|
|
||||||
);
|
|
||||||
let gaveAmount = claim.object?.amountOfThisGood
|
let gaveAmount = claim.object?.amountOfThisGood
|
||||||
? this.displayAmount(claim.object.unitCode, claim.object.amountOfThisGood)
|
? this.displayAmount(claim.object.unitCode, claim.object.amountOfThisGood)
|
||||||
: "";
|
: "";
|
||||||
if (claim.description) {
|
if (claim.description) {
|
||||||
if (gaveAmount) {
|
if (gaveAmount) {
|
||||||
gaveAmount = gaveAmount + ", and also: ";
|
gaveAmount = " (and " + gaveAmount + ")";
|
||||||
}
|
}
|
||||||
gaveAmount = gaveAmount + claim.description;
|
gaveAmount = claim.description + gaveAmount;
|
||||||
}
|
}
|
||||||
if (!gaveAmount) {
|
if (!gaveAmount) {
|
||||||
gaveAmount = "something not described";
|
gaveAmount = "something not described";
|
||||||
}
|
}
|
||||||
// recipient.did is for legacy data, before March 2023
|
|
||||||
const gaveRecipientId =
|
/**
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
* Only show giver and/or receiver info first if they're named.
|
||||||
claim.recipient?.identifier || (claim.recipient as any)?.did;
|
* - If only giver is named, show "... gave"
|
||||||
const gaveRecipientInfo = gaveRecipientId
|
* - If only receiver is named, show "... received"
|
||||||
? " to " +
|
*/
|
||||||
didInfo(
|
|
||||||
gaveRecipientId,
|
const giverInfo = giveRecord.giver;
|
||||||
this.activeDid,
|
const recipientInfo = giveRecord.receiver;
|
||||||
this.allMyDids,
|
if (giverInfo.known && recipientInfo.known) {
|
||||||
this.allContacts,
|
// both giver and recipient are named
|
||||||
)
|
return `${giverInfo.displayName} gave to ${recipientInfo.displayName}: ${gaveAmount}`;
|
||||||
: "";
|
} else if (giverInfo.known) {
|
||||||
return giverInfo + " gave" + gaveRecipientInfo + ": " + gaveAmount;
|
// giver is named but recipient is not
|
||||||
|
return `${giverInfo.displayName} gave: ${gaveAmount} (to ${recipientInfo.displayName})`;
|
||||||
|
} else if (recipientInfo.known) {
|
||||||
|
// recipient is named but giver is not
|
||||||
|
return `${recipientInfo.displayName} received: ${gaveAmount} (from ${giverInfo.displayName})`;
|
||||||
|
} else {
|
||||||
|
// neither giver nor recipient are named
|
||||||
|
let peopleInfo;
|
||||||
|
if (giverInfo.displayName === recipientInfo.displayName) {
|
||||||
|
peopleInfo = `between two who are ${giverInfo.displayName}`;
|
||||||
|
} else {
|
||||||
|
peopleInfo = `from ${giverInfo.displayName} to ${recipientInfo.displayName}`;
|
||||||
|
}
|
||||||
|
return gaveAmount + " (" + peopleInfo + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickLoadClaim(jwtId: string) {
|
onClickLoadClaim(jwtId: string) {
|
||||||
@@ -506,7 +555,7 @@ export default class HomeView extends Vue {
|
|||||||
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog(giver: GiverInputInfo) {
|
openDialog(giver?: GiverInputInfo) {
|
||||||
(this.$refs.customDialog as GiftedDialog).open(giver);
|
(this.$refs.customDialog as GiftedDialog).open(giver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Profile"></QuickNav>
|
<QuickNav selected="Profile" />
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<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">
|
||||||
<!-- Back -->
|
<!-- Back -->
|
||||||
|
|||||||
Reference in New Issue
Block a user