abmp-npm 10.0.62 → 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 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
  };
@@ -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
+ };
@@ -6,4 +6,5 @@ module.exports = {
6
6
  ...require('./url-migration-methods'),
7
7
  ...require('./address-primary-methods'),
8
8
  ...require('./url-space-fix-methods'),
9
+ ...require('./daily-pull-backup-check-methods'),
9
10
  };
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abmp-npm",
3
- "version": "10.0.62",
3
+ "version": "10.0.63",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "check-cycles": "madge --circular .",
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();
@@ -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 { generateId, isWixHostedImage } = require('../public/Utils/sharedUtils');
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;
@@ -2280,12 +2284,15 @@ async function personalDetailsOnReady({
2280
2284
  const addresses = Array.isArray(itemMemberObj.addresses) ? itemMemberObj.addresses : [];
2281
2285
  const phones = Array.isArray(itemMemberObj.phones) ? itemMemberObj.phones : [];
2282
2286
 
2287
+ const rawWebsite = (_$w('#UrlInput').value || '').trim();
2288
+ const rawBooking = (_$w('#schedulingLinkInput').value || '').trim();
2289
+
2283
2290
  return {
2284
2291
  showContactForm: _$w('#showCotactFormCheckbox').checked,
2285
2292
  contactFormEmail: _$w('#contactFormEmailInput').value,
2286
2293
  toShowPhone: getToShowPhone(),
2287
- bookingUrl: _$w('#schedulingLinkInput').value,
2288
- website: _$w('#UrlInput').value,
2294
+ bookingUrl: rawBooking ? normalizeExternalUrl(rawBooking) : '',
2295
+ website: rawWebsite ? normalizeExternalUrl(rawWebsite) : '',
2289
2296
  showWebsite: showExistingUrl,
2290
2297
  showWixUrl,
2291
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
  };