diff --git a/src/components/AdmitPendingMembersDialog.vue b/src/components/AdmitPendingMembersDialog.vue new file mode 100644 index 00000000..d6cbd013 --- /dev/null +++ b/src/components/AdmitPendingMembersDialog.vue @@ -0,0 +1,458 @@ + + + + + diff --git a/src/components/MembersList.vue b/src/components/MembersList.vue index 1a5babbc..9b082312 100644 --- a/src/components/MembersList.vue +++ b/src/components/MembersList.vue @@ -177,6 +177,16 @@ + + + = []; + admitDialogDismissed = false; + isManualRefresh = false; + // Set Visibility Dialog state showSetVisibilityDialog = false; visibilityDialogMembers: Array<{ @@ -296,8 +319,13 @@ export default class MembersList extends Vue { // Start auto-refresh this.startAutoRefresh(); - // Check if we should show the visibility dialog on initial load - this.checkAndShowVisibilityDialog(); + // Check if we should show the admit pending members dialog first + this.checkAndShowAdmitPendingDialog(); + + // If no pending members, check for visibility dialog + if (!this.showAdmitPendingDialog) { + this.checkAndShowVisibilityDialog(); + } } async refreshData() { @@ -305,8 +333,13 @@ export default class MembersList extends Vue { await this.loadContacts(); await this.fetchMembers(); - // Check if we should show the visibility dialog after refresh - this.checkAndShowVisibilityDialog(); + // Check if we should show the admit pending members dialog first + this.checkAndShowAdmitPendingDialog(); + + // If no pending members, check for visibility dialog + if (!this.showAdmitPendingDialog) { + this.checkAndShowVisibilityDialog(); + } } async fetchMembers() { @@ -463,6 +496,26 @@ export default class MembersList extends Vue { return this.contacts.find((contact) => contact.did === did); } + getPendingMembers() { + return this.decryptedMembers + .filter((member) => { + // Exclude the current user + if (member.did === this.activeDid) { + return false; + } + // Only include non-admitted members + return !member.member.admitted; + }) + .map((member) => ({ + did: member.did, + name: member.name, + isContact: !!this.getContactFor(member.did), + member: { + memberId: member.member.memberId.toString(), + }, + })); + } + getMembersForVisibility() { return this.decryptedMembers .filter((member) => { @@ -492,7 +545,8 @@ export default class MembersList extends Vue { * Check if we should show the visibility dialog * Returns true if there are members for visibility and either: * - This is the first time (no previous members tracked), OR - * - New members have been added since last check (not removed) + * - New members have been added since last check (not removed), OR + * - This is a manual refresh (isManualRefresh flag is set) */ shouldShowVisibilityDialog(): boolean { const currentMembers = this.getMembersForVisibility(); @@ -506,6 +560,11 @@ export default class MembersList extends Vue { return true; } + // If this is a manual refresh, always show dialog if there are members + if (this.isManualRefresh) { + return true; + } + // Check if new members have been added (not just any change) const currentMemberIds = currentMembers.map((m) => m.did); const previousMemberIds = this.previousVisibilityMembers; @@ -527,6 +586,31 @@ export default class MembersList extends Vue { this.previousVisibilityMembers = currentMembers.map((m) => m.did); } + /** + * Check if we should show the admit pending members dialog + */ + shouldShowAdmitPendingDialog(): boolean { + // Don't show if already dismissed + if (this.admitDialogDismissed) { + return false; + } + + const pendingMembers = this.getPendingMembers(); + return pendingMembers.length > 0; + } + + /** + * Show the admit pending members dialog if conditions are met + */ + checkAndShowAdmitPendingDialog() { + if (this.shouldShowAdmitPendingDialog()) { + this.showAdmitPendingDialogMethod(); + } else { + // Ensure dialog state is false when no pending members + this.showAdmitPendingDialog = false; + } + } + /** * Show the visibility dialog if conditions are met */ @@ -675,6 +759,24 @@ export default class MembersList extends Vue { } } + showAdmitPendingDialogMethod() { + // Filter members to show only pending (non-admitted) members + const pendingMembers = this.getPendingMembers(); + + // Only show dialog if there are pending members + if (pendingMembers.length === 0) { + this.showAdmitPendingDialog = false; + return; + } + + // Pause auto-refresh when dialog opens + this.stopAutoRefresh(); + + // Open the dialog directly + this.pendingMembersData = pendingMembers; + this.showAdmitPendingDialog = true; + } + showSetBulkVisibilityDialog() { // Filter members to show only those who need visibility set const membersForVisibility = this.getMembersForVisibility(); @@ -682,6 +784,9 @@ export default class MembersList extends Vue { // Pause auto-refresh when dialog opens this.stopAutoRefresh(); + // Reset manual refresh flag when showing visibility dialog + this.isManualRefresh = false; + // Open the dialog directly this.visibilityDialogMembers = membersForVisibility; this.showSetVisibilityDialog = true; @@ -717,28 +822,72 @@ export default class MembersList extends Vue { } } - manualRefresh() { + async manualRefresh() { // Clear existing auto-refresh interval if (this.autoRefreshInterval) { clearInterval(this.autoRefreshInterval); this.autoRefreshInterval = null; } - // Trigger immediate refresh and restart timer - this.refreshData(); - this.startAutoRefresh(); + // Set manual refresh flag + this.isManualRefresh = true; + // Reset the dismissed flag on manual refresh + this.admitDialogDismissed = false; - // Always show dialog on manual refresh if there are members for visibility - if (this.getMembersForVisibility().length > 0) { - this.showSetBulkVisibilityDialog(); + // Trigger immediate refresh + await this.refreshData(); + + // Only start auto-refresh if no dialogs are showing + if (!this.showAdmitPendingDialog && !this.showSetVisibilityDialog) { + this.startAutoRefresh(); } } + // Admit Pending Members Dialog methods + async closeAdmitPendingDialog() { + this.showAdmitPendingDialog = false; + this.pendingMembersData = []; + this.admitDialogDismissed = true; + + // Handle manual refresh flow + if (this.isManualRefresh) { + await this.handleManualRefreshFlow(); + this.isManualRefresh = false; + } else { + // Normal flow: refresh data and resume auto-refresh + this.refreshData(); + this.startAutoRefresh(); + } + } + + async handleManualRefreshFlow() { + // Refresh data to reflect any changes made in the admit dialog + await this.refreshData(); + + // Use the same logic as normal flow to check for visibility dialog + this.checkAndShowVisibilityDialog(); + + // If no visibility dialog was shown, resume auto-refresh + if (!this.showSetVisibilityDialog) { + this.startAutoRefresh(); + } + } + + async onAdmitPendingSuccess(_result: { + admittedCount: number; + contactAddedCount: number; + visibilitySetCount: number; + }) { + // After admitting pending members, close the admit dialog + // The visibility dialog will be handled by the closeAdmitPendingDialog flow + await this.closeAdmitPendingDialog(); + } + // Set Visibility Dialog methods closeSetVisibilityDialog() { this.showSetVisibilityDialog = false; this.visibilityDialogMembers = []; - // Refresh data when dialog is closed + // Refresh data when dialog is closed to reflect any changes made this.refreshData(); // Resume auto-refresh when dialog is closed this.startAutoRefresh();