abmp-npm 2.0.44 → 2.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/jobs.js +15 -0
- package/backend/members-data-methods.js +1 -0
- package/backend/routers/methods.js +4 -2
- package/package.json +1 -1
- package/pages/Home.js +1 -1
- package/pages/LoadingPage.js +12 -3
- package/pages/personalDetails.js +24 -1
- package/public/Utils/homePage.js +90 -31
- package/public/Utils/sharedUtils.js +8 -3
package/backend/jobs.js
CHANGED
|
@@ -68,6 +68,20 @@ async function scheduleCreateContactsFromMembersTask() {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
async function scheduleFixPrimaryAddressForMembersTask() {
|
|
72
|
+
try {
|
|
73
|
+
console.log('scheduleFixPrimaryAddressForMembers started!');
|
|
74
|
+
return await taskManager().schedule({
|
|
75
|
+
name: TASKS_NAMES.scheduleFixPrimaryAddressForMembers,
|
|
76
|
+
data: {},
|
|
77
|
+
type: 'scheduled',
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error(`Failed to scheduleFixPrimaryAddressForMembers: ${error.message}`);
|
|
81
|
+
throw new Error(`Failed to scheduleFixPrimaryAddressForMembers: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
async function updateSiteMapS3() {
|
|
72
86
|
try {
|
|
73
87
|
return await taskManager().schedule({
|
|
@@ -85,4 +99,5 @@ module.exports = {
|
|
|
85
99
|
scheduleDailyPullTask,
|
|
86
100
|
updateSiteMapS3,
|
|
87
101
|
scheduleCreateContactsFromMembersTask,
|
|
102
|
+
scheduleFixPrimaryAddressForMembersTask,
|
|
88
103
|
};
|
|
@@ -410,6 +410,7 @@ async function getMembersWithWixUrl() {
|
|
|
410
410
|
.eq('showWixUrl', true)
|
|
411
411
|
.ne('action', MEMBER_ACTIONS.DROP)
|
|
412
412
|
.ne('memberships.membertype', MEMBERSHIPS_TYPES.PAC_STAFF)
|
|
413
|
+
.ne('memberships.membertype', MEMBERSHIPS_TYPES.STUDENT)
|
|
413
414
|
.isNotEmpty('url')
|
|
414
415
|
.limit(1000);
|
|
415
416
|
let currentResults = await membersQuery.find();
|
|
@@ -47,10 +47,12 @@ const createRoutersHandlers = wixRouterMethods => {
|
|
|
47
47
|
}
|
|
48
48
|
const profileUrl = `${request.baseUrl}/${PAGES_PATHS.PROFILE}/${profileData.url}`;
|
|
49
49
|
const isPrivateMember = profileData.isPrivateMember;
|
|
50
|
+
const isStudent = profileData.shouldHaveStudentBadge;
|
|
51
|
+
const shouldNoIndex = isPrivateMember || isStudent;
|
|
50
52
|
const seoData = {
|
|
51
53
|
title: seoTitle,
|
|
52
54
|
description: description,
|
|
53
|
-
noIndex:
|
|
55
|
+
noIndex: shouldNoIndex,
|
|
54
56
|
metaTags: [
|
|
55
57
|
{
|
|
56
58
|
name: 'description',
|
|
@@ -69,7 +71,7 @@ const createRoutersHandlers = wixRouterMethods => {
|
|
|
69
71
|
},
|
|
70
72
|
{
|
|
71
73
|
name: 'robots',
|
|
72
|
-
content:
|
|
74
|
+
content: shouldNoIndex ? 'noindex, nofollow' : 'index, follow',
|
|
73
75
|
},
|
|
74
76
|
// Open Graph tags
|
|
75
77
|
{
|
package/package.json
CHANGED
package/pages/Home.js
CHANGED
|
@@ -366,7 +366,7 @@ const homePageOnReady = async ({
|
|
|
366
366
|
isSearchingNearby: _$w('#nearBy').checked,
|
|
367
367
|
preservePagination,
|
|
368
368
|
});
|
|
369
|
-
|
|
369
|
+
// URL is updated inside search() with the filter actually used (avoids rapid select/deselect overwriting with live filter)
|
|
370
370
|
return searchResults;
|
|
371
371
|
}
|
|
372
372
|
|
package/pages/LoadingPage.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
const { location: wixLocationFrontend } = require('@wix/site-location');
|
|
2
|
+
const { local } = require('@wix/site-storage');
|
|
1
3
|
const { window: wixWindow, rendering } = require('@wix/site-window');
|
|
2
4
|
|
|
3
|
-
const { LIGHTBOX_NAMES } = require('../public/consts');
|
|
5
|
+
const { LIGHTBOX_NAMES, PAGES_PATHS } = require('../public/consts');
|
|
4
6
|
const { checkAndLogin } = require('../public/sso-auth-methods');
|
|
5
7
|
|
|
6
8
|
async function loadingPageOnReady(authenticateSSOToken) {
|
|
@@ -8,9 +10,16 @@ async function loadingPageOnReady(authenticateSSOToken) {
|
|
|
8
10
|
//This calls needs to triggered on client side, otherwise PAC API will return 401 error
|
|
9
11
|
if (renderingEnv === 'browser') {
|
|
10
12
|
//Need to pass authenticateSSOToken to checkAndLogin so it will run as a web method not a public one.
|
|
11
|
-
await checkAndLogin(authenticateSSOToken).catch(error => {
|
|
12
|
-
wixWindow.openLightbox(LIGHTBOX_NAMES.LOGIN_ERROR_ALERT);
|
|
13
|
+
await checkAndLogin(authenticateSSOToken).catch(async error => {
|
|
13
14
|
console.error(`Something went wrong while logging in: ${error}`);
|
|
15
|
+
// If we already have a session (memberId), redirect to form instead of showing error.
|
|
16
|
+
const storedMemberId = await local.getItem('memberId');
|
|
17
|
+
if (storedMemberId) {
|
|
18
|
+
const redirectTo = `${PAGES_PATHS.MEMBERS_FORM}?token=${encodeURIComponent(storedMemberId)}`;
|
|
19
|
+
await wixLocationFrontend.to(`/${redirectTo}`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
wixWindow.openLightbox(LIGHTBOX_NAMES.LOGIN_ERROR_ALERT);
|
|
14
23
|
});
|
|
15
24
|
}
|
|
16
25
|
}
|
package/pages/personalDetails.js
CHANGED
|
@@ -1556,9 +1556,23 @@ async function personalDetailsOnReady({
|
|
|
1556
1556
|
_$w('#mainAddressCheckbox').checked = false;
|
|
1557
1557
|
checkbox.checked = true;
|
|
1558
1558
|
|
|
1559
|
+
// Primary address cannot be hidden: update model and repeater data so UI and save stay in sync
|
|
1559
1560
|
if (clickedItemData.address.addressStatus === ADDRESS_STATUS_TYPES.DONT_SHOW) {
|
|
1560
1561
|
updateAddressStatus(clickedItemData._id, ADDRESS_STATUS_TYPES.STATE_CITY_ZIP);
|
|
1561
1562
|
$item('#addressStatusOptions').value = ADDRESS_STATUS_TYPES.STATE_CITY_ZIP;
|
|
1563
|
+
const currentData = _$w('#addressesList').data || [];
|
|
1564
|
+
const dataWithStatusFixed = currentData.map(item =>
|
|
1565
|
+
item._id === clickedItemData._id
|
|
1566
|
+
? {
|
|
1567
|
+
...item,
|
|
1568
|
+
address: {
|
|
1569
|
+
...item.address,
|
|
1570
|
+
addressStatus: ADDRESS_STATUS_TYPES.STATE_CITY_ZIP,
|
|
1571
|
+
},
|
|
1572
|
+
}
|
|
1573
|
+
: item
|
|
1574
|
+
);
|
|
1575
|
+
_$w('#addressesList').data = dataWithStatusFixed;
|
|
1562
1576
|
}
|
|
1563
1577
|
|
|
1564
1578
|
updateMainAddressSelection(clickedItemData._id);
|
|
@@ -1567,7 +1581,7 @@ async function personalDetailsOnReady({
|
|
|
1567
1581
|
});
|
|
1568
1582
|
|
|
1569
1583
|
_$w('#addressStatusOptions').onChange(event => {
|
|
1570
|
-
const data = _$w('#addressesList').data;
|
|
1584
|
+
const data = _$w('#addressesList').data || [];
|
|
1571
1585
|
const clickedItemData = data.find(item => item._id === event.context.itemId);
|
|
1572
1586
|
const newStatus = event.target.value;
|
|
1573
1587
|
const $item = _$w.at(event.context);
|
|
@@ -1579,6 +1593,15 @@ async function personalDetailsOnReady({
|
|
|
1579
1593
|
}
|
|
1580
1594
|
|
|
1581
1595
|
updateAddressStatus(clickedItemData._id, newStatus);
|
|
1596
|
+
|
|
1597
|
+
// Keep repeater data in sync (required for new addresses not yet in itemMemberObj.addresses)
|
|
1598
|
+
const updatedData = data.map(item =>
|
|
1599
|
+
item._id === clickedItemData._id
|
|
1600
|
+
? { ...item, address: { ...item.address, addressStatus: newStatus } }
|
|
1601
|
+
: item
|
|
1602
|
+
);
|
|
1603
|
+
_$w('#addressesList').data = updatedData;
|
|
1604
|
+
|
|
1582
1605
|
checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
|
|
1583
1606
|
});
|
|
1584
1607
|
|
package/public/Utils/homePage.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
const { location: wixLocation, queryParams: wixQueryParams } = require('@wix/site-location');
|
|
2
2
|
const { window: wixWindow, rendering } = require('@wix/site-window');
|
|
3
3
|
|
|
4
|
-
const { DEFAULT_FILTER } = require('../consts.js');
|
|
4
|
+
const { DEFAULT_FILTER, DEBOUNCE_DELAY } = require('../consts.js');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
function generateSearchId() {
|
|
7
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
8
|
+
const r = (Math.random() * 16) | 0;
|
|
9
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
10
|
+
return v.toString(16);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
7
13
|
|
|
8
14
|
const createHomepageUtils = (_$w, filterProfiles) => {
|
|
15
|
+
let currentSearchId = null;
|
|
16
|
+
let searchDebounceTimer = null;
|
|
17
|
+
let lastSearchFilter = null;
|
|
18
|
+
let lastSearchIsSearchingNearby = false;
|
|
19
|
+
let lastSearchPreservePagination = false;
|
|
20
|
+
let pendingSearchResolve = null;
|
|
21
|
+
|
|
9
22
|
const getFiltersSelectors = filterName => ({
|
|
10
23
|
checkBoxContainerSelector: _$w(`#${filterName}CheckBoxContainer`),
|
|
11
24
|
searchTextInputSelector: _$w(`#${filterName}TextInput`),
|
|
@@ -655,13 +668,14 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
655
668
|
async function search({
|
|
656
669
|
filter,
|
|
657
670
|
pagination,
|
|
658
|
-
debounceTimeout,
|
|
671
|
+
debounceTimeout: _debounceTimeout,
|
|
659
672
|
timeoutType,
|
|
660
673
|
isSearchingNearby,
|
|
661
674
|
preservePagination = false,
|
|
662
675
|
}) {
|
|
663
676
|
const multiStateBoxSelector = _$w('#resultsStateBox');
|
|
664
677
|
const renderingEnv = await rendering.env();
|
|
678
|
+
|
|
665
679
|
const initSearchResultsUI = () => {
|
|
666
680
|
JSON.stringify(filter) === JSON.stringify(DEFAULT_FILTER)
|
|
667
681
|
? _$w('#resetFilter').hide()
|
|
@@ -672,70 +686,115 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
672
686
|
_$w('#profileRepeater').data = [];
|
|
673
687
|
console.log({ filter });
|
|
674
688
|
};
|
|
675
|
-
|
|
676
|
-
|
|
689
|
+
|
|
690
|
+
const runSearchAndUpdateUI = async (
|
|
691
|
+
filterToUse,
|
|
692
|
+
isSearchingNearbyToUse,
|
|
693
|
+
preservePaginationToUse
|
|
694
|
+
) => {
|
|
695
|
+
if (!isSearchingNearbyToUse) {
|
|
677
696
|
if (
|
|
678
697
|
JSON.stringify({
|
|
679
|
-
...
|
|
698
|
+
...filterToUse,
|
|
680
699
|
latitude: 0,
|
|
681
700
|
longitude: 0,
|
|
682
701
|
}) === JSON.stringify(DEFAULT_FILTER)
|
|
683
702
|
) {
|
|
684
703
|
multiStateBoxSelector.changeState('noSearchCriteria');
|
|
704
|
+
await updateUrlParams(filterToUse, pagination);
|
|
685
705
|
return [];
|
|
686
706
|
}
|
|
687
707
|
}
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
? () => nonDebouncedFilterProfiles()
|
|
700
|
-
: () =>
|
|
701
|
-
debouncedFunction({
|
|
702
|
-
func: filterProfiles,
|
|
703
|
-
debounceTimeout,
|
|
704
|
-
timeoutType,
|
|
705
|
-
args: { filter, isSearchingNearby },
|
|
706
|
-
});
|
|
707
|
-
const { success, response, error } = await funcPromise();
|
|
708
|
-
if (!success) {
|
|
708
|
+
const thisSearchId = generateSearchId();
|
|
709
|
+
currentSearchId = thisSearchId;
|
|
710
|
+
|
|
711
|
+
let result;
|
|
712
|
+
try {
|
|
713
|
+
result = await filterProfiles({
|
|
714
|
+
filter: filterToUse,
|
|
715
|
+
isSearchingNearby: isSearchingNearbyToUse,
|
|
716
|
+
});
|
|
717
|
+
} catch (error) {
|
|
718
|
+
if (thisSearchId !== currentSearchId) return [];
|
|
709
719
|
_$w('#numberOfResults').text = '';
|
|
710
720
|
console.error('[search] failed with error:', error);
|
|
711
721
|
multiStateBoxSelector.changeState('errorState');
|
|
722
|
+
await updateUrlParams(filterToUse, pagination);
|
|
712
723
|
return [];
|
|
713
724
|
}
|
|
725
|
+
|
|
726
|
+
if (thisSearchId !== currentSearchId) return [];
|
|
727
|
+
|
|
728
|
+
const response = result;
|
|
714
729
|
const totalCount = response.items.length;
|
|
715
730
|
if (!totalCount) {
|
|
716
731
|
_$w('#numberOfResults').text = 'Showing 0 results';
|
|
717
732
|
_$w('#noResultsMessage').text = `${
|
|
718
|
-
|
|
719
|
-
? `'${
|
|
733
|
+
filterToUse.searchText && filterToUse.searchText.length > 0
|
|
734
|
+
? `'${filterToUse.searchText}' did not match any search. Please try again.`
|
|
720
735
|
: 'No results found for the selected filters. Please adjust your filters and try again'
|
|
721
736
|
}`;
|
|
722
737
|
multiStateBoxSelector.changeState('noResultsState');
|
|
738
|
+
await updateUrlParams(filterToUse, pagination);
|
|
723
739
|
return [];
|
|
724
740
|
}
|
|
725
741
|
console.log({ response });
|
|
726
742
|
handleNumberOfResults(pagination, totalCount);
|
|
727
743
|
_$w('#showingResult').show();
|
|
728
744
|
|
|
729
|
-
if (!
|
|
745
|
+
if (!preservePaginationToUse || pagination.currentPage >= pagination.totalPages) {
|
|
730
746
|
pagination.currentPage = 0;
|
|
731
747
|
}
|
|
732
748
|
pagination.totalPages = Math.ceil(totalCount / pagination.pageSize);
|
|
733
749
|
paginateSearchResults(response.items, pagination);
|
|
734
750
|
multiStateBoxSelector.changeState('resultsState');
|
|
751
|
+
await updateUrlParams(filterToUse, pagination);
|
|
735
752
|
return response.items;
|
|
736
753
|
};
|
|
754
|
+
|
|
755
|
+
// Always show loading as soon as user changes input
|
|
737
756
|
initSearchResultsUI();
|
|
738
|
-
|
|
757
|
+
|
|
758
|
+
// SSR: run immediately, no debounce
|
|
759
|
+
if (renderingEnv === 'backend') {
|
|
760
|
+
return await runSearchAndUpdateUI(filter, isSearchingNearby, preservePagination);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Client: debounce the API call; loading is already shown above.
|
|
764
|
+
// Snapshot the filter so rapid clicks / URL sync can't mutate it before the debounced run.
|
|
765
|
+
lastSearchFilter = JSON.parse(JSON.stringify(filter));
|
|
766
|
+
lastSearchIsSearchingNearby = isSearchingNearby;
|
|
767
|
+
lastSearchPreservePagination = preservePagination;
|
|
768
|
+
|
|
769
|
+
if (pendingSearchResolve) {
|
|
770
|
+
pendingSearchResolve([]);
|
|
771
|
+
pendingSearchResolve = null;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
if (searchDebounceTimer) {
|
|
775
|
+
clearTimeout(searchDebounceTimer);
|
|
776
|
+
searchDebounceTimer = null;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const delay = DEBOUNCE_DELAY[timeoutType] ?? 300;
|
|
780
|
+
return new Promise(resolve => {
|
|
781
|
+
pendingSearchResolve = resolve;
|
|
782
|
+
searchDebounceTimer = setTimeout(async () => {
|
|
783
|
+
searchDebounceTimer = null;
|
|
784
|
+
const filterToUse = lastSearchFilter;
|
|
785
|
+
const isSearchingNearbyToUse = lastSearchIsSearchingNearby;
|
|
786
|
+
const preservePaginationToUse = lastSearchPreservePagination;
|
|
787
|
+
const items = await runSearchAndUpdateUI(
|
|
788
|
+
filterToUse,
|
|
789
|
+
isSearchingNearbyToUse,
|
|
790
|
+
preservePaginationToUse
|
|
791
|
+
);
|
|
792
|
+
if (pendingSearchResolve) {
|
|
793
|
+
pendingSearchResolve(items);
|
|
794
|
+
pendingSearchResolve = null;
|
|
795
|
+
}
|
|
796
|
+
}, delay);
|
|
797
|
+
});
|
|
739
798
|
}
|
|
740
799
|
|
|
741
800
|
return {
|
|
@@ -87,9 +87,11 @@ function findMainAddress(addressDisplayOption = [], addresses = []) {
|
|
|
87
87
|
return '';
|
|
88
88
|
}
|
|
89
89
|
function formatAddress(item) {
|
|
90
|
+
if (!item) return '';
|
|
90
91
|
let addressParts = [];
|
|
91
|
-
const limitedPostalCode = item.postalcode.slice(0, 5); //show only 5 digits to not show full user address
|
|
92
|
-
|
|
92
|
+
const limitedPostalCode = (item.postalcode && String(item.postalcode).slice(0, 5)) || ''; //show only 5 digits to not show full user address
|
|
93
|
+
const status = item.addressStatus;
|
|
94
|
+
switch (status) {
|
|
93
95
|
case ADDRESS_STATUS_TYPES.FULL_ADDRESS:
|
|
94
96
|
addressParts = [item.line1, item.line2, item.city, item.state, limitedPostalCode];
|
|
95
97
|
break;
|
|
@@ -97,7 +99,10 @@ function formatAddress(item) {
|
|
|
97
99
|
addressParts = [item.city, item.state, limitedPostalCode];
|
|
98
100
|
break;
|
|
99
101
|
default:
|
|
100
|
-
return '';
|
|
102
|
+
if (status === ADDRESS_STATUS_TYPES.DONT_SHOW) return '';
|
|
103
|
+
// Legacy addresses may have no addressStatus; show city/state/zip by default
|
|
104
|
+
addressParts = [item.city, item.state, limitedPostalCode];
|
|
105
|
+
break;
|
|
101
106
|
}
|
|
102
107
|
return addressParts.filter(Boolean).join(', ');
|
|
103
108
|
}
|