From 511be5f9a2b383a0e256d2271b72fdeeb8961df0 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Mon, 19 Aug 2024 20:18:06 -0600 Subject: [PATCH] move contact actions into the details page (prepping for checkboxes) --- playwright.config-local.ts | 2 +- src/libs/util.ts | 29 +- src/views/ContactsView.vue | 329 ++---------------- src/views/DIDView.vue | 439 ++++++++++++++++++++++++- test-playwright/30-record-gift.spec.ts | 4 +- test-playwright/40-add-contact.spec.ts | 9 +- 6 files changed, 478 insertions(+), 334 deletions(-) diff --git a/playwright.config-local.ts b/playwright.config-local.ts index 02f0ae3..eb95e44 100644 --- a/playwright.config-local.ts +++ b/playwright.config-local.ts @@ -74,7 +74,7 @@ export default defineConfig({ /* Configure global timeout; default is 30000 milliseconds */ // the image upload will often not succeed at 5 seconds - //timeout: 10000, + timeout: 15000, /* Run your local dev server before starting the tests */ /** diff --git a/src/libs/util.ts b/src/libs/util.ts index a40f4c4..9830ee7 100644 --- a/src/libs/util.ts +++ b/src/libs/util.ts @@ -1,11 +1,14 @@ // many of these are also found in endorser-mobile utility.ts import axios, { AxiosResponse } from "axios"; +import { Buffer } from "buffer"; +import * as R from "ramda"; import { useClipboard } from "@vueuse/core"; import { DEFAULT_PUSH_SERVER } from "@/constants/app"; import { accountsDB, db } from "@/db/index"; import { Account } from "@/db/tables/accounts"; +import { Contact } from "@/db/tables/contacts"; import { DEFAULT_PASSKEY_EXPIRATION_MINUTES, MASTER_SETTINGS_KEY, @@ -18,11 +21,9 @@ import { OfferVerifiableCredential, } from "@/libs/endorserServer"; import * as serverUtil from "@/libs/endorserServer"; -import { registerCredential } from "@/libs/crypto/vc/passkeyDidPeer"; - -import { Buffer } from "buffer"; import { KeyMeta } from "@/libs/crypto/vc"; import { createPeerDid } from "@/libs/crypto/vc/didPeer"; +import { registerCredential } from "@/libs/crypto/vc/passkeyDidPeer"; export const PRIVACY_MESSAGE = "The data you send will be visible to the world -- except: your IDs and the IDs of anyone you tag will stay private, only visible to them and others you explicitly allow."; @@ -91,6 +92,28 @@ export const isGiveAction = ( return veriClaim.claimType === "GiveAction"; }; +export const nameForDid = ( + activeDid: string, + contacts: Array, + did: string, +): string => { + if (did === activeDid) { + return "you"; + } + const contact = R.find((con) => con.did == did, contacts); + return nameForContact(contact); +}; + +export const nameForContact = ( + contact?: Contact, + capitalize?: boolean, +): string => { + return ( + (contact?.name as string) || + (capitalize ? "This" : "this") + " unnamed user" + ); +}; + export const doCopyTwoSecRedo = (text: string, fn: () => void) => { fn(); useClipboard() diff --git a/src/views/ContactsView.vue b/src/views/ContactsView.vue index 6d282d9..b2714e5 100644 --- a/src/views/ContactsView.vue +++ b/src/views/ContactsView.vue @@ -37,7 +37,7 @@ class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400" @click="onClickNewContact()" > - + @@ -82,10 +82,10 @@
  • @@ -98,131 +98,16 @@ @click="showLargeIdenticon = contact" /> {{ contact.name || AppString.NO_CONTACT_NAME }} - -
    - Identifier: - - Copied DID - {{ contact.did }} -
    -
    - Public Key (base 64): - - Copied Key - {{ contact.publicKeyBase64 }} -
    -
    - Next Public Key Hash (base 64): - - Copied Hash - {{ contact.nextPubKeyHashB64 }} -
    -
    -
    - - - - - - - - - - - - -
    - - -
    - -
    -
    -

    Edit Name

    - -
    - - - -
    -
    -
    @@ -782,55 +640,29 @@ export default class ContactsView extends Vue { }); } - // prompt with confirmation if they want to delete a contact - confirmDeleteContact(contact: Contact) { - this.$notify( - { - group: "modal", - type: "confirm", - title: "Delete", - text: - "Are you sure you want to remove " + - this.nameForDid(this.contacts, contact.did) + - " with DID " + - contact.did + - " from your contact list?", - onYes: async () => { - await this.deleteContact(contact); - }, - }, - -1, - ); - } - - async deleteContact(contact: Contact) { - await db.open(); - await db.contacts.delete(contact.did); - this.contacts = R.without([contact], this.contacts); - } - - // confirm to register a new contact - async confirmRegister(contact: Contact) { + // note that this is also in DIDView.vue + async confirmSetVisibility(contact: Contact, visibility: boolean) { + const visibilityPrompt = visibility + ? "Are you sure you want to make your activity visible to them?" + : "Are you sure you want to hide all your activity from them?"; this.$notify( { group: "modal", type: "confirm", - title: "Register", - text: - "Are you sure you want to register " + - this.nameForDid(this.contacts, contact.did) + - (contact.registered - ? " -- especially since they are already marked as registered" - : "") + - "?", + title: "Set Visibility", + text: visibilityPrompt, onYes: async () => { - await this.register(contact); + const success = await this.setVisibility(contact, visibility, true); + if (success) { + contact.seesMe = visibility; // didn't work inside setVisibility + } }, }, -1, ); } + // note that this is also in DIDView.vue async register(contact: Contact) { this.$notify({ group: "alert", type: "toast", title: "Sent..." }, 1000); @@ -896,27 +728,7 @@ export default class ContactsView extends Vue { } } - async confirmSetVisibility(contact: Contact, visibility: boolean) { - const visibilityPrompt = visibility - ? "Are you sure you want to make your activity visible to them?" - : "Are you sure you want to hide all your activity from them?"; - this.$notify( - { - group: "modal", - type: "confirm", - title: "Set Visibility", - text: visibilityPrompt, - onYes: async () => { - const success = await this.setVisibility(contact, visibility, true); - if (success) { - contact.seesMe = visibility; // didn't work inside setVisibility - } - }, - }, - -1, - ); - } - + // note that this is also in DIDView.vue async setVisibility( contact: Contact, visibility: boolean, @@ -966,6 +778,7 @@ export default class ContactsView extends Vue { } } + // note that this is also in DIDView.vue async checkVisibility(contact: Contact) { const url = this.apiServer + @@ -999,7 +812,7 @@ export default class ContactsView extends Vue { type: "info", title: "Visibility Refreshed", text: - this.nameForContact(contact, true) + + libsUtil.nameForContact(contact, true) + " can " + (visibility ? "" : "not ") + "see your activity.", @@ -1033,21 +846,6 @@ export default class ContactsView extends Vue { } } - private nameForDid(contacts: Array, did: string): string { - if (did === this.activeDid) { - return "you"; - } - const contact = R.find((con) => con.did == did, contacts); - return this.nameForContact(contact); - } - - private nameForContact(contact?: Contact, capitalize?: boolean): string { - return ( - (contact?.name as string) || - (capitalize ? "This" : "this") + " unnamed user" - ); - } - confirmShowGiftedDialog(giverDid: string, recipientDid: string) { // if they have unconfirmed amounts, ask to confirm those if ( @@ -1093,13 +891,13 @@ export default class ContactsView extends Vue { if (giverDid) { giver = { did: giverDid, - name: this.nameForDid(this.contacts, giverDid), + name: libsUtil.nameForDid(this.activeDid, this.contacts, giverDid), }; } if (recipientDid) { receiver = { did: recipientDid, - name: this.nameForDid(this.contacts, recipientDid), + name: libsUtil.nameForDid(this.activeDid, this.contacts, recipientDid), }; } @@ -1131,25 +929,13 @@ export default class ContactsView extends Vue { ); } - openOfferDialog(recipientDid: string, recipientName: string) { + openOfferDialog(recipientDid: string, recipientName?: string) { (this.$refs.customOfferDialog as OfferDialog).open( recipientDid, recipientName, ); } - private async onClickCancelName() { - this.contactEdit = null; - this.contactNewName = ""; - } - - private async onClickSaveName(contact: Contact, newName: string) { - contact.name = newName; - return db.contacts - .update(contact.did, { name: newName }) - .then(() => (this.contactEdit = null)); - } - public async toggleShowContactAmounts() { const newShowValue = !this.showGiveNumbers; try { @@ -1211,74 +997,3 @@ export default class ContactsView extends Vue { } } - - diff --git a/src/views/DIDView.vue b/src/views/DIDView.vue index 118dd3d..a2dd921 100644 --- a/src/views/DIDView.vue +++ b/src/views/DIDView.vue @@ -26,8 +26,20 @@ didInfoForContact(viewingDid, activeDid, contact, allMyDids) .displayName }} + - + + + + + + + + + + + + + + + + +
    +
    Auto-Generated Icon
    +
    + +
    +
    +
    +

    Edit Name

    + +
    + + + +
    +
    +
    - They Are in No Claims Visible to You + They are in no claims visible to you.
    + + diff --git a/test-playwright/30-record-gift.spec.ts b/test-playwright/30-record-gift.spec.ts index 6962303..391ce71 100644 --- a/test-playwright/30-record-gift.spec.ts +++ b/test-playwright/30-record-gift.spec.ts @@ -2,8 +2,8 @@ import { test, expect } from '@playwright/test'; import { importUser } from './testUtils'; test('Record something given', async ({ page }) => { - // Generate a random string of 3 characters - const randomString = Math.random().toString(36).substring(2, 5); + // Generate a random string of a few characters + const randomString = Math.random().toString(36).substring(2, 6); // Generate a random non-zero single-digit number const randomNonZeroNumber = Math.floor(Math.random() * 99) + 1; diff --git a/test-playwright/40-add-contact.spec.ts b/test-playwright/40-add-contact.spec.ts index cc39c37..37a7b2a 100644 --- a/test-playwright/40-add-contact.spec.ts +++ b/test-playwright/40-add-contact.spec.ts @@ -21,14 +21,14 @@ test('Add contact, record gift, confirm gift', async ({ page }) => { const finalTitle = standardTitle + finalRandomString; // Contact name - const contactName = 'Contact 00'; + const contactName = 'Contact #000'; // Import user 01 await importUser(page, '01'); // Add new contact 00 await page.goto('./contacts'); - await page.getByPlaceholder('URL or DID, Name, Public Key').fill('did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F'); + await page.getByPlaceholder('URL or DID, Name, Public Key').fill('did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F, User #000'); await page.locator('button > svg.fa-plus').click(); await expect(page.locator('div[role="alert"]')).toBeVisible(); @@ -36,10 +36,11 @@ test('Add contact, record gift, confirm gift', async ({ page }) => { // await page.locator('div[role="alert"] button:has-text("Yes")').click(); // Verify added contact - await expect(page.locator('li.border-b')).toContainText('did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F'); + await expect(page.locator('li.border-b')).toContainText('User #000'); // Rename contact - await page.locator('li.border-b h2 > button[title="Edit"]').click(); + await page.locator('li.border-b h2 > a[title="See more about this person"]').click(); + await page.locator('h2 > button[title="Edit"]').click(); await expect(page.locator('div.dialog-overlay > div.dialog').filter({ hasText: 'Edit Name' })).toBeVisible(); await page.getByPlaceholder('Name', { exact: true }).fill(contactName); await page.locator('.dialog > .flex > button').first().click();