forked from trent_larson/crowd-funder-for-time-pwa
Compare commits
19 Commits
notiwind-a
...
polish-ui-
| Author | SHA1 | Date | |
|---|---|---|---|
| 3204f1d676 | |||
|
|
304985f88d | ||
|
|
9a41aff8f0 | ||
|
|
e19cd980b4 | ||
| b31c0d975c | |||
| f09684d7cd | |||
| 1767a48a7f | |||
|
|
4de66b1609 | ||
|
|
4b87692231 | ||
|
|
503bb1bd93 | ||
|
|
9fa3b8be0b | ||
| 3b1a9b9c5b | |||
| 7f48149d6f | |||
| c5b4921583 | |||
| b28689ad06 | |||
| 0444b5be32 | |||
| 4866416aae | |||
| e48a4ed05b | |||
| 87cfead094 |
23
package-lock.json
generated
23
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
19
src/components/EntityIcon.vue
Normal file
19
src/components/EntityIcon.vue
Normal 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>
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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…
|
||||||
</button>
|
</button>
|
||||||
― 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()">
|
||||||
{{ 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"> or </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…
|
||||||
|
</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>
|
…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 = "";
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|||||||
Reference in New Issue
Block a user