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 @@
+
+
+
+
+
+ Admit Pending Members
+
+
+ The following members are waiting to be admitted to the meeting. You
+ can choose to admit them and optionally add them as contacts with
+ visibility settings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No pending members to admit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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();