From e9ea89edae7bb2f35a5080865d078b006610e49b Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Tue, 21 Oct 2025 18:13:10 +0800
Subject: [PATCH 01/26] feat: enhance members list UI with visual indicators
and improved styling
- Sort members list with organizer first, then non-admitted, then admitted
- Add crown icon for meeting organizer identification
- Add spinner icon for non-admitted members
- Implement conditional styling for non-admitted members
- Update button styling to use circle icons instead of rounded backgrounds
- Improve visual hierarchy with better spacing and color coding
---
src/components/MembersList.vue | 114 +++++++++++++++++++++++----------
src/libs/fontawesome.ts | 4 ++
2 files changed, 84 insertions(+), 34 deletions(-)
diff --git a/src/components/MembersList.vue b/src/components/MembersList.vue
index e26613bf..fe54b8d1 100644
--- a/src/components/MembersList.vue
+++ b/src/components/MembersList.vue
@@ -28,26 +28,14 @@
v-if="membersToShow().length > 0 && showOrganizerTools && isOrganizer"
>
Click
-
-
-
+
/
-
-
-
+
to add/remove them to/from the meeting.
@@ -378,17 +394,44 @@ export default class MembersList extends Vue {
}
membersToShow(): DecryptedMember[] {
+ let members: DecryptedMember[] = [];
+
if (this.isOrganizer) {
if (this.showOrganizerTools) {
- return this.decryptedMembers;
+ members = this.decryptedMembers;
} else {
- return this.decryptedMembers.filter(
+ members = this.decryptedMembers.filter(
(member: DecryptedMember) => member.member.admitted,
);
}
+ } else {
+ // non-organizers only get visible members from server
+ members = this.decryptedMembers;
}
- // non-organizers only get visible members from server
- return this.decryptedMembers;
+
+ // Sort members according to priority:
+ // 1. Organizer at the top
+ // 2. Non-admitted members next
+ // 3. Everyone else after
+ return members.sort((a, b) => {
+ // Check if either member is the organizer (first member in original list)
+ const aIsOrganizer = a.member.memberId === this.members[0]?.memberId;
+ const bIsOrganizer = b.member.memberId === this.members[0]?.memberId;
+
+ // Organizer always comes first
+ if (aIsOrganizer && !bIsOrganizer) return -1;
+ if (!aIsOrganizer && bIsOrganizer) return 1;
+
+ // If both are organizers or neither are organizers, sort by admission status
+ if (aIsOrganizer && bIsOrganizer) return 0; // Both organizers, maintain original order
+
+ // Non-admitted members come before admitted members
+ if (!a.member.admitted && b.member.admitted) return -1;
+ if (a.member.admitted && !b.member.admitted) return 1;
+
+ // If admission status is the same, maintain original order
+ return 0;
+ });
}
informAboutAdmission() {
@@ -718,23 +761,26 @@ export default class MembersList extends Vue {
.btn-add-contact {
/* stylelint-disable-next-line at-rule-no-unknown */
- @apply w-6 h-6 flex items-center justify-center rounded-full
- bg-green-100 text-green-600 hover:bg-green-200 hover:text-green-800
+ @apply text-lg text-green-600 hover:text-green-800
transition-colors;
}
.btn-info-contact,
.btn-info-admission {
/* stylelint-disable-next-line at-rule-no-unknown */
- @apply w-6 h-6 flex items-center justify-center rounded-full
- bg-slate-100 text-slate-400 hover:text-slate-600
+ @apply text-slate-400 hover:text-slate-600
transition-colors;
}
-.btn-admission {
+.btn-admission-add {
/* stylelint-disable-next-line at-rule-no-unknown */
- @apply w-6 h-6 flex items-center justify-center rounded-full
- bg-blue-100 text-blue-600 hover:bg-blue-200 hover:text-blue-800
+ @apply text-lg text-blue-500 hover:text-blue-700
+ transition-colors;
+}
+
+.btn-admission-remove {
+ /* stylelint-disable-next-line at-rule-no-unknown */
+ @apply text-lg text-rose-500 hover:text-rose-700
transition-colors;
}
diff --git a/src/libs/fontawesome.ts b/src/libs/fontawesome.ts
index efd8ff03..b2e1ad13 100644
--- a/src/libs/fontawesome.ts
+++ b/src/libs/fontawesome.ts
@@ -29,6 +29,7 @@ import {
faCircle,
faCircleCheck,
faCircleInfo,
+ faCircleMinus,
faCirclePlus,
faCircleQuestion,
faCircleRight,
@@ -37,6 +38,7 @@ import {
faCoins,
faComment,
faCopy,
+ faCrown,
faDollar,
faDownload,
faEllipsis,
@@ -123,6 +125,7 @@ library.add(
faCircle,
faCircleCheck,
faCircleInfo,
+ faCircleMinus,
faCirclePlus,
faCircleQuestion,
faCircleRight,
@@ -131,6 +134,7 @@ library.add(
faCoins,
faComment,
faCopy,
+ faCrown,
faDollar,
faDownload,
faEllipsis,
From 035509224b46badc62ff05a3b6dc50012051e912 Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Tue, 21 Oct 2025 22:00:21 +0800
Subject: [PATCH 02/26] feat: change icon for pending members
- Changed from an animating spinner to a static hourglass
---
src/components/MembersList.vue | 4 ++--
src/libs/fontawesome.ts | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/components/MembersList.vue b/src/components/MembersList.vue
index fe54b8d1..1a5babbc 100644
--- a/src/components/MembersList.vue
+++ b/src/components/MembersList.vue
@@ -86,8 +86,8 @@
/>
{{ member.name || unnamedMember }}
diff --git a/src/libs/fontawesome.ts b/src/libs/fontawesome.ts
index b2e1ad13..947833e6 100644
--- a/src/libs/fontawesome.ts
+++ b/src/libs/fontawesome.ts
@@ -60,6 +60,7 @@ import {
faHand,
faHandHoldingDollar,
faHandHoldingHeart,
+ faHourglassHalf,
faHouseChimney,
faImage,
faImagePortrait,
@@ -156,6 +157,7 @@ library.add(
faHand,
faHandHoldingDollar,
faHandHoldingHeart,
+ faHourglassHalf,
faHouseChimney,
faImage,
faImagePortrait,
From 6fbc9c2a5b772138a3af04965035246ba569cfa8 Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Wed, 22 Oct 2025 21:56:00 +0800
Subject: [PATCH 03/26] feat: Add AdmitPendingMembersDialog for bulk member
admission
- Add new AdmitPendingMembersDialog component with checkbox selection
- Support two action modes: "Admit + Add Contacts" and "Admit Only"
- Integrate dialog into MembersList with proper sequencing
- Show admit dialog before visibility dialog when pending members exist
- Fix auto-refresh pause/resume logic for both dialogs
- Ensure consistent dialog behavior between initial load and manual refresh
- Add proper async/await handling for data refresh operations
- Optimize dialog state management and remove redundant code
- Maintain proper flag timing to prevent race conditions
The admit dialog now shows automatically when there are pending members,
allowing organizers to efficiently admit multiple members at once while
optionally adding them as contacts and setting visibility preferences.
---
src/components/AdmitPendingMembersDialog.vue | 458 +++++++++++++++++++
src/components/MembersList.vue | 175 ++++++-
2 files changed, 620 insertions(+), 13 deletions(-)
create mode 100644 src/components/AdmitPendingMembersDialog.vue
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();
From ad51c187aa6e1e41522187c2e26462f79094c1e8 Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Thu, 23 Oct 2025 19:59:55 +0800
Subject: [PATCH 04/26] Update AdmitPendingMembersDialog.vue
feat: add DID display to Pending Members dialog
- Restructure member display with better visual hierarchy
- Add DID display with responsive truncation for mobile
- Simplify button labels ("Admit + Add Contacts" and "Admit Only")
---
src/components/AdmitPendingMembersDialog.vue | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/components/AdmitPendingMembersDialog.vue b/src/components/AdmitPendingMembersDialog.vue
index d6cbd013..ca668cbd 100644
--- a/src/components/AdmitPendingMembersDialog.vue
+++ b/src/components/AdmitPendingMembersDialog.vue
@@ -52,7 +52,21 @@
:checked="isMemberSelected(member.did)"
@change="toggleMemberSelection(member.did)"
/>
- {{ member.name || SOMEONE_UNNAMED }}
+
From b37051f25d7349cb75a2d89624a2153a33c31b69 Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Wed, 29 Oct 2025 18:21:32 +0800
Subject: [PATCH 25/26] refactor: unify member dialogs into reusable
BulkMembersDialog component
- Merge AdmitPendingMembersDialog and SetBulkVisibilityDialog into single BulkMembersDialog
- Add dynamic props for dialog type, title, description, button text, and empty state
- Support both 'admit' and 'visibility' modes with conditional behavior
- Rename setVisibilityForSelectedMembers to addContactWithVisibility for clarity
- Update success counting to track contacts added vs visibility set
- Improve error messages to reflect primary action of adding contacts
- Update MembersList to use unified dialog with role-based configuration
- Remove unused libsUtil import from MembersList
- Update comments and method names to reflect unified functionality
- Rename closeMemberSelectionDialogCallback to closeBulkMembersDialogCallback
This consolidation eliminates ~200 lines of duplicate code while maintaining
all existing functionality and improving maintainability through a single
source of truth for bulk member operations.
---
...embersDialog.vue => BulkMembersDialog.vue} | 100 +++++-
src/components/MembersList.vue | 58 ++--
src/components/SetBulkVisibilityDialog.vue | 324 ------------------
3 files changed, 114 insertions(+), 368 deletions(-)
rename src/components/{AdmitPendingMembersDialog.vue => BulkMembersDialog.vue} (78%)
delete mode 100644 src/components/SetBulkVisibilityDialog.vue
diff --git a/src/components/AdmitPendingMembersDialog.vue b/src/components/BulkMembersDialog.vue
similarity index 78%
rename from src/components/AdmitPendingMembersDialog.vue
rename to src/components/BulkMembersDialog.vue
index 8b6a6662..d93a3069 100644
--- a/src/components/AdmitPendingMembersDialog.vue
+++ b/src/components/BulkMembersDialog.vue
@@ -3,18 +3,18 @@
- Admit Pending Members
+ {{ title }}
- Would you like to admit these members to the meeting and add them to
- your contacts?
+ {{ description }}
-
+
+
@@ -31,14 +31,15 @@
-
+
- No pending members to admit
+ {{ emptyStateText }}
+
+
@@ -97,20 +99,23 @@
+
+
- Admit + Add to Contacts
+ {{ buttonText }}
+
@@ -282,6 +300,61 @@ export default class AdmitPendingMembersDialog extends Vue {
}
}
+ async addContactWithVisibility() {
+ try {
+ const selectedMembers = this.membersData.filter((member) =>
+ this.selectedMembers.includes(member.did),
+ );
+ const notSelectedMembers = this.membersData.filter(
+ (member) => !this.selectedMembers.includes(member.did),
+ );
+
+ let contactsAddedCount = 0;
+
+ for (const member of selectedMembers) {
+ try {
+ // If they're not a contact yet, add them as a contact first
+ if (!member.isContact) {
+ await this.addAsContact(member);
+ contactsAddedCount++;
+ }
+
+ // Set their seesMe to true
+ await this.updateContactVisibility(member.did, true);
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error(`Error processing member ${member.did}:`, error);
+ // Continue with other members even if one fails
+ }
+ }
+
+ // Show success notification
+ this.$notify(
+ {
+ group: "alert",
+ type: "success",
+ title: "Contacts Added Successfully",
+ text: `${contactsAddedCount} member${contactsAddedCount === 1 ? "" : "s"} added as contact${contactsAddedCount === 1 ? "" : "s"}.`,
+ },
+ 5000,
+ );
+
+ this.close(notSelectedMembers.map((member) => member.did));
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.error("Error adding contacts:", error);
+ this.$notify(
+ {
+ group: "alert",
+ type: "danger",
+ title: "Error",
+ text: "Failed to add some members as contacts. Please try again.",
+ },
+ 5000,
+ );
+ }
+ }
+
async admitMember(member: {
did: string;
name: string;
@@ -348,12 +421,17 @@ export default class AdmitPendingMembersDialog extends Vue {
}
showContactInfo() {
+ const message =
+ this.dialogType === "admit"
+ ? "This user is already your contact, but they are not yet admitted to the meeting."
+ : "This user is already your contact, but your activities are not visible to them yet.";
+
this.$notify(
{
group: "alert",
type: "info",
title: "Contact Info",
- text: "This user is already your contact, but they are not yet admitted to the meeting.",
+ text: message,
},
5000,
);
diff --git a/src/components/MembersList.vue b/src/components/MembersList.vue
index 81963dad..dc533d82 100644
--- a/src/components/MembersList.vue
+++ b/src/components/MembersList.vue
@@ -197,22 +197,25 @@
-
-
+
-
-
@@ -235,11 +238,9 @@ import {
import { decryptMessage } from "@/libs/crypto";
import { Contact } from "@/db/tables/contacts";
import { MemberData } from "@/interfaces";
-import * as libsUtil from "@/libs/util";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
-import AdmitPendingMembersDialog from "./AdmitPendingMembersDialog.vue";
-import SetBulkVisibilityDialog from "./SetBulkVisibilityDialog.vue";
+import BulkMembersDialog from "./BulkMembersDialog.vue";
interface Member {
admitted: boolean;
@@ -256,8 +257,7 @@ interface DecryptedMember {
@Component({
components: {
- AdmitPendingMembersDialog,
- SetBulkVisibilityDialog,
+ BulkMembersDialog,
},
mixins: [PlatformServiceMixin],
})
@@ -265,7 +265,6 @@ export default class MembersList extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
notify!: ReturnType;
- libsUtil = libsUtil;
@Prop({ required: true }) password!: string;
@Prop({ default: false }) showOrganizerTools!: boolean;
@@ -532,7 +531,8 @@ export default class MembersList extends Vue {
}
/**
- * Show the admit pending members dialog if conditions are met
+ * Show the bulk members dialog if conditions are met
+ * (admit pending members for organizers, add to contacts for non-organizers)
*/
async refreshData(bypassPromptIfAllWereIgnored = true) {
// Force refresh both contacts and members
@@ -547,7 +547,7 @@ export default class MembersList extends Vue {
return;
}
if (bypassPromptIfAllWereIgnored) {
- // only show if there are pending members that have not been ignored
+ // only show if there are members that have not been ignored
const pendingMembersNotIgnored = pendingMembers.filter(
(member) => !this.previousMemberDidsIgnored.includes(member.did),
);
@@ -558,19 +558,11 @@ export default class MembersList extends Vue {
}
}
this.stopAutoRefresh();
- if (this.isOrganizer) {
- (this.$refs.admitPendingMembersDialog as AdmitPendingMembersDialog).open(
- pendingMembers,
- );
- } else {
- (this.$refs.setBulkVisibilityDialog as SetBulkVisibilityDialog).open(
- pendingMembers,
- );
- }
+ (this.$refs.bulkMembersDialog as BulkMembersDialog).open(pendingMembers);
}
- // Admit Pending Members Dialog methods
- async closeMemberSelectionDialogCallback(
+ // Bulk Members Dialog methods
+ async closeBulkMembersDialogCallback(
result: { notSelectedMemberDids: string[] } | undefined,
) {
this.previousMemberDidsIgnored = result?.notSelectedMemberDids || [];
diff --git a/src/components/SetBulkVisibilityDialog.vue b/src/components/SetBulkVisibilityDialog.vue
deleted file mode 100644
index 2effd010..00000000
--- a/src/components/SetBulkVisibilityDialog.vue
+++ /dev/null
@@ -1,324 +0,0 @@
-
-
-
-
-
- Add Members to Contacts
-
-
- Would you like to add these members to your contacts?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No members are not in your contacts
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Add to Contacts
-
-
- Maybe Later
-
-
-
-
-
-
-
-
From 9628d5c8c62cc6de7fa96869dbb70a69dfa74232 Mon Sep 17 00:00:00 2001
From: Jose Olarte III
Date: Thu, 30 Oct 2025 16:11:45 +0800
Subject: [PATCH 26/26] refactor: move display text logic to BulkMembersDialog
component
- Replace individual text props with single isOrganizer boolean prop
- Add computed properties for title, description, buttonText, and emptyStateText
- Simplify parent component interface by removing text prop passing
- Update quote style from single to double quotes for consistency
- Improve component encapsulation and maintainability
---
src/components/BulkMembersDialog.vue | 27 +++++++++++++++++++++++----
src/components/MembersList.vue | 13 +------------
2 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/src/components/BulkMembersDialog.vue b/src/components/BulkMembersDialog.vue
index d93a3069..dd41e474 100644
--- a/src/components/BulkMembersDialog.vue
+++ b/src/components/BulkMembersDialog.vue
@@ -145,10 +145,7 @@ export default class BulkMembersDialog extends Vue {
@Prop({ default: "" }) activeDid!: string;
@Prop({ default: "" }) apiServer!: string;
@Prop({ required: true }) dialogType!: "admit" | "visibility";
- @Prop({ required: true }) title!: string;
- @Prop({ required: true }) description!: string;
- @Prop({ required: true }) buttonText!: string;
- @Prop({ required: true }) emptyStateText!: string;
+ @Prop({ required: true }) isOrganizer!: boolean;
// Vue notification system
$notify!: (
@@ -187,6 +184,28 @@ export default class BulkMembersDialog extends Vue {
return selectedCount > 0 && selectedCount < this.membersData.length;
}
+ get title() {
+ return this.isOrganizer
+ ? "Admit Pending Members"
+ : "Add Members to Contacts";
+ }
+
+ get description() {
+ return this.isOrganizer
+ ? "Would you like to admit these members to the meeting and add them to your contacts?"
+ : "Would you like to add these members to your contacts?";
+ }
+
+ get buttonText() {
+ return this.isOrganizer ? "Admit + Add to Contacts" : "Add to Contacts";
+ }
+
+ get emptyStateText() {
+ return this.isOrganizer
+ ? "No pending members to admit"
+ : "No members are not in your contacts";
+ }
+
created() {
this.notify = createNotifyHelpers(this.$notify);
}
diff --git a/src/components/MembersList.vue b/src/components/MembersList.vue
index dc533d82..f0043040 100644
--- a/src/components/MembersList.vue
+++ b/src/components/MembersList.vue
@@ -203,18 +203,7 @@
:active-did="activeDid"
:api-server="apiServer"
:dialog-type="isOrganizer ? 'admit' : 'visibility'"
- :title="isOrganizer ? 'Admit Pending Members' : 'Add Members to Contacts'"
- :description="
- isOrganizer
- ? 'Would you like to admit these members to the meeting and add them to your contacts?'
- : 'Would you like to add these members to your contacts?'
- "
- :button-text="isOrganizer ? 'Admit + Add to Contacts' : 'Add to Contacts'"
- :empty-state-text="
- isOrganizer
- ? 'No pending members to admit'
- : 'No members are not in your contacts'
- "
+ :is-organizer="isOrganizer"
@close="closeBulkMembersDialogCallback"
/>