forked from trent_larson/crowd-funder-for-time-pwa
fix alert when looking at one's own activity
This commit is contained in:
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.?]
|
||||||
|
### Added
|
||||||
|
- Separate 'isRegistered' flag for each account
|
||||||
|
### Fixed
|
||||||
|
- Alert when looking at one's own activity if not in contacts.
|
||||||
|
|
||||||
|
|
||||||
## [0.3.25] - 2024.08.30 - dcbe02d877aecb4cdef2643d90e6595d246a9f82
|
## [0.3.25] - 2024.08.30 - dcbe02d877aecb4cdef2643d90e6595d246a9f82
|
||||||
### Added
|
### Added
|
||||||
- "Ideas" now jumps directly to giving prompt or contact list.
|
- "Ideas" now jumps directly to giving prompt or contact list.
|
||||||
|
|||||||
@@ -19,14 +19,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Identity Details -->
|
<!-- Identity Details -->
|
||||||
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
<div
|
||||||
|
v-if="!!contactFromDid"
|
||||||
|
class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-xl font-semibold">
|
<h2 class="text-xl font-semibold">
|
||||||
{{ contact?.name || "(no name)" }}
|
{{ contactFromDid?.name || "(no name)" }}
|
||||||
<button
|
<button
|
||||||
@click="
|
@click="
|
||||||
contactEdit = true;
|
contactEdit = true;
|
||||||
contactNewName = contact.name || '';
|
contactNewName = (contactFromDid?.name as string) || '';
|
||||||
"
|
"
|
||||||
title="Edit"
|
title="Edit"
|
||||||
>
|
>
|
||||||
@@ -49,12 +52,15 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center mt-4">
|
<div class="flex justify-center mt-4">
|
||||||
<span v-if="contact?.profileImageUrl" class="flex justify-between">
|
<span
|
||||||
|
v-if="contactFromDid?.profileImageUrl"
|
||||||
|
class="flex justify-between"
|
||||||
|
>
|
||||||
<EntityIcon
|
<EntityIcon
|
||||||
:icon-size="96"
|
:icon-size="96"
|
||||||
:profileImageUrl="contact?.profileImageUrl"
|
:profileImageUrl="contactFromDid?.profileImageUrl"
|
||||||
class="inline-block align-text-bottom border border-slate-300 rounded"
|
class="inline-block align-text-bottom border border-slate-300 rounded"
|
||||||
@click="showLargeIdenticonUrl = contact?.profileImageUrl"
|
@click="showLargeIdenticonUrl = contactFromDid?.profileImageUrl"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -63,17 +69,21 @@
|
|||||||
<div v-if="activeDid" class="flex justify-between">
|
<div v-if="activeDid" class="flex justify-between">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
v-if="contact?.seesMe && contact.did !== activeDid"
|
v-if="
|
||||||
|
contactFromDid?.seesMe && contactFromDid.did !== activeDid
|
||||||
|
"
|
||||||
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
||||||
@click="confirmSetVisibility(contact, false)"
|
@click="confirmSetVisibility(contactFromDid, false)"
|
||||||
title="They can see you"
|
title="They can see you"
|
||||||
>
|
>
|
||||||
<fa icon="eye" class="fa-fw" />
|
<fa icon="eye" class="fa-fw" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-else-if="!contact?.seesMe && contact?.did !== activeDid"
|
v-else-if="
|
||||||
|
!contactFromDid?.seesMe && contactFromDid?.did !== activeDid
|
||||||
|
"
|
||||||
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
||||||
@click="confirmSetVisibility(contact, true)"
|
@click="confirmSetVisibility(contactFromDid, true)"
|
||||||
title="They cannot see you"
|
title="They cannot see you"
|
||||||
>
|
>
|
||||||
<fa icon="eye-slash" class="fa-fw" />
|
<fa icon="eye-slash" class="fa-fw" />
|
||||||
@@ -83,9 +93,9 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
||||||
@click="checkVisibility(contact)"
|
@click="checkVisibility(contactFromDid)"
|
||||||
title="Check Visibility"
|
title="Check Visibility"
|
||||||
v-if="contact?.did !== activeDid"
|
v-if="contactFromDid?.did !== activeDid"
|
||||||
>
|
>
|
||||||
<fa icon="rotate" class="fa-fw" />
|
<fa icon="rotate" class="fa-fw" />
|
||||||
</button>
|
</button>
|
||||||
@@ -94,13 +104,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@click="confirmRegister(contact)"
|
@click="confirmRegister(contactFromDid)"
|
||||||
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-6 mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
class="text-sm uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-6 mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
||||||
v-if="contact?.did !== activeDid"
|
v-if="contactFromDid?.did !== activeDid"
|
||||||
title="Registration"
|
title="Registration"
|
||||||
>
|
>
|
||||||
<fa
|
<fa
|
||||||
v-if="contact?.registered"
|
v-if="contactFromDid?.registered"
|
||||||
icon="person-circle-check"
|
icon="person-circle-check"
|
||||||
class="fa-fw"
|
class="fa-fw"
|
||||||
/>
|
/>
|
||||||
@@ -111,14 +121,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@click="confirmDeleteContact(contact)"
|
@click="confirmDeleteContact(contactFromDid)"
|
||||||
class="text-sm uppercase bg-gradient-to-b from-rose-500 to-rose-800 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-6 mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
class="text-sm uppercase bg-gradient-to-b from-rose-500 to-rose-800 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white ml-6 mx-0.5 my-0.5 px-2 py-1.5 rounded-md"
|
||||||
title="Delete"
|
title="Delete"
|
||||||
>
|
>
|
||||||
<fa icon="trash-can" class="fa-fw" />
|
<fa icon="trash-can" class="fa-fw" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!contact?.profileImageUrl">
|
<div v-if="!contactFromDid?.profileImageUrl">
|
||||||
<div>Auto-Generated Icon</div>
|
<div>Auto-Generated Icon</div>
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<EntityIcon
|
<EntityIcon
|
||||||
@@ -150,6 +160,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
||||||
|
<!-- !contactFromDid -->
|
||||||
|
<div>
|
||||||
|
<h2 class="text-xl font-semibold">
|
||||||
|
{{ isMyDid ? "You" : "(no name)" }}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="contactEdit" class="dialog-overlay">
|
<div v-if="contactEdit" class="dialog-overlay">
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<h1 class="text-xl font-bold text-center mb-4">Edit Name</h1>
|
<h1 class="text-xl font-bold text-center mb-4">Edit Name</h1>
|
||||||
@@ -222,7 +241,8 @@
|
|||||||
v-if="!isLoading && claims.length === 0"
|
v-if="!isLoading && claims.length === 0"
|
||||||
class="flex justify-center mt-4"
|
class="flex justify-center mt-4"
|
||||||
>
|
>
|
||||||
<span>They are in no claims visible to you.</span>
|
<span v-if="isMyDid">You have no claims yet.</span>
|
||||||
|
<span v-else>They are in no claims visible to you.</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -270,15 +290,15 @@ export default class DIDView extends Vue {
|
|||||||
yaml = yaml;
|
yaml = yaml;
|
||||||
|
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
allMyDids: Array<string> = [];
|
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
claims: Array<GenericCredWrapper<GenericVerifiableCredential>> = [];
|
claims: Array<GenericCredWrapper<GenericVerifiableCredential>> = [];
|
||||||
contact: Contact;
|
contactFromDid?: Contact;
|
||||||
contactEdit = false;
|
contactEdit = false;
|
||||||
contactNewName?: string;
|
contactNewName: string = "";
|
||||||
contactYaml = "";
|
contactYaml = "";
|
||||||
hitEnd = false;
|
hitEnd = false;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
isMyDid = false;
|
||||||
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
||||||
showDidDetails = false;
|
showDidDetails = false;
|
||||||
showLargeIdenticonId?: string;
|
showLargeIdenticonId?: string;
|
||||||
@@ -295,32 +315,23 @@ export default class DIDView extends Vue {
|
|||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
|
|
||||||
const pathParam = window.location.pathname.substring("/did/".length);
|
const pathParam = window.location.pathname.substring("/did/".length);
|
||||||
let theContact: Contact | undefined;
|
|
||||||
if (pathParam) {
|
if (pathParam) {
|
||||||
this.viewingDid = decodeURIComponent(pathParam);
|
this.viewingDid = decodeURIComponent(pathParam);
|
||||||
theContact = await db.contacts.get(this.viewingDid);
|
this.contactFromDid = await db.contacts.get(this.viewingDid);
|
||||||
}
|
if (this.contactFromDid) {
|
||||||
if (theContact) {
|
this.contactYaml = yaml.dump(this.contactFromDid);
|
||||||
this.contact = theContact;
|
}
|
||||||
} else {
|
await this.loadClaimsAbout();
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: "No valid claim ID was provided.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.contactYaml = yaml.dump(this.contact);
|
await accountsDB.open();
|
||||||
await this.loadClaimsAbout();
|
const allAccounts = await accountsDB.accounts.toArray();
|
||||||
|
for (const account of allAccounts) {
|
||||||
await accountsDB.open();
|
if (account.did === this.viewingDid) {
|
||||||
const allAccounts = await accountsDB.accounts.toArray();
|
this.isMyDid = true;
|
||||||
this.allMyDids = allAccounts.map((acc) => acc.did);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -376,7 +387,7 @@ export default class DIDView extends Vue {
|
|||||||
title: "Register",
|
title: "Register",
|
||||||
text:
|
text:
|
||||||
"Are you sure you want to register " +
|
"Are you sure you want to register " +
|
||||||
libsUtil.nameForContact(this.contact, false) +
|
libsUtil.nameForContact(this.contactFromDid, false) +
|
||||||
(contact.registered
|
(contact.registered
|
||||||
? " -- especially since they are already marked as registered"
|
? " -- especially since they are already marked as registered"
|
||||||
: "") +
|
: "") +
|
||||||
@@ -557,9 +568,21 @@ export default class DIDView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async onClickSaveName(newName: string) {
|
private async onClickSaveName(newName: string) {
|
||||||
this.contact.name = newName;
|
if (!this.contactFromDid) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Not A Contact",
|
||||||
|
text: "First add this on the contact page, then you can edit here.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.contactFromDid.name = newName;
|
||||||
return db.contacts
|
return db.contacts
|
||||||
.update(this.contact.did, { name: newName })
|
.update(this.contactFromDid.did, { name: newName })
|
||||||
.then(() => (this.contactEdit = false));
|
.then(() => (this.contactEdit = false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { generateEthrUser, importUser } from './testUtils';
|
import { deleteContact, generateEthrUser, importUser } from './testUtils';
|
||||||
|
|
||||||
test('Check activity feed', async ({ page }) => {
|
test('Check activity feed', async ({ page }) => {
|
||||||
// Load app homepage
|
// Load app homepage
|
||||||
@@ -123,4 +123,20 @@ test('Check User 0 can register a random person', async ({ page }) => {
|
|||||||
// now ensure that alert goes away
|
// now ensure that alert goes away
|
||||||
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss alert
|
await page.locator('div[role="alert"] button > svg.fa-xmark').click(); // dismiss alert
|
||||||
await expect(page.getByText('That gift was recorded.')).toBeHidden();
|
await expect(page.getByText('That gift was recorded.')).toBeHidden();
|
||||||
|
|
||||||
|
// now delete the contact to test that pages still do reasonable things
|
||||||
|
await deleteContact(page, newDid);
|
||||||
|
// go the activity page for this new person
|
||||||
|
await page.goto('./did/' + encodeURIComponent(newDid));
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await page.waitForSelector('div[role="alert"]', { timeout: 2000 });
|
||||||
|
error = new Error('Error alert should not show.');
|
||||||
|
} catch (error) {
|
||||||
|
// success
|
||||||
|
} finally {
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,6 +40,22 @@ export async function switchToUser(page: Page, did: string): Promise<void> {
|
|||||||
await page.getByRole('code', { name: did }).click();
|
await page.getByRole('code', { name: did }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createContactName(did: string): string {
|
||||||
|
return "User " + did.slice(11, 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteContact(page: Page, did: string): Promise<void> {
|
||||||
|
await page.goto('./contacts');
|
||||||
|
const contactName = createContactName(did);
|
||||||
|
// go to the detail page for this contact
|
||||||
|
await page.locator(`li[data-testid="contactListItem"] h2:has-text("${contactName}") + a`).click();
|
||||||
|
// delete the contact
|
||||||
|
await page.locator('button > svg.fa-trash-can').click();
|
||||||
|
await page.locator('div[role="alert"] button:has-text("Yes")').click();
|
||||||
|
// for some reason, .isHidden() (without expect) doesn't work
|
||||||
|
await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a new random user and register them.
|
// Generate a new random user and register them.
|
||||||
// Note that this makes 000 the active user. Use switchToUser to switch to this DID.
|
// Note that this makes 000 the active user. Use switchToUser to switch to this DID.
|
||||||
export async function generateEthrUser(page: Page): Promise<string> {
|
export async function generateEthrUser(page: Page): Promise<string> {
|
||||||
@@ -55,10 +71,10 @@ export async function generateEthrUser(page: Page): Promise<string> {
|
|||||||
await importUser(page, '000'); // switch to user 000
|
await importUser(page, '000'); // switch to user 000
|
||||||
|
|
||||||
await page.goto('./contacts');
|
await page.goto('./contacts');
|
||||||
const threeChars = newDid.slice(11, 14);
|
const contactName = createContactName(newDid);
|
||||||
await page.getByPlaceholder('URL or DID, Name, Public Key').fill(`${newDid}, User ${threeChars}`);
|
await page.getByPlaceholder('URL or DID, Name, Public Key').fill(`${newDid}, ${contactName}`);
|
||||||
await page.locator('button > svg.fa-plus').click();
|
await page.locator('button > svg.fa-plus').click();
|
||||||
await page.locator('li', { hasText: threeChars }).click();
|
await page.locator('li', { hasText: contactName }).click();
|
||||||
// register them
|
// register them
|
||||||
await page.locator('div[role="alert"] button:has-text("Yes")').click();
|
await page.locator('div[role="alert"] button:has-text("Yes")').click();
|
||||||
// wait for it to disappear because the next steps may depend on alerts being gone
|
// wait for it to disappear because the next steps may depend on alerts being gone
|
||||||
|
|||||||
Reference in New Issue
Block a user