abmp-npm 2.0.14 → 2.0.16
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/cms-data-methods.js +3 -1
- package/backend/daily-pull/utils.js +14 -1
- package/backend/members-data-methods.js +47 -1
- package/backend/tasks/url-migration-methods.js +22 -7
- package/package.json +1 -1
- package/pages/LearnMore.js +27 -0
- package/pages/index.js +1 -0
- package/pages/personalDetails.js +32 -1
- package/public/Utils/sharedUtils.js +1 -1
- package/public/consts.js +1 -0
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
GEO_HASH_PRECISION,
|
|
9
9
|
MAX__MEMBERS_SEARCH_RESULTS,
|
|
10
10
|
WIX_QUERY_MAX_LIMIT,
|
|
11
|
+
MEMBERSHIPS_TYPES,
|
|
11
12
|
} = require('./consts.js');
|
|
12
13
|
const { wixData } = require('./elevated-modules');
|
|
13
14
|
|
|
@@ -31,6 +32,7 @@ function buildMembersSearchQuery(data) {
|
|
|
31
32
|
.query(COLLECTIONS.MEMBERS_DATA)
|
|
32
33
|
.ne('optOut', true)
|
|
33
34
|
.ne('action', 'drop')
|
|
35
|
+
.ne('memberships.membertype', MEMBERSHIPS_TYPES.PAC_STAFF)
|
|
34
36
|
.eq('isVisible', true);
|
|
35
37
|
let filterConfig = [
|
|
36
38
|
{
|
|
@@ -105,7 +107,7 @@ function buildMembersSearchQuery(data) {
|
|
|
105
107
|
query = query.contains('fullName', filter.searchText);
|
|
106
108
|
}
|
|
107
109
|
if (!includeStudents) {
|
|
108
|
-
query = query.ne('memberships.membertype',
|
|
110
|
+
query = query.ne('memberships.membertype', MEMBERSHIPS_TYPES.STUDENT);
|
|
109
111
|
}
|
|
110
112
|
return query;
|
|
111
113
|
},
|
|
@@ -35,7 +35,17 @@ const extractBaseUrl = url => {
|
|
|
35
35
|
return url;
|
|
36
36
|
};
|
|
37
37
|
const incrementUrlCounter = (existingUrl, baseUrl) => {
|
|
38
|
-
if (existingUrl
|
|
38
|
+
if (!existingUrl || !baseUrl) {
|
|
39
|
+
return baseUrl;
|
|
40
|
+
}
|
|
41
|
+
// Normalize for comparison (case-insensitive)
|
|
42
|
+
const normalizedExisting = existingUrl.toLowerCase();
|
|
43
|
+
const normalizedBase = baseUrl.toLowerCase();
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
normalizedExisting === normalizedBase ||
|
|
47
|
+
normalizedExisting.startsWith(`${normalizedBase}-`)
|
|
48
|
+
) {
|
|
39
49
|
console.log(
|
|
40
50
|
`Found member with same url ${existingUrl} for baseUrl ${baseUrl}, increasing counter by 1`
|
|
41
51
|
);
|
|
@@ -44,6 +54,9 @@ const incrementUrlCounter = (existingUrl, baseUrl) => {
|
|
|
44
54
|
const lastCounter = isNumeric ? parseInt(lastSegment, 10) : 0;
|
|
45
55
|
return `${baseUrl}-${lastCounter + 1}`;
|
|
46
56
|
}
|
|
57
|
+
|
|
58
|
+
// No conflict, return baseUrl with counter 1 to be safe
|
|
59
|
+
return `${baseUrl}-1`;
|
|
47
60
|
};
|
|
48
61
|
/**
|
|
49
62
|
* Validates core member data requirements
|
|
@@ -4,7 +4,7 @@ const { MEMBERSHIPS_TYPES } = require('./consts');
|
|
|
4
4
|
const { updateMemberContactInfo } = require('./contacts-methods');
|
|
5
5
|
const { MEMBER_ACTIONS } = require('./daily-pull/consts');
|
|
6
6
|
const { wixData } = require('./elevated-modules');
|
|
7
|
-
const { createSiteMember } = require('./members-area-methods');
|
|
7
|
+
const { createSiteMember, getCurrentMember } = require('./members-area-methods');
|
|
8
8
|
const {
|
|
9
9
|
chunkArray,
|
|
10
10
|
normalizeUrlForComparison,
|
|
@@ -477,6 +477,51 @@ async function getSiteMemberId(data) {
|
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Tracks a button click with member and location info.
|
|
482
|
+
* @param {Object} params - Parameters
|
|
483
|
+
* @param {string} params.pageName - Name of the page/popup where button was clicked
|
|
484
|
+
* @param {string} params.buttonName - Name/ID of the button that was clicked
|
|
485
|
+
* @returns {Promise<Object>} - Saved record or null if member not found
|
|
486
|
+
*/
|
|
487
|
+
async function trackButtonClick({ pageName, buttonName }) {
|
|
488
|
+
const wixMember = await getCurrentMember();
|
|
489
|
+
|
|
490
|
+
if (!wixMember) {
|
|
491
|
+
console.warn('[trackButtonClick]: No logged in member found');
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const dbMember = await getMemberByContactId(wixMember._id);
|
|
496
|
+
|
|
497
|
+
if (!dbMember) {
|
|
498
|
+
console.warn(
|
|
499
|
+
`[trackButtonClick]: Member not found in MembersDataLatest for contactId: ${wixMember._id}`
|
|
500
|
+
);
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const memberName = dbMember.fullName || 'Unknown';
|
|
505
|
+
const memberId = dbMember.memberId;
|
|
506
|
+
|
|
507
|
+
const clickData = {
|
|
508
|
+
memberName,
|
|
509
|
+
memberId,
|
|
510
|
+
pageName,
|
|
511
|
+
buttonName,
|
|
512
|
+
clickedAt: new Date(),
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
const result = await wixData.insert(COLLECTIONS.BUTTON_CLICKS, clickData);
|
|
517
|
+
console.log(`Tracked ${buttonName} click on ${pageName} for member ${memberId}`);
|
|
518
|
+
return result;
|
|
519
|
+
} catch (error) {
|
|
520
|
+
console.error(`Error tracking ${buttonName} click:`, error);
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
480
525
|
module.exports = {
|
|
481
526
|
findMemberByWixDataId,
|
|
482
527
|
createContactAndMemberIfNew,
|
|
@@ -496,4 +541,5 @@ module.exports = {
|
|
|
496
541
|
getQAUsers,
|
|
497
542
|
getSiteMemberId,
|
|
498
543
|
checkUrlUniqueness,
|
|
544
|
+
trackButtonClick,
|
|
499
545
|
};
|
|
@@ -9,7 +9,8 @@ const { queryAllItems, chunkArray } = require('../utils');
|
|
|
9
9
|
const { TASKS_NAMES } = require('./consts');
|
|
10
10
|
|
|
11
11
|
const COLLECTION_WITH_URLS = 'MembersDataWithUrls';
|
|
12
|
-
const CHUNK_SIZE = 5000; // 5k members per task
|
|
12
|
+
const CHUNK_SIZE = 5000; // 5k members per task for migration
|
|
13
|
+
const GENERATION_CHUNK_SIZE = 1000; // 1k members per task for URL generation
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Step 1: Migrate existing URLs from backup collection
|
|
@@ -201,7 +202,7 @@ async function scheduleGenerateMissingUrls() {
|
|
|
201
202
|
};
|
|
202
203
|
}
|
|
203
204
|
|
|
204
|
-
const chunks = chunkArray(membersToUpdate,
|
|
205
|
+
const chunks = chunkArray(membersToUpdate, GENERATION_CHUNK_SIZE);
|
|
205
206
|
|
|
206
207
|
for (let i = 0; i < chunks.length; i++) {
|
|
207
208
|
const chunk = chunks[i];
|
|
@@ -255,11 +256,25 @@ async function generateUrlsChunk(data) {
|
|
|
255
256
|
};
|
|
256
257
|
|
|
257
258
|
try {
|
|
258
|
-
// Fetch
|
|
259
|
-
|
|
260
|
-
const
|
|
261
|
-
|
|
259
|
+
// Fetch members in smaller batches to avoid cursor size limits
|
|
260
|
+
// hasSome with too many IDs creates cursors that exceed Wix's 150KB limit
|
|
261
|
+
const FETCH_BATCH_SIZE = 200;
|
|
262
|
+
console.log(
|
|
263
|
+
`Fetching ${memberIds.length} members from database in batches of ${FETCH_BATCH_SIZE}...`
|
|
262
264
|
);
|
|
265
|
+
|
|
266
|
+
const members = [];
|
|
267
|
+
const idBatches = chunkArray(memberIds, FETCH_BATCH_SIZE);
|
|
268
|
+
|
|
269
|
+
for (let i = 0; i < idBatches.length; i++) {
|
|
270
|
+
const idBatch = idBatches[i];
|
|
271
|
+
const batchMembers = await queryAllItems(
|
|
272
|
+
wixData.query(COLLECTIONS.MEMBERS_DATA).hasSome('_id', idBatch)
|
|
273
|
+
);
|
|
274
|
+
members.push(...batchMembers);
|
|
275
|
+
console.log(`Fetched batch ${i + 1}/${idBatches.length}: ${batchMembers.length} members`);
|
|
276
|
+
}
|
|
277
|
+
|
|
263
278
|
console.log(`Found ${members.length} members in database`);
|
|
264
279
|
|
|
265
280
|
// Create a map of _id -> member for quick lookup
|
|
@@ -292,7 +307,7 @@ async function generateUrlsChunk(data) {
|
|
|
292
307
|
try {
|
|
293
308
|
const uniqueUrl = await ensureUniqueUrl({
|
|
294
309
|
url: '',
|
|
295
|
-
memberId: member.
|
|
310
|
+
memberId: member.memberId,
|
|
296
311
|
fullName: name || '', // Let ensureUniqueUrl handle fallback for empty names
|
|
297
312
|
});
|
|
298
313
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const PAGE_NAME = 'Learn More';
|
|
2
|
+
const BUTTON_NAME = 'Upgrade Now';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates the Learn More popup handler
|
|
6
|
+
* @param {Object} params - Parameters
|
|
7
|
+
* @param {Function} params.$w - Wix $w selector
|
|
8
|
+
* @param {Function} params.trackClick - Backend function to track the click (handles member lookup internally)
|
|
9
|
+
*/
|
|
10
|
+
function learnMoreOnReady({ $w: _$w, trackClick }) {
|
|
11
|
+
_$w('#learnMoreBtn').onClick(async () => {
|
|
12
|
+
try {
|
|
13
|
+
await trackClick({
|
|
14
|
+
pageName: PAGE_NAME,
|
|
15
|
+
buttonName: BUTTON_NAME,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
console.log(`Tracked ${BUTTON_NAME} click on ${PAGE_NAME}`);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('Error tracking button click:', error);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
learnMoreOnReady,
|
|
27
|
+
};
|
package/pages/index.js
CHANGED
package/pages/personalDetails.js
CHANGED
|
@@ -1294,6 +1294,7 @@ async function personalDetailsOnReady({
|
|
|
1294
1294
|
streetAddress: {
|
|
1295
1295
|
name: extractStreetName(address.line1),
|
|
1296
1296
|
number: extractStreetNumber(address.line1),
|
|
1297
|
+
apt: address.line2 || '',
|
|
1297
1298
|
},
|
|
1298
1299
|
city: address.city || '',
|
|
1299
1300
|
subdivision: address.state || '',
|
|
@@ -1309,20 +1310,49 @@ async function personalDetailsOnReady({
|
|
|
1309
1310
|
if (!addressInputValue) return null;
|
|
1310
1311
|
|
|
1311
1312
|
let line1 = '';
|
|
1313
|
+
let line2 = '';
|
|
1314
|
+
|
|
1312
1315
|
if (addressInputValue.streetAddress) {
|
|
1313
1316
|
const number = addressInputValue.streetAddress.number || '';
|
|
1314
1317
|
const name = addressInputValue.streetAddress.name || '';
|
|
1315
1318
|
line1 = `${number} ${name}`.trim();
|
|
1319
|
+
|
|
1320
|
+
// Capture apartment/suite/building info from streetAddress.apt (undocumented but exists)
|
|
1321
|
+
if (addressInputValue.streetAddress.apt) {
|
|
1322
|
+
line2 = addressInputValue.streetAddress.apt;
|
|
1323
|
+
}
|
|
1316
1324
|
}
|
|
1317
1325
|
|
|
1318
1326
|
if (!line1 && addressInputValue.formatted) {
|
|
1319
1327
|
line1 = addressInputValue.formatted.split(',')[0]?.trim() || '';
|
|
1320
1328
|
}
|
|
1321
1329
|
|
|
1330
|
+
// If line2 is still empty, try to extract building/suite info from formatted address
|
|
1331
|
+
if (!line2 && addressInputValue.formatted) {
|
|
1332
|
+
const formattedParts = addressInputValue.formatted.split(',').map(part => part.trim());
|
|
1333
|
+
// Look for BLDG/STE/APT/UNIT/SUITE info in the formatted parts
|
|
1334
|
+
for (let i = 1; i < formattedParts.length; i++) {
|
|
1335
|
+
const part = formattedParts[i];
|
|
1336
|
+
const lowerPart = part.toLowerCase();
|
|
1337
|
+
if (
|
|
1338
|
+
lowerPart.includes('bldg') ||
|
|
1339
|
+
lowerPart.includes('ste') ||
|
|
1340
|
+
lowerPart.includes('apt') ||
|
|
1341
|
+
lowerPart.includes('unit') ||
|
|
1342
|
+
lowerPart.includes('suite') ||
|
|
1343
|
+
lowerPart.includes('#') ||
|
|
1344
|
+
lowerPart.includes('building')
|
|
1345
|
+
) {
|
|
1346
|
+
line2 = part;
|
|
1347
|
+
break;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1322
1352
|
return {
|
|
1323
1353
|
key: existingAddress?.key || generateId(),
|
|
1324
1354
|
line1,
|
|
1325
|
-
line2: existingAddress?.line2 || '',
|
|
1355
|
+
line2: line2 || existingAddress?.line2 || '',
|
|
1326
1356
|
city: addressInputValue.city || '',
|
|
1327
1357
|
state: addressInputValue.subdivision || '',
|
|
1328
1358
|
postalcode: addressInputValue.postalCode || '',
|
|
@@ -1705,6 +1735,7 @@ async function personalDetailsOnReady({
|
|
|
1705
1735
|
const parts = [];
|
|
1706
1736
|
|
|
1707
1737
|
if (addr.line1) parts.push(addr.line1);
|
|
1738
|
+
if (addr.line2) parts.push(addr.line2); // Include building/suite info
|
|
1708
1739
|
if (addr.city) parts.push(addr.city);
|
|
1709
1740
|
if (addr.state && addr.postalcode) {
|
|
1710
1741
|
parts.push(`${addr.state} ${addr.postalcode}`);
|
|
@@ -91,7 +91,7 @@ function formatAddress(item) {
|
|
|
91
91
|
const limitedPostalCode = item.postalcode.slice(0, 5); //show only 5 digits to not show full user address
|
|
92
92
|
switch (item.addressStatus) {
|
|
93
93
|
case ADDRESS_STATUS_TYPES.FULL_ADDRESS:
|
|
94
|
-
addressParts = [item.line1, item.city, item.state, limitedPostalCode];
|
|
94
|
+
addressParts = [item.line1, item.line2, item.city, item.state, limitedPostalCode];
|
|
95
95
|
break;
|
|
96
96
|
case ADDRESS_STATUS_TYPES.STATE_CITY_ZIP:
|
|
97
97
|
addressParts = [item.city, item.state, limitedPostalCode];
|