Compare commits

..

23 Commits

Author SHA1 Message Date
ac4c92d8e8 Merge branch 'master' into update-api-server 2023-08-07 03:13:26 -04:00
937a3cb6c6 Merge pull request 'Minor cleanup' (#54) from seed-backup-view-improvements into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#54
2023-08-07 03:11:23 -04:00
Matthew Aaron Raymer
304985f88d Merge remote-tracking branch 'origin/polish-ui-project-view' 2023-08-07 16:08:48 +08:00
Matthew Aaron Raymer
9a41aff8f0 Merge remote-tracking branch 'origin/jdenticon-entity-photos' 2023-08-07 15:59:47 +08:00
Matthew Aaron Raymer
e19cd980b4 Merging with corrections 2023-08-07 15:54:06 +08:00
194f741984 Merge branch 'master' into seed-backup-view-improvements 2023-08-07 03:11:07 -04:00
b31c0d975c Merge pull request 'fix display of gives on contact screen; adjust give UI for project' (#49) from ui-fix into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#49
2023-08-07 02:42:30 -04:00
f09684d7cd Merge branch 'master' into ui-fix 2023-08-07 02:41:30 -04:00
1767a48a7f Merge pull request 'New notification system + test' (#48) from notiwind-alert into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#48
2023-08-07 02:41:05 -04:00
bf6830a1a8 update URL for API server 2023-08-05 18:20:03 -06:00
Jose Olarte III
fe09f5180d Minor cleanup 2023-08-03 20:12:47 +08:00
Jose Olarte III
4de66b1609 Cleaned up Project view UI 2023-07-28 20:22:03 +08:00
Jose Olarte III
4b87692231 Added jdenticon to more views 2023-07-25 18:41:23 +08:00
Jose Olarte III
503bb1bd93 Added jdenticon to home and contact gives views 2023-07-24 19:32:30 +08:00
Jose Olarte III
9fa3b8be0b Built jdenticon component 2023-07-24 19:32:11 +08:00
3b1a9b9c5b change description since issuer isn't necessarily giver, and add a task 2023-07-23 11:35:03 -06:00
7f48149d6f add some detail for the map pin, plus other refactors 2023-07-20 20:59:53 -06:00
c5b4921583 fix failure to retrieve all totals for gives from me 2023-07-20 20:33:55 -06:00
b28689ad06 walk back edits that were forward-looking but broken 2023-07-20 20:15:17 -06:00
0444b5be32 fix so that contact recipient is also recorded 2023-07-20 20:12:13 -06:00
4866416aae fix didInfo logic, and add to project lists 2023-07-20 19:02:18 -06:00
e48a4ed05b fix to use the real project name, and add creator 2023-07-20 18:35:27 -06:00
87cfead094 fix display of gives on contact screen; adjust give UI for project 2023-07-20 18:22:45 -06:00
16 changed files with 308 additions and 153 deletions

23
package-lock.json generated
View File

@@ -33,6 +33,7 @@
"ethereum-cryptography": "^2.0.0", "ethereum-cryptography": "^2.0.0",
"ethereumjs-util": "^7.1.5", "ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.0.0", "ethr-did-resolver": "^8.0.0",
"jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9", "js-generate-password": "^0.1.9",
"localstorage-slim": "^2.4.0", "localstorage-slim": "^2.4.0",
"luxon": "^3.3.0", "luxon": "^3.3.0",
@@ -12049,6 +12050,14 @@
"resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz",
"integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==" "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w=="
}, },
"node_modules/canvas-renderer": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/canvas-renderer/-/canvas-renderer-2.2.1.tgz",
"integrity": "sha512-RrBgVL5qCEDIXpJ6NrzyRNoTnXxYarqm/cS/W6ERhUJts5UQtt/XPEosGN3rqUkZ4fjBArlnCbsISJ+KCFnIAg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/case-sensitive-paths-webpack-plugin": { "node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", "resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@@ -17798,6 +17807,20 @@
"integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==",
"dev": true "dev": true
}, },
"node_modules/jdenticon": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jdenticon/-/jdenticon-3.2.0.tgz",
"integrity": "sha512-z6Iq3fTODUMSOiR2nNYrqigS6Y0GvdXfyQWrUby7htDHvX7GNEwaWR4hcaL+FmhEgBe08Xkup/BKxXQhDJByPA==",
"dependencies": {
"canvas-renderer": "~2.2.0"
},
"bin": {
"jdenticon": "bin/jdenticon.js"
},
"engines": {
"node": ">=6.4.0"
}
},
"node_modules/jest-environment-node": { "node_modules/jest-environment-node": {
"version": "29.5.0", "version": "29.5.0",
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz",

View File

@@ -33,6 +33,7 @@
"ethereum-cryptography": "^2.0.0", "ethereum-cryptography": "^2.0.0",
"ethereumjs-util": "^7.1.5", "ethereumjs-util": "^7.1.5",
"ethr-did-resolver": "^8.0.0", "ethr-did-resolver": "^8.0.0",
"jdenticon": "^3.2.0",
"js-generate-password": "^0.1.9", "js-generate-password": "^0.1.9",
"localstorage-slim": "^2.4.0", "localstorage-slim": "^2.4.0",
"luxon": "^3.3.0", "luxon": "^3.3.0",

View File

@@ -1,6 +1,8 @@
tasks: tasks:
- 01 add a location for a project via map pin - .2 bug - on contacts view, click on "to" & "from" and nothing happens
- 01 add a location for a project via map pin :
- add with a "location" field containing this: { "geo":{ "@type":"GeoCoordinates", "latitude":40.883944, "longitude":-111.884787 } }
- 04 search by a bounding box for local projects (see API by clicking on "Nearby") - 04 search by a bounding box for local projects (see API by clicking on "Nearby")
- 01 Replace Gifted/Give in ContactsView with GiftedDialog assignee:jose - 01 Replace Gifted/Give in ContactsView with GiftedDialog assignee:jose
- 02 Fix images on projectview - allow choice of image from a pallete of images or a url image. - 02 Fix images on projectview - allow choice of image from a pallete of images or a url image.
@@ -24,6 +26,7 @@ tasks:
- 24 Move to Vite - 24 Move to Vite
- .5 add link to further project / people when a project pays ahead
- .5 add project ID to the URL, to make a project publicly-accessible - .5 add project ID to the URL, to make a project publicly-accessible
- .5 remove edit from project page for projects owned by others - .5 remove edit from project page for projects owned by others
- .5 fix where user 0 sees no txns from user 1 on contacts page but sees them on list page - .5 fix where user 0 sees no txns from user 1 on contacts page but sees them on list page
@@ -32,6 +35,8 @@ tasks:
- .2 on ProjectViewView, show different messages for "to" and "from" sections if none exist - .2 on ProjectViewView, show different messages for "to" and "from" sections if none exist
- .2 fix static icon to the right on project page (Matthew - I've made "Rotary" into issuer?) - .2 fix static icon to the right on project page (Matthew - I've made "Rotary" into issuer?)
- .2 fix rate limit verbiage (with the new one-per-day allowance) assignee:trent - .2 fix rate limit verbiage (with the new one-per-day allowance) assignee:trent
- .2 move 'switch identity' to the advanced section
- .1 remove the logic to exclude beforeId in list of plans after server has commit 26b25af605e715600d4f12b6416ed9fd7142d164
- Discuss whether the remaining tasks are worthwhile before MVP release. - Discuss whether the remaining tasks are worthwhile before MVP release.

View File

@@ -0,0 +1,19 @@
<template>
<div v-html="generateIdenticon()" class="w-fit"></div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-facing-decorator";
import { toSvg } from "jdenticon";
@Component
export default class EntityIcon extends Vue {
@Prop entityId = "";
@Prop iconSize = "";
generateIdenticon() {
const svgString = toSvg(this.entityId, this.iconSize);
return svgString;
}
}
</script>
<style scoped></style>

View File

@@ -4,7 +4,7 @@
export enum AppString { export enum AppString {
APP_NAME = "Kick-Start with Time", APP_NAME = "Kick-Start with Time",
PROD_ENDORSER_API_SERVER = "https://endorser.ch:3000", PROD_ENDORSER_API_SERVER = "https://api.endorser.ch",
TEST_ENDORSER_API_SERVER = "https://test.endorser.ch:8000", TEST_ENDORSER_API_SERVER = "https://test.endorser.ch:8000",
LOCAL_ENDORSER_API_SERVER = "http://localhost:3000", LOCAL_ENDORSER_API_SERVER = "http://localhost:3000",

View File

@@ -82,10 +82,15 @@ export function isHiddenDid(did) {
/** /**
always returns text, maybe UNNAMED_VISIBLE or UNKNOWN_ENTITY always returns text, maybe UNNAMED_VISIBLE or UNKNOWN_ENTITY
**/ **/
export function didInfo(did, activeDid, allMyDids, contacts) { export function didInfo(
const myId: string | undefined = R.find(R.identity, allMyDids); did: string,
activeDid: string,
allMyDids: Array<string>,
contacts: Array<Contact>,
): string {
const myId: string | undefined = R.find(R.equals(did), allMyDids, did);
if (myId) { if (myId) {
return "You" + (myId.did !== activeDid ? " (Alt ID)" : ""); return "You" + (myId !== activeDid ? " (Alt ID)" : "");
} else { } else {
const contact: Contact | undefined = R.find((c) => c.did === did, contacts); const contact: Contact | undefined = R.find((c) => c.did === did, contacts);
if (contact) { if (contact) {
@@ -101,7 +106,7 @@ export function didInfo(did, activeDid, allMyDids, contacts) {
} }
/** /**
* For result, see https://endorser.ch:3000/api-docs/#/claims/post_api_v2_claim * For result, see https://api.endorser.ch/api-docs/#/claims/post_api_v2_claim
* *
* @param identity * @param identity
* @param fromDid may be null * @param fromDid may be null

View File

@@ -4,6 +4,11 @@
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8"> <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Given with {{ contact?.name }} Given with {{ contact?.name }}
</h1> </h1>
<div class="flex justify-around">
<span />
<span class="justify-around">(Only 50 most recent)</span>
<span />
</div>
<!-- Results List --> <!-- Results List -->
<div> <div>
@@ -170,7 +175,7 @@ export default class ContactsView extends Vue {
encodeURIComponent(identity.did) + encodeURIComponent(identity.did) +
"&recipientDid=" + "&recipientDid=" +
encodeURIComponent(contact.did); encodeURIComponent(contact.did);
const headers = this.getHeaders(identity); const headers = await this.getHeaders(identity);
const resp = await this.axios.get(url, { headers }); const resp = await this.axios.get(url, { headers });
if (resp.status === 200) { if (resp.status === 200) {
result = resp.data.data; result = resp.data.data;

View File

@@ -24,8 +24,12 @@
<ul class="border-t border-slate-300"> <ul class="border-t border-slate-300">
<li class="border-b border-slate-300 py-3"> <li class="border-b border-slate-300 py-3">
<h2 class="text-base flex gap-4 items-center"> <h2 class="text-base flex gap-4 items-center">
<span class="grow italic" <span class="grow italic text-slate-500"
><fa icon="question-circle" class="fa-fw fa-xl text-slate-400"></fa> ><EntityIcon
entityId="Anonymous"
:iconSize="32"
class="opacity-50 inline-block align-middle border border-dashed border-slate-400 bg-slate-200 rounded-md mr-1"
></EntityIcon>
Anonymous Anonymous
</span> </span>
<span class="text-right"> <span class="text-right">
@@ -46,7 +50,11 @@
> >
<h2 class="text-base flex gap-4 items-center"> <h2 class="text-base flex gap-4 items-center">
<span class="grow font-semibold" <span class="grow font-semibold"
><fa icon="user" class="fa-fw fa-xl text-slate-400"></fa> ><EntityIcon
:entityId="contact.did"
:iconSize="32"
class="inline-block align-middle border border-slate-300 rounded-md mr-1"
></EntityIcon>
{{ contact.name || "(no name)" }} {{ contact.name || "(no name)" }}
</span> </span>
<span class="text-right"> <span class="text-right">
@@ -87,9 +95,10 @@ import { Account } from "@/db/tables/accounts";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import EntityIcon from "@/components/EntityIcon";
@Component({ @Component({
components: { GiftedDialog, AlertMessage, QuickNav }, components: { GiftedDialog, AlertMessage, QuickNav, EntityIcon },
}) })
export default class HomeView extends Vue { export default class HomeView extends Vue {
activeDid = ""; activeDid = "";

View File

@@ -66,18 +66,27 @@
: "Unconfirmed" : "Unconfirmed"
}} }}
</button> </button>
<br />
(Only hours shown)
<br />
(Only recent shown)
</div> </div>
</div> </div>
<!-- Results List --> <!-- Results List -->
<ul v-if="contacts.length > 0" class="border-t border-slate-300"> <ul v-if="contacts.length > 0" class="border-t border-slate-300">
<li <li
class="border-b border-slate-300 py-4" class="border-b border-slate-300 pt-2.5 pb-4"
v-for="contact in contacts" v-for="contact in contacts"
:key="contact.did" :key="contact.did"
> >
<div class="grow overflow-hidden"> <div class="grow overflow-hidden">
<h2 class="text-base font-semibold"> <h2 class="text-base font-semibold">
<EntityIcon
:entityId="contact.did"
:iconSize="24"
class="inline-block align-text-bottom border border-slate-300 rounded"
></EntityIcon>
{{ contact.name || "(no name)" }} {{ contact.name || "(no name)" }}
</h2> </h2>
<div class="text-sm truncate">{{ contact.did }}</div> <div class="text-sm truncate">{{ contact.did }}</div>
@@ -135,9 +144,12 @@
<fa icon="trash-can" class="fa-fw" /> <fa icon="trash-can" class="fa-fw" />
</button> </button>
<div v-if="!showGiveNumbers" class="ml-auto flex gap-1.5"> <div
v-if="showGiveNumbers && contact.did != activeDid"
class="ml-auto flex gap-1.5"
>
<button <button
class="text-sm uppercase bg-blue-600 text-white px-2 py-1.5 rounded-md" class="text-sm bg-blue-600 text-white px-2 py-1.5 rounded-l-md"
@click="onClickAddGive(activeDid, contact.did)" @click="onClickAddGive(activeDid, contact.did)"
title="givenByMeDescriptions[contact.did]" title="givenByMeDescriptions[contact.did]"
> >
@@ -152,11 +164,11 @@
: (givenByMeUnconfirmed[contact.did] || 0) : (givenByMeUnconfirmed[contact.did] || 0)
/* eslint-enable prettier/prettier */ /* eslint-enable prettier/prettier */
}} }}
<fa icon="plus" class="fa-fw" /> <fa icon="plus" />
</button> </button>
<button <button
class="text-sm uppercase bg-blue-600 text-white px-2 py-1.5 rounded-md" class="text-sm bg-blue-600 text-white px-2 py-1.5 rounded-r-md -ml-1.5 border-l border-blue-400"
@click="onClickAddGive(contact.did, activeDid)" @click="onClickAddGive(contact.did, activeDid)"
title="givenToMeDescriptions[contact.did]" title="givenToMeDescriptions[contact.did]"
> >
@@ -171,7 +183,7 @@
: (givenToMeUnconfirmed[contact.did] || 0) : (givenToMeUnconfirmed[contact.did] || 0)
/* eslint-enable prettier/prettier */ /* eslint-enable prettier/prettier */
}} }}
<fa icon="plus" class="fa-fw" /> <fa icon="plus" />
</button> </button>
<router-link <router-link
@@ -214,12 +226,13 @@ import {
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import EntityIcon from "@/components/EntityIcon";
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const Buffer = require("buffer/").Buffer; const Buffer = require("buffer/").Buffer;
@Component({ @Component({
components: { AlertMessage, QuickNav }, components: { AlertMessage, QuickNav, EntityIcon },
}) })
export default class ContactsView extends Vue { export default class ContactsView extends Vue {
activeDid = ""; activeDid = "";
@@ -294,20 +307,27 @@ export default class ContactsView extends Vue {
} }
async loadGives() { async loadGives() {
const handleResponse = (resp, descriptions, confirmed, unconfirmed) => { const handleResponse = (
resp,
descriptions,
confirmed,
unconfirmed,
useRecipient,
) => {
if (resp.status === 200) { if (resp.status === 200) {
const allData = resp.data.data; const allData = resp.data.data;
for (const give of allData) { for (const give of allData) {
const otherDid = useRecipient ? give.recipientDid : give.agentDid;
if (give.unit === "HUR") { if (give.unit === "HUR") {
if (give.amountConfirmed) { if (give.amountConfirmed) {
const prevAmount = confirmed[give.agentDid] || 0; const prevAmount = confirmed[otherDid] || 0;
confirmed[give.agentDid] = prevAmount + give.amount; confirmed[otherDid] = prevAmount + give.amount;
} else { } else {
const prevAmount = unconfirmed[give.agentDid] || 0; const prevAmount = unconfirmed[otherDid] || 0;
unconfirmed[give.agentDid] = prevAmount + give.amount; unconfirmed[otherDid] = prevAmount + give.amount;
} }
if (!descriptions[give.agentDid] && give.description) { if (!descriptions[otherDid] && give.description) {
descriptions[give.agentDid] = give.description; descriptions[otherDid] = give.description;
} }
} }
} }
@@ -334,17 +354,15 @@ export default class ContactsView extends Vue {
}; };
try { try {
const { headers, identity } = await this.getHeadersAndIdentity( const { headers } = await this.getHeadersAndIdentity(this.activeDid);
this.activeDid,
);
const givenByUrl = const givenByUrl =
this.apiServer + this.apiServer +
"/api/v2/report/gives?agentDid=" + "/api/v2/report/gives?agentDid=" +
encodeURIComponent(identity.did); encodeURIComponent(this.activeDid);
const givenToUrl = const givenToUrl =
this.apiServer + this.apiServer +
"/api/v2/report/gives?recipientDid=" + "/api/v2/report/gives?recipientDid=" +
encodeURIComponent(identity.did); encodeURIComponent(this.activeDid);
const [givenByMeResp, givenToMeResp] = await Promise.all([ const [givenByMeResp, givenToMeResp] = await Promise.all([
this.axios.get(givenByUrl, { headers }), this.axios.get(givenByUrl, { headers }),
@@ -359,6 +377,7 @@ export default class ContactsView extends Vue {
givenByMeDescriptions, givenByMeDescriptions,
givenByMeConfirmed, givenByMeConfirmed,
givenByMeUnconfirmed, givenByMeUnconfirmed,
true,
); );
this.givenByMeDescriptions = givenByMeDescriptions; this.givenByMeDescriptions = givenByMeDescriptions;
this.givenByMeConfirmed = givenByMeConfirmed; this.givenByMeConfirmed = givenByMeConfirmed;
@@ -372,6 +391,7 @@ export default class ContactsView extends Vue {
givenToMeDescriptions, givenToMeDescriptions,
givenToMeConfirmed, givenToMeConfirmed,
givenToMeUnconfirmed, givenToMeUnconfirmed,
false,
); );
this.givenToMeDescriptions = givenToMeDescriptions; this.givenToMeDescriptions = givenToMeDescriptions;
this.givenToMeConfirmed = givenToMeConfirmed; this.givenToMeConfirmed = givenToMeConfirmed;

View File

@@ -83,17 +83,21 @@
class="block py-4 flex gap-4" class="block py-4 flex gap-4"
> >
<div class="w-12"> <div class="w-12">
<img <EntityIcon
src="https://picsum.photos/200/200?random=1" :entityId="project.handleId"
class="w-full rounded" :iconSize="48"
/> class="block border border-slate-300 rounded-md"
></EntityIcon>
</div> </div>
<div class="grow"> <div class="grow">
<h2 class="text-base font-semibold">Canyon cleanup</h2> <h2 class="text-base font-semibold">{{ project.name }}</h2>
<h2 class="text-base font-semibold">{{ project.name }}</h2>
<div class="text-sm"> <div class="text-sm">
<fa icon="user" class="fa-fw text-slate-400"></fa> <fa icon="user" class="fa-fw text-slate-400"></fa>
{{ project.name }} {{
didInfo(project.issuerDid, activeDid, allMyDids, allContacts)
}}
</div> </div>
</div> </div>
</a> </a>
@@ -111,17 +115,22 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { accountsDB, db } from "@/db"; import { accountsDB, db } from "@/db";
import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
import { didInfo } from "@/libs/endorserServer";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import InfiniteScroll from "@/components/InfiniteScroll"; import InfiniteScroll from "@/components/InfiniteScroll";
import EntityIcon from "@/components/EntityIcon";
@Component({ @Component({
components: { AlertMessage, QuickNav, InfiniteScroll }, components: { AlertMessage, QuickNav, InfiniteScroll, EntityIcon },
}) })
export default class DiscoverView extends Vue { export default class DiscoverView extends Vue {
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = [];
allMyDids: Array<string> = [];
apiServer = ""; apiServer = "";
searchTerms = ""; searchTerms = "";
alertMessage = ""; alertMessage = "";
@@ -133,11 +142,20 @@ export default class DiscoverView extends Vue {
remoteCount = 0; remoteCount = 0;
isLoading = false; isLoading = false;
// make this function available to the Vue template
didInfo = didInfo;
async mounted() { async mounted() {
await db.open(); await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY); const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || ""; this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || ""; this.apiServer = settings?.apiServer || "";
this.allContacts = await db.contacts.toArray();
await accountsDB.open();
const allAccounts = await accountsDB.accounts.toArray();
this.allMyDids = allAccounts.map((acc) => acc.did);
this.searchLocal(); this.searchLocal();
} }
@@ -166,7 +184,6 @@ export default class DiscoverView extends Vue {
public async search(beforeId?: string) { public async search(beforeId?: string) {
let queryParams = "claimContents=" + encodeURIComponent(this.searchTerms); let queryParams = "claimContents=" + encodeURIComponent(this.searchTerms);
console.log(beforeId);
if (beforeId) { if (beforeId) {
queryParams = queryParams + `&beforeId=${beforeId}`; queryParams = queryParams + `&beforeId=${beforeId}`;
} }
@@ -204,9 +221,8 @@ export default class DiscoverView extends Vue {
const plans: ProjectData[] = results.data; const plans: ProjectData[] = results.data;
if (plans) { if (plans) {
for (const plan of plans) { for (const plan of plans) {
const { name, description, handleId = plan.handleId, rowid } = plan; const { name, description, handleId, rowid, issuerDid } = plan;
console.log("here"); this.projects.push({ name, description, handleId, rowid, issuerDid });
this.projects.push({ name, description, handleId, rowid });
} }
this.remoteCount = this.projects.length; this.remoteCount = this.projects.length;
} else { } else {
@@ -310,8 +326,6 @@ export default class DiscoverView extends Vue {
async loadMoreData(payload: boolean) { async loadMoreData(payload: boolean) {
if (this.projects.length > 0 && payload) { if (this.projects.length > 0 && payload) {
const latestProject = this.projects[this.projects.length - 1]; const latestProject = this.projects[this.projects.length - 1];
console.log("rowid", latestProject, payload);
console.log(Object.keys(latestProject));
if (this.isLocalActive) { if (this.isLocalActive) {
this.searchLocal(latestProject["rowid"]); this.searchLocal(latestProject["rowid"]);
} else if (this.isRemoteActive) { } else if (this.isRemoteActive) {

View File

@@ -128,6 +128,14 @@
key. key.
</p> </p>
<h2 class="text-xl font-semibold">How do I create another identity?</h2>
<p>
Go
<router-link to="start" class="text-blue-500">
create another identity here.
</router-link>
</p>
<h2 class="text-xl font-semibold"> <h2 class="text-xl font-semibold">
I know there is a record from someone, so why can't I see that info? I know there is a record from someone, so why can't I see that info?
</h2> </h2>
@@ -146,14 +154,6 @@
page. page.
</p> </p>
<h2 class="text-xl font-semibold">How do I create another identity?</h2>
<p>
Go
<router-link to="start" class="text-blue-500">
create another identity here.
</router-link>
</p>
<h2 class="text-xl font-semibold">What is your privacy policy?</h2> <h2 class="text-xl font-semibold">What is your privacy policy?</h2>
<p> <p>
See See

View File

@@ -104,9 +104,11 @@
:key="contact.did" :key="contact.did"
@click="openDialog(contact)" @click="openDialog(contact)"
> >
<div class="mb-1"> <EntityIcon
<fa icon="user" class="fa-fw fa-xl text-slate-400"></fa> :entityId="contact.did"
</div> :iconSize="64"
class="mx-auto border border-slate-300 rounded-md mb-1"
></EntityIcon>
<h3 <h3
class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden" class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
> >
@@ -183,9 +185,10 @@ import { createAndSubmitGive, didInfo } from "@/libs/endorserServer";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import EntityIcon from "@/components/EntityIcon";
@Component({ @Component({
components: { GiftedDialog, AlertMessage, QuickNav }, components: { GiftedDialog, AlertMessage, QuickNav, EntityIcon },
}) })
export default class HomeView extends Vue { export default class HomeView extends Vue {
activeDid = ""; activeDid = "";
@@ -348,7 +351,7 @@ export default class HomeView extends Vue {
} }
// agent.did is for legacy data, before March 2023 // agent.did is for legacy data, before March 2023
const giverDid = const giverDid =
claim.agent?.identifier || claim.agent?.did || giveRecord.issuer; claim.agent?.identifier || claim.agent?.did;
const giverInfo = didInfo( const giverInfo = didInfo(
giverDid, giverDid,
this.activeDid, this.activeDid,

View File

@@ -218,13 +218,13 @@ export default class NewEditProjectView extends Vue {
try { try {
const resp = await this.axios.post(url, payload, { headers }); const resp = await this.axios.post(url, payload, { headers });
// handleId is new in server v release-1.6.0; remove fullIri when that // handleId is new in server v release-1.6.0; remove fullIri when that
// version shows up here: https://endorser.ch:3000/api-docs/ // version shows up here: https://api.endorser.ch/api-docs/
if (resp.data?.success?.handleId || resp.data?.success?.fullIri) { if (resp.data?.success?.handleId || resp.data?.success?.fullIri) {
this.errorMessage = ""; this.errorMessage = "";
this.alertTitle = ""; this.alertTitle = "";
this.alertMessage = ""; this.alertMessage = "";
// handleId is new in server v release-1.6.0; remove fullIri when that // handleId is new in server v release-1.6.0; remove fullIri when that
// version shows up here: https://endorser.ch:3000/api-docs/ // version shows up here: https://api.endorser.ch/api-docs/
useAppStore().setProjectId( useAppStore().setProjectId(
resp.data.success.handleId || resp.data.success.fullIri, resp.data.success.handleId || resp.data.success.fullIri,
); );

View File

@@ -26,16 +26,28 @@
<!-- Project Details --> <!-- Project Details -->
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4"> <div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
<div> <div>
<h2 class="text-xl font-semibold">{{ name }}</h2> <div class="block pb-4 flex gap-4">
<div class="flex justify-between gap-4 text-sm mb-3"> <div class="flex-none w-16 pt-1">
<span <EntityIcon
><fa icon="user" class="fa-fw text-slate-400"></fa> :entityId="projectId"
{{ issuer }}</span :iconSize="64"
> class="block border border-slate-300 rounded-md"
<span ></EntityIcon>
><fa icon="calendar" class="fa-fw text-slate-400"></fa </div>
>{{ timeSince }}
</span> <div class="overflow-hidden">
<h2 class="text-xl font-semibold">{{ name }}</h2>
<div class="text-sm mb-3">
<div class="truncate"
><fa icon="user" class="fa-fw text-slate-400"></fa>
{{ issuer }}</div
>
<div
><fa icon="calendar" class="fa-fw text-slate-400"></fa
>{{ timeSince }}
</div>
</div>
</div>
</div> </div>
<div class="text-sm text-slate-500"> <div class="text-sm text-slate-500">
@@ -65,83 +77,115 @@
</div> </div>
<div> <div>
<div v-if="activeDid"> <div v-if="activeDid" class="text-center">
<button <button
@click="openDialog({ name: 'you', did: activeDid })" @click="openDialog({ name: 'you', did: activeDid })"
class="text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md" class="block w-full text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md"
> >
I gave... I gave&hellip;
</button> </button>
&horbar; or: <p class="mt-2 mb-4 text-center">Or, record a gift from:</p>
</div> </div>
<!-- similar contact selection code is in multiple places --> <p v-if="!activeDid" class="mt-2 mb-4">Record a gift from:</p>
Record a gift from
<span v-for="contact in allContacts" :key="contact.did"> <ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
<button @click="openDialog(contact)" class="text-blue-500"> <li @click="openDialog()">
&nbsp;{{ contact.name }}</button <div class="mb-1">
>, <fa icon="question-circle" class="fa-fw fa-xl text-slate-400"></fa>
</span> </div>
<span v-if="allContacts.length > 0">&nbsp;or&nbsp;</span> <h3
<button @click="openDialog()" class="text-blue-500"> class="text-xs italic font-medium text-ellipsis whitespace-nowrap overflow-hidden"
someone not specified >
</button> Anonymous
</h3>
</li>
<li
v-for="contact in allContacts"
:key="contact.did"
@click="openDialog(contact)"
>
<div class="mb-1">
<fa icon="user" class="fa-fw fa-xl text-slate-400"></fa>
</div>
<h3
class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
>
{{ contact.name || "(no name)" }}
</h3>
</li>
</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) -->
<router-link
v-if="allContacts.length > 7"
:to="{ name: 'contact-gives' }"
class="block text-center text-md font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md"
>
Show More Contacts&hellip;
</router-link>
</div> </div>
<!-- Gifts to & from this --> <!-- Gifts to & from this -->
<div class="mt-8 flex justify-around"> <div class="grid items-start grid-cols-1 sm:grid-cols-2 gap-4">
<div> <div class="bg-slate-100 px-4 py-3 rounded-md">
<h1 class="text-xl">Given to this Project</h1> <h3 class="text-sm uppercase font-semibold mb-3">
Given to this Project
</h3>
<ul class="text-sm border-t border-slate-300">
<li
v-for="give in givesToThis"
:key="give.id"
class="py-1.5 border-b border-slate-300"
>
<div class="flex justify-between gap-4">
<span
><fa icon="user" class="fa-fw text-slate-400"></fa>
{{ didInfo(give.agentDid, activeDid, allMyDids, allContacts) }}
</span>
<span v-if="give.amount"
><fa icon="coins" class="fa-fw text-slate-400"></fa>
{{ give.amount }}
</span>
</div>
<div v-if="give.description" class="text-slate-500">
<fa icon="comment" class="fa-fw text-slate-400"></fa>
{{ give.description }}
</div>
</li>
</ul>
</div> </div>
<div>
<h1 class="text-xl">... and from this Project</h1> <div class="bg-slate-100 px-4 py-3 rounded-md">
</div> <h3 class="text-sm uppercase font-semibold mb-3">
</div> &hellip;and from this Project
<div class="flex justify-around"> </h3>
<div class="w-1/2">
<div v-for="give in givesToThis" :key="give.id"> <ul class="text-sm border-t border-slate-300">
<div class="flex justify-between"> <li
<div class="flex gap-3"> v-for="give in givesByThis"
<div class="flex gap-2"> :key="give.id"
<fa icon="user" class="fa-fw text-slate-400"></fa> class="py-1.5 border-b border-slate-300"
<span>{{ >
didInfo(give.agentDid, activeDid, allMyDids, allContacts) <div class="flex justify-between gap-4">
}}</span> <span
</div> ><fa icon="user" class="fa-fw text-slate-400"></fa>
<div class="flex gap-2" v-if="give.amount"> {{ didInfo(give.agentDid, activeDid, allMyDids, allContacts) }}
<fa icon="coins" class="fa-fw text-slate-400"></fa> </span>
<span>{{ give.amount }}</span> <span v-if="give.amount"
</div> ><fa icon="coins" class="fa-fw text-slate-400"></fa>
<div class="flex gap-2" v-if="give.description"> {{ give.amount }}
<fa icon="comment" class="fa-fw text-slate-400"></fa> </span>
<span>{{ give.description }}</span> </div>
</div> <div v-if="give.description" class="text-slate-500">
</div> <fa icon="comment" class="fa-fw text-slate-400"></fa>
</div> {{ give.description }}
</div> </div>
</div> </li>
<div class="w-1/2"> </ul>
<div v-for="give in givesByThis" :key="give.id">
<div class="flex justify-between">
<div class="flex gap-3">
<div class="flex gap-2">
<fa icon="user" class="fa-fw text-slate-400"></fa>
<span>{{
didInfo(give.agentDid, activeDid, allMyDids, allContacts)
}}</span>
</div>
<div class="flex gap-2" v-if="give.amount">
<fa icon="coins" class="fa-fw text-slate-400"></fa>
<span>{{ give.amount }}</span>
</div>
<div class="flex gap-2">
<fa icon="comment" class="fa-fw text-slate-400"></fa>
<span>{{ give.description }}</span>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
<GiftedDialog <GiftedDialog
ref="customDialog" ref="customDialog"
@dialog-result="handleDialogResult" @dialog-result="handleDialogResult"
@@ -173,9 +217,10 @@ import {
} from "@/libs/endorserServer"; } from "@/libs/endorserServer";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import EntityIcon from "@/components/EntityIcon";
@Component({ @Component({
components: { GiftedDialog, AlertMessage, QuickNav }, components: { GiftedDialog, AlertMessage, QuickNav, EntityIcon },
}) })
export default class ProjectViewView extends Vue { export default class ProjectViewView extends Vue {
activeDid = ""; activeDid = "";

View File

@@ -50,10 +50,11 @@
class="block py-4 flex gap-4" class="block py-4 flex gap-4"
> >
<div class="flex-none w-12"> <div class="flex-none w-12">
<img <EntityIcon
src="https://picsum.photos/200/200?random=1" :entityId="project.handleId"
class="w-full rounded" :iconSize="48"
/> class="inline-block align-middle border border-slate-300 rounded-md"
></EntityIcon>
</div> </div>
<div class="grow overflow-hidden"> <div class="grow overflow-hidden">
@@ -82,9 +83,10 @@ import { IIdentifier } from "@veramo/core";
import InfiniteScroll from "@/components/InfiniteScroll"; import InfiniteScroll from "@/components/InfiniteScroll";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
import EntityIcon from "@/components/EntityIcon";
@Component({ @Component({
components: { InfiniteScroll, AlertMessage, QuickNav }, components: { InfiniteScroll, AlertMessage, QuickNav, EntityIcon },
}) })
export default class ProjectsView extends Vue { export default class ProjectsView extends Vue {
apiServer = ""; apiServer = "";

View File

@@ -20,22 +20,26 @@
</div> </div>
<div v-if="activeAccount"> <div v-if="activeAccount">
<p> <p class="text-center mb-4">
BEWARE: Anyone who gets hold of this mnemonic seed phrase will be able <b class="text-red-600">BEWARE!</b> Anyone who has this seed phrase will
impersonate you and take over any digital holdings based on it. So only be able impersonate you and take over any digital holdings based on it.
reveal it when you are in a private place out of sight of other eyes, Reveal it when you are somewhere only you can see your screen, and
and only record it in something private -- don't take a screenshot or record it somewhere only you have access.
send it to any online service. <i>Don't take a screenshot or send it to any online service.</i>
</p> </p>
<button <div class="bg-slate-100 rounded-md overflow-hidden p-4 mb-4">
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md" <button
@click="showSeedPhrase" class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
> @click="showSeedPhrase"
Click here when you're ready to see it. >
</button> Reveal my Seed Phrase
</button>
<p v-if="showSeed">{{ activeAccount.mnemonic }}</p> <p v-if="showSeed" class="text-center text-slate-700 mt-2">
{{ activeAccount.mnemonic }}
</p>
</div>
</div> </div>
<div v-else>You do not have an active identity.</div> <div v-else>You do not have an active identity.</div>
<AlertMessage <AlertMessage