From 72148825239d7dca378e2224df99e68a3aeb07e1 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 13 Mar 2023 20:36:33 -0600 Subject: [PATCH 1/6] feat: show hours given to and received from contacts --- src/views/ContactsView.vue | 109 ++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index ccd5fa397..eb204f136 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -40,12 +40,17 @@ +

My Contacts

+
+ {{ errorMessage }} +
+
+ +
+ + +
+ @@ -83,6 +112,10 @@ From 392728fd4a7d735ddcacbdca6d512dec99e46b18 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 14 Mar 2023 17:03:32 -0600 Subject: [PATCH 2/6] feat: allow entry and send of a Give to/from addresses in contact list --- src/views/ContactsView.vue | 177 ++++++++++++++++++++++++++++++++----- 1 file changed, 157 insertions(+), 20 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index eb204f136..f8c620609 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -69,17 +69,28 @@
- +
+ +
+
+ Hours to Add: + +
@@ -97,11 +108,20 @@
{{ contact.publicKeyBase64 }}
- to: {{ contactGivenTotals[contact.did] || 0 }} -
-
-
- from: {{ contactReceivedTotals[contact.did] || 0 }} + to: {{ givenByMeTotals[contact.did] || 0 }} + + by: {{ givenToMeTotals[contact.did] || 0 }} +
@@ -111,14 +131,24 @@ From d5abfb0265b3e18d31377d3cb51f3d7016bcf561 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 14 Mar 2023 18:42:30 -0600 Subject: [PATCH 3/6] feat: load totals immediately, and prompt to verify giving amount --- src/views/ContactsView.vue | 51 ++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index f8c620609..0ecb8d279 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -67,22 +67,8 @@ - -
- -
- -
-
+
+
Hours to Add: import { AxiosError } from "axios"; import * as didJwt from "did-jwt"; +import * as R from "ramda"; import { Options, Vue } from "vue-class-component"; import { AppString } from "@/constants/app"; @@ -153,7 +140,7 @@ export interface GiveVerifiableCredential { components: {}, }) export default class ContactsView extends Vue { - contacts: Contact[] = []; + contacts: Array = []; contactInput = ""; // { "did:...": amount } entry for each contact givenByMeTotals = {}; @@ -167,13 +154,15 @@ export default class ContactsView extends Vue { // 'created' hook runs when the Vue instance is first created async created() { await db.open(); + const accounts = await db.accounts.toArray(); + this.identity = JSON.parse(accounts[0].identity); this.contacts = await db.contacts.toArray(); const params = new URLSearchParams(window.location.search); this.showGiveTotals = params.get("showGiveTotals") == "true"; - - const accounts = await db.accounts.toArray(); - this.identity = JSON.parse(accounts[0].identity); + if (this.showGiveTotals) { + this.loadGives(); + } } async onClickNewContact(): void { @@ -259,6 +248,10 @@ export default class ContactsView extends Vue { return !isNaN(str) && !isNaN(parseFloat(str)); } + private contactForDid(contacts: Array, did: string): Contact { + return R.find((con) => con.did == did, contacts); + } + async onClickAddGive(fromDid: string, toDid: string): void { if (!this.hourInput) { this.errorMessage = "Giving 0 hours does nothing."; @@ -267,7 +260,23 @@ export default class ContactsView extends Vue { "This is not a valid number of hours: " + this.hourInput; } else { this.errorMessage = ""; - this.createAndSubmitGive(fromDid, toDid, parseFloat(this.hourInput)); + let toFrom; + if (fromDid == this.identity.did) { + toFrom = "to " + this.contactForDid(this.contacts, toDid).name; + } else { + toFrom = "from " + this.contactForDid(this.contacts, fromDid).name; + } + if ( + confirm( + "Are you sure you want to record " + + this.hourInput + + " hours " + + toFrom + + "?" + ) + ) { + this.createAndSubmitGive(fromDid, toDid, parseFloat(this.hourInput)); + } } } From d6a5bd02f3d10eb31ea5059138e3018f3768b8e5 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Tue, 14 Mar 2023 20:31:26 -0600 Subject: [PATCH 4/6] fix: type-checking --- src/views/ContactsView.vue | 110 +++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 0ecb8d279..c6647badf 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -114,6 +114,16 @@
+
+ +

{{ alertTitle }}

+

{{ alertMessage }}

+
From 9cb10b856196bf810db3fb554ef06b86fd74a64d Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Wed, 15 Mar 2023 18:49:05 -0600 Subject: [PATCH 5/6] ui: change item on bottom row to 'contacts' --- src/main.ts | 2 ++ src/views/AccountViewView.vue | 4 ++-- src/views/ContactsView.vue | 8 +++++--- src/views/DiscoverView.vue | 6 ++++-- src/views/ProjectsView.vue | 6 ++++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main.ts b/src/main.ts index 234967b8f..8fc26a4e5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,6 +20,7 @@ import { faShareNodes, faQrcode, faUser, + faUsers, faPen, faPlus, faTrashCan, @@ -41,6 +42,7 @@ library.add( faShareNodes, faQrcode, faUser, + faUsers, faPen, faPlus, faTrashCan, diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 0bc56faf4..d67e3a25f 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -29,10 +29,10 @@
  • - +
  • diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index c6647badf..6147f5dce 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -19,15 +19,17 @@
  • -
  • diff --git a/src/views/DiscoverView.vue b/src/views/DiscoverView.vue index c35148107..7eadab713 100644 --- a/src/views/DiscoverView.vue +++ b/src/views/DiscoverView.vue @@ -26,8 +26,10 @@
  • -
  • diff --git a/src/views/ProjectsView.vue b/src/views/ProjectsView.vue index ae3abbe6a..46660cd36 100644 --- a/src/views/ProjectsView.vue +++ b/src/views/ProjectsView.vue @@ -26,8 +26,10 @@
  • -
  • From f6a7677bdc0ed0e95590d2d7c24d7a040df7628d Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Wed, 15 Mar 2023 21:04:10 -0600 Subject: [PATCH 6/6] feat: add a description for time gifts (and refactor errors) --- src/views/ContactsView.vue | 76 ++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 6147f5dce..34fcb2b85 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -49,10 +49,6 @@ My Contacts -
    - {{ errorMessage }} -
    -
    +
    +
    @@ -144,8 +147,9 @@ export interface GiveVerifiableCredential { "@context": string; "@type": string; agent: { identifier: string }; - recipient: { identifier: string }; + description?: string; object: { amountOfThisGood: number; unitCode: string }; + recipient: { identifier: string }; } @Options({ @@ -158,9 +162,9 @@ export default class ContactsView extends Vue { givenByMeTotals: Record = {}; // { "did:...": amount } entry for each contact givenToMeTotals: Record = {}; + hourDescriptionInput = ""; hourInput = "0"; identity: IIdentifier | null = null; - errorMessage = ""; showGiveTotals = false; // 'created' hook runs when the Vue instance is first created @@ -231,7 +235,9 @@ export default class ContactsView extends Vue { this.givenByMeTotals = contactTotals; } } catch (error) { - this.errorMessage = "" + error; + this.alertTitle = "Error from Server"; + this.alertMessage = error as string; + this.isAlertVisible = true; } // load all the time I have received @@ -259,7 +265,9 @@ export default class ContactsView extends Vue { this.givenToMeTotals = contactTotals; } } catch (error) { - this.errorMessage = "" + error; + this.alertTitle = "Error from Server"; + this.alertMessage = error as string; + this.isAlertVisible = true; } } @@ -275,20 +283,25 @@ export default class ContactsView extends Vue { } async onClickAddGive(fromDid: string, toDid: string): Promise { - if (!this.hourInput) { - this.errorMessage = "Giving 0 hours does nothing."; - } else if (!this.isNumeric(this.hourInput)) { - this.errorMessage = + if (!this.isNumeric(this.hourInput)) { + this.alertTitle = "Input Error"; + this.alertMessage = "This is not a valid number of hours: " + this.hourInput; + this.isAlertVisible = true; + } else if (!parseFloat(this.hourInput)) { + this.alertTitle = "Input Error"; + this.alertMessage = "Giving 0 hours does nothing."; + this.isAlertVisible = true; } else if (!this.identity) { - this.errorMessage = "No identity is available."; + this.alertTitle = "Status Error"; + this.alertMessage = "No identity is available."; + this.isAlertVisible = true; } else { - this.errorMessage = ""; let toFrom; if (fromDid == this.identity?.did) { - toFrom = "to " + this.nameForDid(this.contacts, toDid); + toFrom = "from you to " + this.nameForDid(this.contacts, toDid); } else { - toFrom = "from " + this.nameForDid(this.contacts, fromDid); + toFrom = "from " + this.nameForDid(this.contacts, fromDid) + " to you"; } if ( confirm( @@ -303,7 +316,8 @@ export default class ContactsView extends Vue { this.identity, fromDid, toDid, - parseFloat(this.hourInput) + parseFloat(this.hourInput), + this.hourDescriptionInput ); } } @@ -313,16 +327,20 @@ export default class ContactsView extends Vue { identity: IIdentifier, fromDid: string, toDid: string, - amount: number + amount: number, + description: string ): Promise { // Make a claim const vcClaim: GiveVerifiableCredential = { "@context": "https://schema.org", "@type": "GiveAction", agent: { identifier: fromDid }, - recipient: { identifier: toDid }, object: { amountOfThisGood: amount, unitCode: "HUR" }, + recipient: { identifier: toDid }, }; + if (description) { + vcClaim.description = description; + } // Make a payload for the claim const vcPayload = { vc: { @@ -359,18 +377,17 @@ export default class ContactsView extends Vue { const resp = await this.axios.post(url, payload, { headers }); //console.log("Got resp data:", resp.data); if (resp.data?.success?.handleId) { - this.errorMessage = ""; this.alertTitle = ""; this.alertMessage = ""; if (fromDid === identity.did) { this.givenByMeTotals[toDid] = this.givenByMeTotals[toDid] + amount; - // do this to update the UI + // do this to update the UI (is there a better way?) // eslint-disable-next-line no-self-assign this.givenByMeTotals = this.givenByMeTotals; } else { this.givenToMeTotals[fromDid] = this.givenToMeTotals[fromDid] + amount; - // do this to update the UI + // do this to update the UI (is there a better way?) // eslint-disable-next-line no-self-assign this.givenToMeTotals = this.givenToMeTotals; } @@ -379,21 +396,18 @@ export default class ContactsView extends Vue { let userMessage = "There was an error. See logs for more info."; const serverError = error as AxiosError; if (serverError) { - this.isAlertVisible = true; if (serverError.message) { - this.alertTitle = "User Message"; - userMessage = serverError.message; // This is info for the user. - this.alertMessage = userMessage; + userMessage = serverError.message; // Info for the user } else { - this.alertTitle = "Server Message"; - this.alertMessage = JSON.stringify(serverError.toJSON()); + userMessage = JSON.stringify(serverError.toJSON()); } } else { - this.alertTitle = "Claim Error"; - this.alertMessage = error as string; + userMessage = error as string; } // Now set that error for the user to see. - this.errorMessage = userMessage; + this.alertTitle = "Error with Server"; + this.alertMessage = userMessage; + this.isAlertVisible = true; } } }