abmp-npm 2.0.61 → 2.0.63
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/package.json +1 -1
- package/pages/Home.js +3 -2
- package/pages/personalDetails.js +79 -8
- package/public/Utils/homePage.js +2 -38
- package/public/Utils/sharedUtils.js +10 -0
package/package.json
CHANGED
package/pages/Home.js
CHANGED
|
@@ -10,6 +10,7 @@ const {
|
|
|
10
10
|
formatPracticeAreasForDisplay,
|
|
11
11
|
checkAddressIsVisible,
|
|
12
12
|
isWixHostedImage,
|
|
13
|
+
normalizeExternalUrl,
|
|
13
14
|
} = require('../public/Utils/sharedUtils.js');
|
|
14
15
|
|
|
15
16
|
let filter = JSON.parse(JSON.stringify(DEFAULT_FILTER));
|
|
@@ -198,7 +199,7 @@ const homePageOnReady = async ({
|
|
|
198
199
|
$item('#websiteContainer').collapse();
|
|
199
200
|
} else {
|
|
200
201
|
if (itemData.showWebsite) {
|
|
201
|
-
$item('#website').link = itemData.website;
|
|
202
|
+
$item('#website').link = normalizeExternalUrl(itemData.website);
|
|
202
203
|
} else {
|
|
203
204
|
$item('#website').link = `${baseUrl}/profile/${itemData.url}`;
|
|
204
205
|
}
|
|
@@ -256,7 +257,7 @@ const homePageOnReady = async ({
|
|
|
256
257
|
// 9) "Book now" button
|
|
257
258
|
if (itemData.bookingUrl) {
|
|
258
259
|
$item('#bookNowButton').show();
|
|
259
|
-
$item('#bookNowButton').link = itemData.bookingUrl;
|
|
260
|
+
$item('#bookNowButton').link = normalizeExternalUrl(itemData.bookingUrl);
|
|
260
261
|
$item('#bookNowButton').target = '_blank';
|
|
261
262
|
} else {
|
|
262
263
|
$item('#bookNowButton').hide();
|
package/pages/personalDetails.js
CHANGED
|
@@ -9,7 +9,11 @@ const {
|
|
|
9
9
|
LIGHTBOX_NAMES,
|
|
10
10
|
} = require('../public/consts');
|
|
11
11
|
const { handleOnCustomValidation, isNotValidUrl } = require('../public/Utils/personalDetailsUtils');
|
|
12
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
generateId,
|
|
14
|
+
isWixHostedImage,
|
|
15
|
+
normalizeExternalUrl,
|
|
16
|
+
} = require('../public/Utils/sharedUtils');
|
|
13
17
|
|
|
14
18
|
const MAX_PHONES_COUNT = 10;
|
|
15
19
|
const MAX_ADDRESSES_COUNT = 10;
|
|
@@ -2039,9 +2043,14 @@ async function personalDetailsOnReady({
|
|
|
2039
2043
|
return;
|
|
2040
2044
|
}
|
|
2041
2045
|
|
|
2046
|
+
const $item = _$w.at(event.context);
|
|
2042
2047
|
const isChecked = event.target.checked;
|
|
2043
2048
|
let updated;
|
|
2044
2049
|
if (isChecked) {
|
|
2050
|
+
// Same pattern as #mainAddressCheckbox: clear every row, then select one (repeater
|
|
2051
|
+
// often does not refresh sibling items' controls when only `data` changes).
|
|
2052
|
+
_$w('#showPhoneCheckbox').checked = false;
|
|
2053
|
+
$item('#showPhoneCheckbox').checked = true;
|
|
2045
2054
|
updated = data.map(item =>
|
|
2046
2055
|
item._id === clickedItemData._id
|
|
2047
2056
|
? { ...item, showPhone: true }
|
|
@@ -2094,6 +2103,34 @@ async function personalDetailsOnReady({
|
|
|
2094
2103
|
$item('#phoneNumberLabel').text = `Phone ${itemData.phoneIndex}`;
|
|
2095
2104
|
}
|
|
2096
2105
|
|
|
2106
|
+
/** Only one "Show your phone" row at a time; aligns UI with itemMemberObj.toShowPhone. */
|
|
2107
|
+
function normalizePhoneShowFlags(phoneData) {
|
|
2108
|
+
if (!phoneData?.length) return phoneData;
|
|
2109
|
+
|
|
2110
|
+
const cms = (itemMemberObj.toShowPhone || '').trim();
|
|
2111
|
+
if (cms) {
|
|
2112
|
+
let matched = false;
|
|
2113
|
+
return phoneData.map(p => {
|
|
2114
|
+
const t = (p.phoneNumber || '').trim();
|
|
2115
|
+
const isMatch = Boolean(t && t === cms);
|
|
2116
|
+
if (isMatch && !matched) {
|
|
2117
|
+
matched = true;
|
|
2118
|
+
return { ...p, showPhone: true };
|
|
2119
|
+
}
|
|
2120
|
+
return { ...p, showPhone: false };
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
const trueIdxs = phoneData.map((p, i) => (p.showPhone ? i : -1)).filter(i => i >= 0);
|
|
2125
|
+
if (trueIdxs.length <= 1) return phoneData;
|
|
2126
|
+
|
|
2127
|
+
const keep = trueIdxs[0];
|
|
2128
|
+
return phoneData.map((p, i) => ({
|
|
2129
|
+
...p,
|
|
2130
|
+
showPhone: i === keep,
|
|
2131
|
+
}));
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2097
2134
|
function renderPhonesList(updatedPhones) {
|
|
2098
2135
|
let phoneData = updatedPhones || [];
|
|
2099
2136
|
|
|
@@ -2109,12 +2146,28 @@ async function personalDetailsOnReady({
|
|
|
2109
2146
|
}));
|
|
2110
2147
|
}
|
|
2111
2148
|
|
|
2149
|
+
phoneData = normalizePhoneShowFlags(phoneData);
|
|
2150
|
+
|
|
2112
2151
|
const repeater = _$w('#phoneNumbersList');
|
|
2113
2152
|
|
|
2114
2153
|
repeater.data = phoneData;
|
|
2154
|
+
refreshPhoneShowCheckboxState(phoneData);
|
|
2115
2155
|
updatePhoneAddButtonState();
|
|
2116
2156
|
}
|
|
2117
2157
|
|
|
2158
|
+
/**
|
|
2159
|
+
* Repeater may not re-run onItemReady for sibling items when only showPhone flags change;
|
|
2160
|
+
* keep each #showPhoneCheckbox in sync with data (same idea as refreshAddressListIsMainState).
|
|
2161
|
+
*/
|
|
2162
|
+
function refreshPhoneShowCheckboxState(phoneData) {
|
|
2163
|
+
const repeater = _$w('#phoneNumbersList');
|
|
2164
|
+
const data = phoneData || repeater.data || [];
|
|
2165
|
+
repeater.forEachItem(($item, _itemData, index) => {
|
|
2166
|
+
const show = index < data.length ? data[index].showPhone : false;
|
|
2167
|
+
$item('#showPhoneCheckbox').checked = Boolean(show);
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2118
2171
|
function updatePhoneAddButtonState() {
|
|
2119
2172
|
const currentData = _$w('#phoneNumbersList').data || [];
|
|
2120
2173
|
const addPhoneButton = _$w('#addPhoneButton');
|
|
@@ -2131,7 +2184,22 @@ async function personalDetailsOnReady({
|
|
|
2131
2184
|
const itemIndex = currentData.findIndex(item => item._id === phoneId);
|
|
2132
2185
|
|
|
2133
2186
|
if (itemIndex !== -1) {
|
|
2134
|
-
currentData[itemIndex]
|
|
2187
|
+
const item = currentData[itemIndex];
|
|
2188
|
+
const prevTrimmed = (item.phoneNumber || '').trim();
|
|
2189
|
+
const newTrimmed = newPhoneNumber.trim();
|
|
2190
|
+
|
|
2191
|
+
item.phoneNumber = newPhoneNumber;
|
|
2192
|
+
|
|
2193
|
+
if (item.showPhone) {
|
|
2194
|
+
itemMemberObj.toShowPhone = newTrimmed || null;
|
|
2195
|
+
} else if (
|
|
2196
|
+
itemMemberObj.toShowPhone &&
|
|
2197
|
+
prevTrimmed &&
|
|
2198
|
+
itemMemberObj.toShowPhone === prevTrimmed
|
|
2199
|
+
) {
|
|
2200
|
+
itemMemberObj.toShowPhone = newTrimmed || null;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2135
2203
|
renderPhonesList(currentData);
|
|
2136
2204
|
syncPhonesFromRepeater();
|
|
2137
2205
|
checkFormChanges(FORM_SECTION_HANDLER_MAP.CONTACT_BOOKING);
|
|
@@ -2187,14 +2255,14 @@ async function personalDetailsOnReady({
|
|
|
2187
2255
|
return;
|
|
2188
2256
|
}
|
|
2189
2257
|
|
|
2258
|
+
const trimmed = (selectedItem.phoneNumber || '').trim();
|
|
2259
|
+
|
|
2190
2260
|
if (isVisible) {
|
|
2191
|
-
itemMemberObj.toShowPhone =
|
|
2192
|
-
? selectedItem.phoneNumber
|
|
2193
|
-
: null;
|
|
2261
|
+
itemMemberObj.toShowPhone = trimmed || null;
|
|
2194
2262
|
return;
|
|
2195
2263
|
}
|
|
2196
2264
|
|
|
2197
|
-
if (
|
|
2265
|
+
if (itemMemberObj.toShowPhone === trimmed) {
|
|
2198
2266
|
itemMemberObj.toShowPhone = null;
|
|
2199
2267
|
}
|
|
2200
2268
|
}
|
|
@@ -2216,12 +2284,15 @@ async function personalDetailsOnReady({
|
|
|
2216
2284
|
const addresses = Array.isArray(itemMemberObj.addresses) ? itemMemberObj.addresses : [];
|
|
2217
2285
|
const phones = Array.isArray(itemMemberObj.phones) ? itemMemberObj.phones : [];
|
|
2218
2286
|
|
|
2287
|
+
const rawWebsite = (_$w('#UrlInput').value || '').trim();
|
|
2288
|
+
const rawBooking = (_$w('#schedulingLinkInput').value || '').trim();
|
|
2289
|
+
|
|
2219
2290
|
return {
|
|
2220
2291
|
showContactForm: _$w('#showCotactFormCheckbox').checked,
|
|
2221
2292
|
contactFormEmail: _$w('#contactFormEmailInput').value,
|
|
2222
2293
|
toShowPhone: getToShowPhone(),
|
|
2223
|
-
bookingUrl:
|
|
2224
|
-
website:
|
|
2294
|
+
bookingUrl: rawBooking ? normalizeExternalUrl(rawBooking) : '',
|
|
2295
|
+
website: rawWebsite ? normalizeExternalUrl(rawWebsite) : '',
|
|
2225
2296
|
showWebsite: showExistingUrl,
|
|
2226
2297
|
showWixUrl,
|
|
2227
2298
|
addresses,
|
package/public/Utils/homePage.js
CHANGED
|
@@ -5,37 +5,7 @@ const { DEFAULT_FILTER } = require('../consts.js');
|
|
|
5
5
|
|
|
6
6
|
const { debouncedFunction } = require('./sharedUtils.js');
|
|
7
7
|
|
|
8
|
-
/** Returned when an in-flight search was superseded; do not apply results to UI */
|
|
9
|
-
const STALE_SEARCH_RESPONSE = Symbol('STALE_SEARCH_RESPONSE');
|
|
10
|
-
|
|
11
|
-
function generateSearchId() {
|
|
12
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
13
|
-
const r = (Math.random() * 16) | 0;
|
|
14
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
15
|
-
return v.toString(16);
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
8
|
const createHomepageUtils = (_$w, filterProfiles) => {
|
|
20
|
-
let currentSearchId = null;
|
|
21
|
-
|
|
22
|
-
async function fetchProfilesWithSearchId(args) {
|
|
23
|
-
const thisSearchId = generateSearchId();
|
|
24
|
-
currentSearchId = thisSearchId;
|
|
25
|
-
try {
|
|
26
|
-
const response = await filterProfiles(args);
|
|
27
|
-
if (thisSearchId !== currentSearchId) {
|
|
28
|
-
return STALE_SEARCH_RESPONSE;
|
|
29
|
-
}
|
|
30
|
-
return response;
|
|
31
|
-
} catch (error) {
|
|
32
|
-
if (thisSearchId !== currentSearchId) {
|
|
33
|
-
return STALE_SEARCH_RESPONSE;
|
|
34
|
-
}
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
9
|
const getFiltersSelectors = filterName => ({
|
|
40
10
|
checkBoxContainerSelector: _$w(`#${filterName}CheckBoxContainer`),
|
|
41
11
|
searchTextInputSelector: _$w(`#${filterName}TextInput`),
|
|
@@ -717,10 +687,7 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
717
687
|
}
|
|
718
688
|
const nonDebouncedFilterProfiles = async () => {
|
|
719
689
|
try {
|
|
720
|
-
const result = await
|
|
721
|
-
if (result === STALE_SEARCH_RESPONSE) {
|
|
722
|
-
return { success: true, response: STALE_SEARCH_RESPONSE };
|
|
723
|
-
}
|
|
690
|
+
const result = await filterProfiles({ filter, isSearchingNearby });
|
|
724
691
|
return { success: true, response: result };
|
|
725
692
|
} catch (error) {
|
|
726
693
|
return { success: false, error };
|
|
@@ -732,15 +699,12 @@ const createHomepageUtils = (_$w, filterProfiles) => {
|
|
|
732
699
|
? () => nonDebouncedFilterProfiles()
|
|
733
700
|
: () =>
|
|
734
701
|
debouncedFunction({
|
|
735
|
-
func:
|
|
702
|
+
func: filterProfiles,
|
|
736
703
|
debounceTimeout,
|
|
737
704
|
timeoutType,
|
|
738
705
|
args: { filter, isSearchingNearby },
|
|
739
706
|
});
|
|
740
707
|
const { success, response, error } = await funcPromise();
|
|
741
|
-
if (response === STALE_SEARCH_RESPONSE) {
|
|
742
|
-
return [];
|
|
743
|
-
}
|
|
744
708
|
if (!success) {
|
|
745
709
|
_$w('#numberOfResults').text = '';
|
|
746
710
|
console.error('[search] failed with error:', error);
|
|
@@ -186,6 +186,15 @@ function isWixHostedImage(imageUrl) {
|
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/** Web URLs only: bare hostnames get https:// so they are not treated as site-relative paths. */
|
|
190
|
+
function normalizeExternalUrl(url) {
|
|
191
|
+
if (!url || typeof url !== 'string') return url;
|
|
192
|
+
const trimmed = url.trim();
|
|
193
|
+
if (!trimmed) return trimmed;
|
|
194
|
+
if (/^https?:\/\//i.test(trimmed)) return trimmed;
|
|
195
|
+
return `https://${trimmed}`;
|
|
196
|
+
}
|
|
197
|
+
|
|
189
198
|
module.exports = {
|
|
190
199
|
checkAddressIsVisible,
|
|
191
200
|
formatPracticeAreasForDisplay,
|
|
@@ -198,4 +207,5 @@ module.exports = {
|
|
|
198
207
|
generateId,
|
|
199
208
|
formatAddress,
|
|
200
209
|
isWixHostedImage,
|
|
210
|
+
normalizeExternalUrl,
|
|
201
211
|
};
|