abmp-npm 10.0.61 → 10.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/backend/jobs.js +15 -0
- package/backend/tasks/consts.js +2 -0
- package/backend/tasks/daily-pull-backup-check-methods.js +106 -0
- package/backend/tasks/index.js +1 -0
- package/backend/tasks/tasks-configs.js +18 -0
- package/package.json +1 -1
- package/pages/Home.js +3 -2
- package/pages/personalDetails.js +29 -3
- package/public/Utils/sharedUtils.js +10 -0
package/backend/jobs.js
CHANGED
|
@@ -96,6 +96,20 @@ async function scheduleFixUrlsWithSpacesTask() {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
async function scheduleDailyPullExecutionCheckTask() {
|
|
100
|
+
try {
|
|
101
|
+
console.log('scheduleDailyPullExecutionCheck started!');
|
|
102
|
+
return await taskManager().schedule({
|
|
103
|
+
name: TASKS_NAMES.scheduleDailyPullExecutionCheck,
|
|
104
|
+
data: {},
|
|
105
|
+
type: 'scheduled',
|
|
106
|
+
});
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error(`Failed to scheduleDailyPullExecutionCheck: ${error.message}`);
|
|
109
|
+
throw new Error(`Failed to scheduleDailyPullExecutionCheck: ${error.message}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
99
113
|
async function updateSiteMapS3() {
|
|
100
114
|
try {
|
|
101
115
|
return await taskManager().schedule({
|
|
@@ -115,4 +129,5 @@ module.exports = {
|
|
|
115
129
|
scheduleCreateContactsFromMembersTask,
|
|
116
130
|
scheduleFixPrimaryAddressForMembersTask,
|
|
117
131
|
scheduleFixUrlsWithSpacesTask,
|
|
132
|
+
scheduleDailyPullExecutionCheckTask,
|
|
118
133
|
};
|
package/backend/tasks/consts.js
CHANGED
|
@@ -22,6 +22,8 @@ const TASKS_NAMES = {
|
|
|
22
22
|
fixPrimaryAddressChunk: 'fixPrimaryAddressChunk',
|
|
23
23
|
scheduleFixUrlsWithSpaces: 'scheduleFixUrlsWithSpaces',
|
|
24
24
|
fixUrlsWithSpacesChunk: 'fixUrlsWithSpacesChunk',
|
|
25
|
+
scheduleDailyPullExecutionCheck: 'scheduleDailyPullExecutionCheck',
|
|
26
|
+
dailyPullExecutionCheck: 'dailyPullExecutionCheck',
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
module.exports = {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const { taskManager } = require('psdev-task-manager');
|
|
2
|
+
const { COLLECTIONS } = require('psdev-task-manager/public/consts');
|
|
3
|
+
|
|
4
|
+
const { MEMBER_ACTIONS } = require('../daily-pull/consts');
|
|
5
|
+
const { wixData } = require('../elevated-modules');
|
|
6
|
+
const { queryAllItems } = require('../utils');
|
|
7
|
+
|
|
8
|
+
const { TASKS_NAMES } = require('./consts');
|
|
9
|
+
|
|
10
|
+
const DEFAULT_HOURS_BACK = 4;
|
|
11
|
+
|
|
12
|
+
const getActionsToCheck = includeNone =>
|
|
13
|
+
includeNone
|
|
14
|
+
? Object.values(MEMBER_ACTIONS)
|
|
15
|
+
: Object.values(MEMBER_ACTIONS).filter(action => action !== MEMBER_ACTIONS.NONE);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Schedules an execution check for daily pull status.
|
|
19
|
+
*/
|
|
20
|
+
async function scheduleDailyPullExecutionCheck() {
|
|
21
|
+
try {
|
|
22
|
+
console.log('scheduleDailyPullExecutionCheck started!');
|
|
23
|
+
return await taskManager().schedule({
|
|
24
|
+
name: TASKS_NAMES.dailyPullExecutionCheck,
|
|
25
|
+
data: { hoursBack: DEFAULT_HOURS_BACK, includeNone: false },
|
|
26
|
+
type: 'scheduled',
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(`Failed to scheduleDailyPullExecutionCheck: ${error.message}`);
|
|
30
|
+
throw new Error(`Failed to scheduleDailyPullExecutionCheck: ${error.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Verifies ScheduleMembersDataPerAction tasks exist and succeeded per action.
|
|
36
|
+
*/
|
|
37
|
+
async function dailyPullExecutionCheck(taskData) {
|
|
38
|
+
const hoursBack =
|
|
39
|
+
taskData?.hoursBack && Number.isFinite(taskData.hoursBack)
|
|
40
|
+
? taskData.hoursBack
|
|
41
|
+
: DEFAULT_HOURS_BACK;
|
|
42
|
+
const includeNone = Boolean(taskData?.includeNone);
|
|
43
|
+
const sinceDate = new Date(Date.now() - hoursBack * 60 * 60 * 1000);
|
|
44
|
+
|
|
45
|
+
console.log('dailyPullExecutionCheck started', { hoursBack, sinceDate });
|
|
46
|
+
|
|
47
|
+
const tasksQuery = wixData
|
|
48
|
+
.query(COLLECTIONS.TASKS)
|
|
49
|
+
.eq('name', TASKS_NAMES.ScheduleMembersDataPerAction)
|
|
50
|
+
.ge('_createdDate', sinceDate)
|
|
51
|
+
.limit(1000);
|
|
52
|
+
|
|
53
|
+
const tasks = await queryAllItems(tasksQuery);
|
|
54
|
+
const actionsToCheck = getActionsToCheck(includeNone);
|
|
55
|
+
|
|
56
|
+
const statusByAction = actionsToCheck.reduce((acc, action) => {
|
|
57
|
+
acc[action] = { success: 0, failed: 0, pending: 0, in_progress: 0, skipped: 0 };
|
|
58
|
+
return acc;
|
|
59
|
+
}, {});
|
|
60
|
+
|
|
61
|
+
tasks.forEach(task => {
|
|
62
|
+
const action = task?.data?.action;
|
|
63
|
+
if (!action || !(action in statusByAction)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const status = task?.status || 'unknown';
|
|
67
|
+
if (!statusByAction[action][status]) {
|
|
68
|
+
statusByAction[action][status] = 0;
|
|
69
|
+
}
|
|
70
|
+
statusByAction[action][status] += 1;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const missingActions = actionsToCheck.filter(
|
|
74
|
+
action => (statusByAction[action]?.success || 0) === 0
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const result = {
|
|
78
|
+
success: missingActions.length === 0,
|
|
79
|
+
sinceDate: sinceDate.toISOString(),
|
|
80
|
+
actionsChecked: actionsToCheck,
|
|
81
|
+
missingActions,
|
|
82
|
+
statusByAction,
|
|
83
|
+
totalTasksFound: tasks.length,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
if (missingActions.length > 0) {
|
|
87
|
+
console.log('Missing daily pull actions detected, scheduling fallback daily pull run', {
|
|
88
|
+
missingActions,
|
|
89
|
+
});
|
|
90
|
+
await taskManager().schedule({
|
|
91
|
+
name: TASKS_NAMES.ScheduleDailyMembersDataSync,
|
|
92
|
+
data: {},
|
|
93
|
+
type: 'scheduled',
|
|
94
|
+
});
|
|
95
|
+
result.fallbackScheduled = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('dailyPullExecutionCheck result', JSON.stringify(result, null, 2));
|
|
99
|
+
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = {
|
|
104
|
+
scheduleDailyPullExecutionCheck,
|
|
105
|
+
dailyPullExecutionCheck,
|
|
106
|
+
};
|
package/backend/tasks/index.js
CHANGED
|
@@ -9,6 +9,10 @@ const {
|
|
|
9
9
|
fixPrimaryAddressChunk,
|
|
10
10
|
} = require('./address-primary-methods');
|
|
11
11
|
const { TASKS_NAMES } = require('./consts');
|
|
12
|
+
const {
|
|
13
|
+
scheduleDailyPullExecutionCheck,
|
|
14
|
+
dailyPullExecutionCheck,
|
|
15
|
+
} = require('./daily-pull-backup-check-methods');
|
|
12
16
|
const {
|
|
13
17
|
scheduleTaskForEmptyAboutYouMembers,
|
|
14
18
|
convertAboutYouHtmlToRichContent,
|
|
@@ -202,6 +206,20 @@ const TASKS = {
|
|
|
202
206
|
shouldSkipCheck: () => false,
|
|
203
207
|
estimatedDurationSec: 80,
|
|
204
208
|
},
|
|
209
|
+
[TASKS_NAMES.scheduleDailyPullExecutionCheck]: {
|
|
210
|
+
name: TASKS_NAMES.scheduleDailyPullExecutionCheck,
|
|
211
|
+
getIdentifier: () => 'SHOULD_NEVER_SKIP',
|
|
212
|
+
process: scheduleDailyPullExecutionCheck,
|
|
213
|
+
shouldSkipCheck: () => false,
|
|
214
|
+
estimatedDurationSec: 30,
|
|
215
|
+
},
|
|
216
|
+
[TASKS_NAMES.dailyPullExecutionCheck]: {
|
|
217
|
+
name: TASKS_NAMES.dailyPullExecutionCheck,
|
|
218
|
+
getIdentifier: task => task.data,
|
|
219
|
+
process: dailyPullExecutionCheck,
|
|
220
|
+
shouldSkipCheck: () => false,
|
|
221
|
+
estimatedDurationSec: 30,
|
|
222
|
+
},
|
|
205
223
|
};
|
|
206
224
|
|
|
207
225
|
module.exports = { TASKS };
|
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 }
|
|
@@ -2142,9 +2151,23 @@ async function personalDetailsOnReady({
|
|
|
2142
2151
|
const repeater = _$w('#phoneNumbersList');
|
|
2143
2152
|
|
|
2144
2153
|
repeater.data = phoneData;
|
|
2154
|
+
refreshPhoneShowCheckboxState(phoneData);
|
|
2145
2155
|
updatePhoneAddButtonState();
|
|
2146
2156
|
}
|
|
2147
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
|
+
|
|
2148
2171
|
function updatePhoneAddButtonState() {
|
|
2149
2172
|
const currentData = _$w('#phoneNumbersList').data || [];
|
|
2150
2173
|
const addPhoneButton = _$w('#addPhoneButton');
|
|
@@ -2261,12 +2284,15 @@ async function personalDetailsOnReady({
|
|
|
2261
2284
|
const addresses = Array.isArray(itemMemberObj.addresses) ? itemMemberObj.addresses : [];
|
|
2262
2285
|
const phones = Array.isArray(itemMemberObj.phones) ? itemMemberObj.phones : [];
|
|
2263
2286
|
|
|
2287
|
+
const rawWebsite = (_$w('#UrlInput').value || '').trim();
|
|
2288
|
+
const rawBooking = (_$w('#schedulingLinkInput').value || '').trim();
|
|
2289
|
+
|
|
2264
2290
|
return {
|
|
2265
2291
|
showContactForm: _$w('#showCotactFormCheckbox').checked,
|
|
2266
2292
|
contactFormEmail: _$w('#contactFormEmailInput').value,
|
|
2267
2293
|
toShowPhone: getToShowPhone(),
|
|
2268
|
-
bookingUrl:
|
|
2269
|
-
website:
|
|
2294
|
+
bookingUrl: rawBooking ? normalizeExternalUrl(rawBooking) : '',
|
|
2295
|
+
website: rawWebsite ? normalizeExternalUrl(rawWebsite) : '',
|
|
2270
2296
|
showWebsite: showExistingUrl,
|
|
2271
2297
|
showWixUrl,
|
|
2272
2298
|
addresses,
|
|
@@ -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
|
};
|