Fix unable to add members to board.

Fixes #5972
This commit is contained in:
Lauri Ojansivu 2025-10-23 00:34:19 +03:00
parent bd1837ee36
commit c6d4600683
5 changed files with 173 additions and 23 deletions

View file

@ -56,17 +56,17 @@ template(name="importMapMembersAddPopup")
p
| {{_ 'import-user-select'}}
.js-map-member
+EasySearch.Input(index=searchIndex)
input.js-search-member-input(type="text" placeholder="{{_ 'search-users'}}")
ul.pop-over-list
+EasySearch.Each(index=searchIndex)
each searchResults
li.item.js-member-item
a.name.js-select-import(title="{{profile.fullname}} ({{username}})" data-id="{{__originalId}}")
+userAvatar(userId=__originalId)
a.name.js-select-import(title="{{profile.fullname}} ({{username}})" data-id="{{_id}}")
+userAvatar(userId=_id)
span.full-name
= profile.fullname
| (<span class="username">{{username}}</span>)
+EasySearch.IfSearching(index=searchIndex)
if searching.get
+spinner
+EasySearch.IfNoResults(index=searchIndex)
if noResults.get
.manage-member-section
p.quiet {{_ 'no-results'}}

View file

@ -311,6 +311,73 @@ BlazeComponent.extendComponent({
},
}).register('importMapMembersAddPopup');
// Global reactive variables for import member popup
const importMemberPopupState = {
searching: new ReactiveVar(false),
searchResults: new ReactiveVar([]),
noResults: new ReactiveVar(false),
searchTimeout: null
};
BlazeComponent.extendComponent({
onCreated() {
// Use global state
this.searching = importMemberPopupState.searching;
this.searchResults = importMemberPopupState.searchResults;
this.noResults = importMemberPopupState.noResults;
this.searchTimeout = importMemberPopupState.searchTimeout;
},
onRendered() {
this.find('.js-search-member-input').focus();
},
performSearch(query) {
if (!query || query.length < 2) {
this.searchResults.set([]);
this.noResults.set(false);
return;
}
this.searching.set(true);
this.noResults.set(false);
const results = UserSearchIndex.search(query, { limit: 20 }).fetch();
this.searchResults.set(results);
this.searching.set(false);
if (results.length === 0) {
this.noResults.set(true);
}
},
events() {
return [
{
'keyup .js-search-member-input'(event) {
const query = event.target.value.trim();
if (this.searchTimeout) {
clearTimeout(this.searchTimeout);
}
this.searchTimeout = setTimeout(() => {
this.performSearch(query);
}, 300);
},
},
];
},
}).register('importMapMembersAddPopupSearch');
Template.importMapMembersAddPopup.helpers({
searchIndex: () => UserSearchIndex,
searchResults() {
return importMemberPopupState.searchResults.get();
},
searching() {
return importMemberPopupState.searching;
},
noResults() {
return importMemberPopupState.noResults;
}
})

View file

@ -631,7 +631,7 @@ template(name="removeBoardTeamPopup")
template(name="addMemberPopup")
.js-search-member
+EasySearch.Input(index=searchIndex)
input.js-search-member-input(type="text" placeholder="{{_ 'email-address'}}")
if loading.get
+spinner
@ -639,25 +639,38 @@ template(name="addMemberPopup")
.warning {{_ error.get}}
else
ul.pop-over-list
+EasySearch.Each(index=searchIndex)
each searchResults
li.item.js-member-item(class="{{#if isBoardMember}}disabled{{/if}}")
a.name.js-select-member(title="{{profile.fullname}} ({{username}})")
+userAvatar(userId=__originalId)
+userAvatar(userId=_id)
span.full-name
= profile.fullname
| (<span class="username">{{username}}</span>)
if isBoardMember
.quiet ({{_ 'joined'}})
+EasySearch.IfSearching(index=searchIndex)
if searching.get
+spinner
+EasySearch.IfNoResults(index=searchIndex)
if noResults.get
.manage-member-section
p.quiet {{_ 'no-results'}}
button.js-email-invite.primary.full {{_ 'email-invite'}}
template(name="addMemberPopupTest")
.js-search-member
input.js-search-member-input(type="text" placeholder="{{_ 'email-address'}}")
ul.pop-over-list
each searchResults
li.item.js-member-item
a.name.js-select-member(title="{{profile.fullname}} ({{username}})")
+userAvatar(userId=_id)
span.full-name
= profile.fullname
| (<span class="username">{{username}}</span>)
button.js-email-invite.primary.full {{_ 'email-invite'}}
template(name="changePermissionsPopup")
ul.pop-over-list
li

View file

@ -1492,19 +1492,28 @@ BlazeComponent.extendComponent({
},
}).register('boardCardSettingsPopup');
// Use Session variables instead of global ReactiveVars
Session.setDefault('addMemberPopup.searchResults', []);
Session.setDefault('addMemberPopup.searching', false);
Session.setDefault('addMemberPopup.noResults', false);
Session.setDefault('addMemberPopup.loading', false);
Session.setDefault('addMemberPopup.error', '');
console.log('addMemberPopup Session variables initialized');
BlazeComponent.extendComponent({
onCreated() {
this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false);
// Use Session variables
this.searchTimeout = null;
},
onRendered() {
this.find('.js-search-member input').focus();
this.find('.js-search-member-input').focus();
this.setLoading(false);
},
isBoardMember() {
const userId = this.currentData().__originalId;
const userId = this.currentData()._id;
const user = ReactiveCache.getUser(userId);
return user && user.isBoardMember();
},
@ -1514,15 +1523,35 @@ BlazeComponent.extendComponent({
},
setError(error) {
this.error.set(error);
Session.set('addMemberPopup.error', error);
},
setLoading(w) {
this.loading.set(w);
Session.set('addMemberPopup.loading', w);
},
isLoading() {
return this.loading.get();
return Session.get('addMemberPopup.loading');
},
performSearch(query) {
if (!query || query.length < 2) {
Session.set('addMemberPopup.searchResults', []);
Session.set('addMemberPopup.noResults', false);
return;
}
Session.set('addMemberPopup.searching', true);
Session.set('addMemberPopup.noResults', false);
// Use the fallback search
const results = UserSearchIndex.search(query, { limit: 20 }).fetch();
Session.set('addMemberPopup.searchResults', results);
Session.set('addMemberPopup.searching', false);
if (results.length === 0) {
Session.set('addMemberPopup.noResults', true);
}
},
inviteUser(idNameEmail) {
@ -1540,18 +1569,30 @@ BlazeComponent.extendComponent({
events() {
return [
{
'keyup input'() {
'keyup .js-search-member-input'(event) {
this.setError('');
const query = event.target.value.trim();
this.searchQuery.set(query);
// Clear previous timeout
if (this.searchTimeout) {
clearTimeout(this.searchTimeout);
}
// Debounce search
this.searchTimeout = setTimeout(() => {
this.performSearch(query);
}, 300);
},
'click .js-select-member'() {
const userId = this.currentData().__originalId;
const userId = this.currentData()._id;
const currentBoard = Utils.getCurrentBoard();
if (!currentBoard.hasMember(userId)) {
this.inviteUser(userId);
}
},
'click .js-email-invite'() {
const idNameEmail = $('.js-search-member input').val();
const idNameEmail = $('.js-search-member-input').val();
if (idNameEmail.indexOf('@') < 0 || this.isValidEmail(idNameEmail)) {
this.inviteUser(idNameEmail);
} else this.setError('email-invalid');
@ -1562,7 +1603,35 @@ BlazeComponent.extendComponent({
}).register('addMemberPopup');
Template.addMemberPopup.helpers({
searchIndex: () => UserSearchIndex,
searchResults() {
const results = Session.get('addMemberPopup.searchResults');
console.log('searchResults helper called, returning:', results);
return results;
},
searching() {
return Session.get('addMemberPopup.searching');
},
noResults() {
return Session.get('addMemberPopup.noResults');
},
loading() {
return Session.get('addMemberPopup.loading');
},
error() {
return Session.get('addMemberPopup.error');
},
isBoardMember() {
const userId = this._id;
const user = ReactiveCache.getUser(userId);
return user && user.isBoardMember();
}
})
Template.addMemberPopupTest.helpers({
searchResults() {
console.log('addMemberPopupTest searchResults helper called');
return Session.get('addMemberPopup.searchResults') || [];
}
})
BlazeComponent.extendComponent({

View file

@ -385,6 +385,7 @@
"editNotificationPopup-title": "Edit Notification",
"editProfilePopup-title": "Edit Profile",
"email": "Email",
"email-address": "Email Address",
"email-enrollAccount-subject": "An account created for you on __siteName__",
"email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
"email-fail": "Sending email failed",