diff --git a/client/components/import/import.jade b/client/components/import/import.jade
index 7b55dadbd..ed42fe44b 100644
--- a/client/components/import/import.jade
+++ b/client/components/import/import.jade
@@ -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
| ({{username}})
- +EasySearch.IfSearching(index=searchIndex)
+ if searching.get
+spinner
- +EasySearch.IfNoResults(index=searchIndex)
+ if noResults.get
.manage-member-section
p.quiet {{_ 'no-results'}}
diff --git a/client/components/import/import.js b/client/components/import/import.js
index 4d4ba7fa7..757b55e41 100644
--- a/client/components/import/import.js
+++ b/client/components/import/import.js
@@ -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;
+ }
})
diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade
index d63ea9d98..023b01b9e 100644
--- a/client/components/sidebar/sidebar.jade
+++ b/client/components/sidebar/sidebar.jade
@@ -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
| ({{username}})
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
+ | ({{username}})
+ button.js-email-invite.primary.full {{_ 'email-invite'}}
+
template(name="changePermissionsPopup")
ul.pop-over-list
li
diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js
index 9f1d9c5c1..273df70a5 100644
--- a/client/components/sidebar/sidebar.js
+++ b/client/components/sidebar/sidebar.js
@@ -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({
diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json
index dd01adcd0..212c8428f 100644
--- a/imports/i18n/data/en.i18n.json
+++ b/imports/i18n/data/en.i18n.json
@@ -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",