4 changed files with 175 additions and 110 deletions
@ -0,0 +1,107 @@ |
|||
<template> |
|||
<div class="space-y-4"> |
|||
<!-- Loading State --> |
|||
<div v-if="isLoading" class="flex justify-center items-center py-8"> |
|||
<fa icon="spinner" class="fa-spin-pulse" /> |
|||
</div> |
|||
|
|||
<!-- Members List --> |
|||
<div v-else class="space-y-4"> |
|||
<div v-for="member in decryptedMembers" :key="member.memberId" |
|||
class="p-4 bg-gray-50 rounded-lg"> |
|||
<h3 class="text-lg font-medium">{{ member.name }}</h3> |
|||
<p class="text-sm text-gray-600">{{ member.did }}</p> |
|||
</div> |
|||
|
|||
<p v-if="members.length === 0" class="text-center text-gray-500 py-4"> |
|||
No members have joined this meeting yet |
|||
</p> |
|||
<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> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts"> |
|||
import { Component, Vue, Prop } from 'vue-facing-decorator'; |
|||
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from '@/db/index'; |
|||
import { errorStringForLog, getHeaders, serverMessageForUser } from '@/libs/endorserServer'; |
|||
import { decryptMessage } from '@/libs/crypto'; |
|||
|
|||
interface Member { |
|||
memberId: number; |
|||
content: string; |
|||
} |
|||
|
|||
interface DecryptedMember { |
|||
memberId: number; |
|||
name: string; |
|||
did: string; |
|||
} |
|||
|
|||
@Component |
|||
export default class MembersList extends Vue { |
|||
@Prop({ required: true }) password!: string; |
|||
@Prop({ default: 'Your password failed. Please go back and try again.' }) decryptFailureMessage!: string; |
|||
|
|||
decryptedMembers: DecryptedMember[] = []; |
|||
missingPassword = false; |
|||
isLoading = false; |
|||
members: Member[] = []; |
|||
activeDid = ''; |
|||
apiServer = ''; |
|||
|
|||
async created() { |
|||
const settings = await retrieveSettingsForActiveAccount(); |
|||
this.activeDid = settings.activeDid || ''; |
|||
this.apiServer = settings.apiServer || ''; |
|||
await this.fetchMembers(); |
|||
} |
|||
|
|||
async fetchMembers() { |
|||
this.isLoading = true; |
|||
try { |
|||
const headers = await getHeaders(this.activeDid); |
|||
const response = await this.axios.get( |
|||
`${this.apiServer}/api/partner/groupOnboardMembers/`, |
|||
{ headers } |
|||
); |
|||
|
|||
if (response.data && response.data.data) { |
|||
this.members = response.data.data; |
|||
await this.decryptMemberContents(); |
|||
} |
|||
} catch (error) { |
|||
logConsoleAndDb('Error fetching members: ' + errorStringForLog(error), true); |
|||
this.$emit('error', serverMessageForUser(error) || 'Failed to fetch members.'); |
|||
} finally { |
|||
this.isLoading = false; |
|||
} |
|||
} |
|||
|
|||
async decryptMemberContents() { |
|||
this.decryptedMembers = []; |
|||
|
|||
if (!this.password) { |
|||
this.missingPassword = true; |
|||
return; |
|||
} |
|||
|
|||
for (const member of this.members) { |
|||
try { |
|||
const decryptedContent = await decryptMessage(member.content, this.password); |
|||
const content = JSON.parse(decryptedContent); |
|||
|
|||
this.decryptedMembers.push({ |
|||
memberId: member.memberId, |
|||
name: content.name, |
|||
did: content.did, |
|||
}); |
|||
} catch (error) { |
|||
// do nothing, relying on the count of members to determine if there was an error |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
Loading…
Reference in new issue