|
|
@ -1,40 +1,41 @@ |
|
|
|
<template> |
|
|
|
<div class="space-y-4"> |
|
|
|
<!-- Loading State --> |
|
|
|
<div v-if="isLoading" class="flex justify-center items-center py-8"> |
|
|
|
<div |
|
|
|
v-if="isLoading" |
|
|
|
class="mt-16 text-center text-4xl bg-slate-400 text-white w-14 py-2.5 rounded-full mx-auto" |
|
|
|
> |
|
|
|
<fa icon="spinner" class="fa-spin-pulse" /> |
|
|
|
</div> |
|
|
|
|
|
|
|
<!-- Members List --> |
|
|
|
|
|
|
|
<p |
|
|
|
v-if="decryptedMembers.length < members.length" |
|
|
|
class="text-center text-red-600 py-4" |
|
|
|
> |
|
|
|
{{ |
|
|
|
decryptFailureMessage || |
|
|
|
"Your password failed. Please go back and try again." |
|
|
|
}} |
|
|
|
</p> |
|
|
|
<div v-else> |
|
|
|
<div class="text-center text-red-600 py-4"> |
|
|
|
{{ decryptionErrorMessage() }} |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-else class="space-y-4"> |
|
|
|
<div v-if="missingMyself" class="py-4 text-red-600"> |
|
|
|
You are not admitted. The organizer will admit you. |
|
|
|
You are not currently admitted by the organizer. |
|
|
|
</div> |
|
|
|
<div v-if="!firstName" class="py-4 text-red-600"> |
|
|
|
Your name is not set, so others may not recognize you. Reload this page |
|
|
|
to set it. |
|
|
|
</div> |
|
|
|
|
|
|
|
<div> |
|
|
|
<span |
|
|
|
v-if="showOrganizerTools && isOrganizer" |
|
|
|
v-if="membersToShow().length > 0 && showOrganizerTools && isOrganizer" |
|
|
|
class="inline-flex items-center flex-wrap" |
|
|
|
> |
|
|
|
<span class="inline-flex items-center"> |
|
|
|
Use |
|
|
|
• Click |
|
|
|
<span |
|
|
|
class="mx-2 min-w-[24px] min-h-[24px] w-6 h-6 flex items-center justify-center rounded-full bg-blue-100 text-blue-600" |
|
|
|
> |
|
|
|
<fa icon="plus" class="text-sm" /> |
|
|
|
</span> |
|
|
|
and |
|
|
|
/ |
|
|
|
<span |
|
|
|
class="mx-2 min-w-[24px] min-h-[24px] w-6 h-6 flex items-center justify-center rounded-full bg-blue-100 text-blue-600" |
|
|
|
> |
|
|
@ -45,8 +46,11 @@ |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<span class="inline-flex items-center"> |
|
|
|
Use |
|
|
|
<span |
|
|
|
v-if="membersToShow().length > 0" |
|
|
|
class="inline-flex items-center" |
|
|
|
> |
|
|
|
• Click |
|
|
|
<span |
|
|
|
class="mx-2 w-8 h-8 flex items-center justify-center rounded-full bg-green-100 text-green-600" |
|
|
|
> |
|
|
@ -56,7 +60,8 @@ |
|
|
|
</span> |
|
|
|
</div> |
|
|
|
|
|
|
|
<div v-if="members.length > 0" class="flex justify-center"> |
|
|
|
<div class="flex justify-center"> |
|
|
|
<!-- always have at least one refresh button even without members in case the organizer changes the password --> |
|
|
|
<button |
|
|
|
@click="fetchMembers" |
|
|
|
class="w-8 h-8 flex items-center justify-center rounded-full bg-blue-100 text-blue-600 hover:bg-blue-200 hover:text-blue-800 transition-colors" |
|
|
@ -68,7 +73,7 @@ |
|
|
|
<div |
|
|
|
v-for="member in membersToShow()" |
|
|
|
:key="member.member.memberId" |
|
|
|
class="p-4 bg-gray-50 rounded-lg" |
|
|
|
class="mt-2 p-4 bg-gray-50 rounded-lg" |
|
|
|
> |
|
|
|
<div class="flex items-center justify-between"> |
|
|
|
<div class="flex items-center"> |
|
|
@ -131,7 +136,7 @@ |
|
|
|
{{ member.did }} |
|
|
|
</p> |
|
|
|
</div> |
|
|
|
<div v-if="members.length > 0" class="flex justify-center mt-4"> |
|
|
|
<div v-if="membersToShow().length > 0" class="flex justify-center mt-4"> |
|
|
|
<button |
|
|
|
@click="fetchMembers" |
|
|
|
class="w-8 h-8 flex items-center justify-center rounded-full bg-blue-100 text-blue-600 hover:bg-blue-200 hover:text-blue-800 transition-colors" |
|
|
@ -187,16 +192,15 @@ export default class MembersList extends Vue { |
|
|
|
libsUtil = libsUtil; |
|
|
|
|
|
|
|
@Prop({ required: true }) password!: string; |
|
|
|
@Prop({ default: "Your password failed. Please go back and try again." }) |
|
|
|
decryptFailureMessage!: string; |
|
|
|
@Prop({ default: false }) showOrganizerTools!: boolean; |
|
|
|
|
|
|
|
decryptedMembers: DecryptedMember[] = []; |
|
|
|
missingPassword = false; |
|
|
|
missingMyself = false; |
|
|
|
isLoading = false; |
|
|
|
firstName = ""; |
|
|
|
isLoading = true; |
|
|
|
isOrganizer = false; |
|
|
|
members: Member[] = []; |
|
|
|
missingPassword = false; |
|
|
|
missingMyself = false; |
|
|
|
activeDid = ""; |
|
|
|
apiServer = ""; |
|
|
|
contacts: Array<Contact> = []; |
|
|
@ -205,13 +209,14 @@ export default class MembersList extends Vue { |
|
|
|
const settings = await retrieveSettingsForActiveAccount(); |
|
|
|
this.activeDid = settings.activeDid || ""; |
|
|
|
this.apiServer = settings.apiServer || ""; |
|
|
|
this.firstName = settings.firstName || ""; |
|
|
|
await this.fetchMembers(); |
|
|
|
await this.loadContacts(); |
|
|
|
} |
|
|
|
|
|
|
|
async fetchMembers() { |
|
|
|
this.isLoading = true; |
|
|
|
try { |
|
|
|
this.isLoading = true; |
|
|
|
const headers = await getHeaders(this.activeDid); |
|
|
|
const response = await this.axios.get( |
|
|
|
`${this.apiServer}/api/partner/groupOnboardMembers`, |
|
|
@ -274,6 +279,28 @@ export default class MembersList extends Vue { |
|
|
|
this.missingMyself = !foundMyself; |
|
|
|
} |
|
|
|
|
|
|
|
decryptionErrorMessage(): string { |
|
|
|
if (this.isOrganizer) { |
|
|
|
if (this.decryptedMembers.length < this.members.length) { |
|
|
|
return "Some members have data that cannot be decrypted with that password."; |
|
|
|
} else { |
|
|
|
// the lists must be equal |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// non-organizers should only see problems if the first (organizer) member is not decrypted |
|
|
|
if ( |
|
|
|
this.decryptedMembers.length === 0 || |
|
|
|
this.decryptedMembers[0].member.memberId !== this.members[0].memberId |
|
|
|
) { |
|
|
|
return "Your password is not the same as the organizer. Reload or have them check their password."; |
|
|
|
} else { |
|
|
|
// the first (organizer) member was decrypted OK |
|
|
|
return ""; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
membersToShow(): DecryptedMember[] { |
|
|
|
if (this.isOrganizer) { |
|
|
|
if (this.showOrganizerTools) { |
|
|
@ -356,7 +383,7 @@ export default class MembersList extends Vue { |
|
|
|
group: "modal", |
|
|
|
type: "confirm", |
|
|
|
title: "Continue Without Adding?", |
|
|
|
text: "Are you sure you want to proceed with admission even though they are not a contact?", |
|
|
|
text: "Are you sure you want to proceed with admission? If they are not a contact, you will not know their name after this meeting.", |
|
|
|
yesText: "Continue", |
|
|
|
onYes: async () => { |
|
|
|
await this.toggleAdmission(decrMember); |
|
|
|