sr-npm 1.7.1214 → 1.7.1218

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.
@@ -34,6 +34,12 @@ const CAREERS_MULTI_BOXES_PAGE_CONSTS={
34
34
  RESULTS_MULTI_STATE_BOX: '#multiStateBox1',
35
35
  }
36
36
 
37
+ const PRIMARY_SEARCH_STATES={
38
+ CATEGORY_RESULTS: 'categoryResults',
39
+ JOB_RESULTS: 'jobResults',
40
+ NO_RESULTS: 'noResults',
41
+ }
42
+
37
43
  const TWG_JOBS_COLLECTION_FIELDS={
38
44
  LINK_JOBS_TITLE: 'link-jobs-title',
39
45
  LINK_JOBS_REF_ID_SLUG: 'link-jobs-refId-slug',
@@ -82,4 +88,5 @@ module.exports = {
82
88
  CATEGORY_CUSTOM_FIELD_ID_IN_CMS,
83
89
  possibleUrlParams,
84
90
  TWG_JOBS_COLLECTION_FIELDS,
91
+ PRIMARY_SEARCH_STATES,
85
92
  }
@@ -136,7 +136,13 @@ async function htmlRichContentConverter(sections,richContentConverterToken) {
136
136
  );
137
137
  if (response.ok) {
138
138
  const data = await response.json();
139
- richContentObject[sectionTitle] = data.richContent.richContent;
139
+ const richContentWithSpacing=addSpacingToRichContent(sectionData.text,data.richContent.richContent);
140
+ console.log("richContentWithSpacing ====");
141
+ console.log(richContentWithSpacing);
142
+
143
+ console.log("data.richContent.richContent ====");
144
+ console.log(data.richContent.richContent);
145
+ richContentObject[sectionTitle] = richContentWithSpacing
140
146
  }
141
147
  else {
142
148
  throw new Error("Error converting html to rich content response: "+response);
@@ -146,6 +152,180 @@ async function htmlRichContentConverter(sections,richContentConverterToken) {
146
152
  return richContentObject;
147
153
  }
148
154
 
155
+ //Adds empty paragraph nodes between sections in rich content
156
+ // to create visual spacing that the Wix RICOS converter strips out
157
+ function addSpacingToRichContent(html, richContent) {
158
+ if (!richContent || !richContent.nodes) {
159
+ return richContent;
160
+ }
161
+
162
+ // Extract paragraph texts from HTML that end with  
163
+ const htmlParagraphsWithSpace = [];
164
+ // Extract paragraphs with <br> tags
165
+ const htmlParagraphsWithBr = new Map(); // text -> array of parts split by <br>
166
+
167
+ const pTagRegex = /<p>(.*?)<\/p>/gi;
168
+ let match;
169
+
170
+ while ((match = pTagRegex.exec(html)) !== null) {
171
+ const content = match[1];
172
+
173
+ // Check if this paragraph ends with &#xa0; (before closing tags)
174
+ if (content.includes('&#xa0;')) {
175
+ const textOnly = content.replace(/<[^>]+>/g, '').trim();
176
+ htmlParagraphsWithSpace.push(textOnly);
177
+ }
178
+
179
+ // Check if this paragraph contains <br> tags
180
+ if (content.includes('<br>') || content.includes('<br/>') || content.includes('<br />')) {
181
+ // Split by <br> tags and extract text parts
182
+ const parts = content.split(/<br\s*\/?>/i).map(part =>
183
+ part.replace(/<[^>]+>/g, '').trim()
184
+ ).filter(part => part.length > 0);
185
+
186
+ if (parts.length > 1) {
187
+ // Store the parts for this paragraph
188
+ const fullText = content.replace(/<[^>]+>/g, '').replace(/\s+/g, '').trim();
189
+ htmlParagraphsWithBr.set(fullText, parts);
190
+ }
191
+ }
192
+ }
193
+
194
+ const nodes = richContent.nodes;
195
+ const newNodes = [];
196
+ let nodeIdCounter = 0;
197
+
198
+ // Check if a paragraph is bold (has BOLD decoration)
199
+ const isBoldParagraph = (node) => {
200
+ if (node.type !== 'PARAGRAPH') return false;
201
+ const decorations = node.nodes?.[0]?.textData?.decorations || [];
202
+ return decorations.some(d => d.type === 'BOLD');
203
+ };
204
+
205
+ // Check if a paragraph node's text matches one with &#xa0; in HTML
206
+ const needsSpacingAfter = (node) => {
207
+ if (node.type !== 'PARAGRAPH') return false;
208
+
209
+ // Add spacing after bold paragraphs
210
+ if (isBoldParagraph(node)) {
211
+ return true;
212
+ }
213
+
214
+ const text = node.nodes?.[0]?.textData?.text || '';
215
+ const trimmedText = text.trim();
216
+
217
+ // Check if this text matches any HTML paragraph that had &#xa0;
218
+ return htmlParagraphsWithSpace.some(htmlText => {
219
+ const cleanHtml = htmlText.replace(/&#xa0;/g, ' ').trim();
220
+ return trimmedText.includes(cleanHtml) || cleanHtml.includes(trimmedText);
221
+ });
222
+ };
223
+
224
+ // Check if a paragraph contains text that should be split by <br>
225
+ const shouldSplitByBr = (node) => {
226
+ if (node.type !== 'PARAGRAPH') return null;
227
+
228
+ const text = node.nodes?.[0]?.textData?.text || '';
229
+ const normalizedText = text.replace(/\s+/g, '').trim();
230
+
231
+ // Find matching HTML paragraph with <br>
232
+ for (const [htmlText, parts] of htmlParagraphsWithBr.entries()) {
233
+ if (normalizedText.includes(htmlText) || htmlText.includes(normalizedText)) {
234
+ return parts;
235
+ }
236
+ }
237
+ return null;
238
+ };
239
+
240
+ // Add spacing after bulleted lists
241
+ const isListEnd = (currentNode, nextNode) => {
242
+ return currentNode.type === 'BULLETED_LIST' &&
243
+ nextNode &&
244
+ nextNode.type === 'PARAGRAPH';
245
+ };
246
+
247
+ for (let i = 0; i < nodes.length; i++) {
248
+ const currentNode = nodes[i];
249
+ const nextNode = nodes[i + 1];
250
+
251
+ // Check if this paragraph should be split by <br>
252
+ const brParts = shouldSplitByBr(currentNode);
253
+ if (brParts && brParts.length > 1) {
254
+ // Split into multiple paragraphs and add spacing between them
255
+ const decorations = currentNode.nodes?.[0]?.textData?.decorations || [];
256
+
257
+ brParts.forEach((part, idx) => {
258
+ newNodes.push({
259
+ ...currentNode,
260
+ id: `${currentNode.id}_split_${idx}`,
261
+ nodes: [{
262
+ type: "TEXT",
263
+ id: "",
264
+ nodes: [],
265
+ textData: {
266
+ text: part,
267
+ decorations: decorations
268
+ }
269
+ }]
270
+ });
271
+
272
+ // Add empty paragraph after each split part except the last
273
+ if (idx < brParts.length - 1) {
274
+ newNodes.push(createEmptyParagraph(`empty_br_${nodeIdCounter++}`));
275
+ }
276
+ });
277
+
278
+ // Add spacing after the split paragraphs if there's a next node
279
+ if (nextNode) {
280
+ newNodes.push(createEmptyParagraph(`empty_${nodeIdCounter++}`));
281
+ }
282
+ } else {
283
+ newNodes.push(currentNode);
284
+
285
+ // Add empty paragraph ONLY after paragraphs with &#xa0; or after lists
286
+ if ((needsSpacingAfter(currentNode) || isListEnd(currentNode, nextNode)) && nextNode) {
287
+ newNodes.push(createEmptyParagraph(`empty_${nodeIdCounter++}`));
288
+ }
289
+ }
290
+ }
291
+
292
+ return {
293
+ ...richContent,
294
+ nodes: newNodes
295
+ };
296
+ }
297
+
298
+ function createEmptyParagraph(id) {
299
+ return {
300
+ type: "PARAGRAPH",
301
+ id: id,
302
+ nodes: [
303
+ {
304
+ type: "TEXT",
305
+ id: "",
306
+ nodes: [],
307
+ textData: {
308
+ text: "",
309
+ decorations: []
310
+ }
311
+ }
312
+ ],
313
+ paragraphData: {
314
+ textStyle: {
315
+ textAlignment: "AUTO"
316
+ }
317
+ }
318
+ };
319
+ }
320
+
321
+
322
+
323
+
324
+
325
+
326
+
327
+
328
+
149
329
 
150
330
 
151
331
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sr-npm",
3
- "version": "1.7.1214",
3
+ "version": "1.7.1218",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  "homepage": "https://github.com/psdevteamenterprise/sr-npm#readme",
19
19
  "dependencies": {
20
20
  "@hisense-staging/velo-npm": "3.0.19",
21
- "@wix/data": "^1.0.211",
21
+ "@wix/data": "^1.0.349",
22
22
  "@wix/essentials": "^0.1.24",
23
23
  "@wix/secrets": "1.0.53",
24
24
  "@wix/site-location": "^1.0.0",
@@ -1,5 +1,5 @@
1
1
  const { COLLECTIONS,CUSTOM_VALUES_COLLECTION_FIELDS,JOBS_COLLECTION_FIELDS } = require('../backend/collectionConsts');
2
- const { CAREERS_PAGE_SELECTORS } = require('../public/selectors');
2
+ const { CAREERS_PAGE_SELECTORS, GLOBAL_SECTIONS_SELECTORS } = require('../public/selectors');
3
3
 
4
4
  const { window } = require('@wix/site-window');
5
5
  const { queryParams,onChange} = require('wix-location-frontend');
@@ -18,11 +18,9 @@ const { groupValuesByField,
18
18
  getFieldByTitle,
19
19
  getCorrectOption,
20
20
  getOptionIndexFromCheckBox,
21
- loadPrimarySearchRepeater,
22
- bindPrimarySearch,
23
- primarySearch,
24
21
  getAllDatasetItems
25
22
  } = require('./pagesUtils');
23
+ const { handlePrimarySearch, queryPrimarySearchResults } = require('../public/primarySearchUtils');
26
24
 
27
25
 
28
26
  let dontUpdateThisCheckBox;
@@ -39,8 +37,6 @@ let currentSecondarySearchJobs=[] // current secondary search results that are d
39
37
  let secondarySearchIsFilled=false // whether the secondary search is filled with results
40
38
  let keywordAllJobs; // all jobs that are displayed in the jobs repeater when the keyword is filled
41
39
  let ActivateURLOnchange=true; // whether to activate the url onchange
42
- let considerAllJobs=false; // whether to consider all jobs or not
43
-
44
40
  const pagination = {
45
41
  pageSize: 10,
46
42
  currentPage: 1,
@@ -53,7 +49,7 @@ async function careersMultiBoxesPageOnReady(_$w,urlParams) {
53
49
  });
54
50
  await loadData(_$w);
55
51
  await loadJobsRepeater(_$w); // if we remove the await here the job list will be flaky , it doesn't fill it properly
56
- loadPrimarySearchRepeater(_$w);
52
+ handlePrimarySearch(_$w, allvaluesobjects);
57
53
  await loadFilters(_$w);
58
54
  loadSelectedValuesRepeater(_$w);
59
55
  bindSearchInput(_$w);
@@ -148,10 +144,10 @@ async function handleUrlParams(_$w,urlParams,handleBackAndForth=false) {
148
144
  let currentApplyFilterFlag=false;
149
145
  //apply this first to determine all jobs
150
146
  if(urlParams.keyword) {
151
- applyFiltering = await primarySearch(_$w, decodeURIComponent(urlParams.keyword));
147
+ applyFiltering = await queryPrimarySearchResults(_$w, decodeURIComponent(urlParams.keyword));
152
148
  _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value = decodeURIComponent(urlParams.keyword);
153
149
 
154
- const items = await getAllDatasetItems(_$w, CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_DATASET);
150
+ const items = await getAllDatasetItems(_$w, GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET);
155
151
 
156
152
  currentJobs = items;
157
153
  keywordAllJobs = items;
@@ -271,16 +267,11 @@ async function handleParams(_$w,param,values) {
271
267
  let fieldTitle=field.title.toLowerCase().replace(' ', '');
272
268
  fieldTitle==="brands"? fieldTitle="brand":fieldTitle;
273
269
  ActivateURLOnchange=false;
274
- const previousSelectedSize=selectedByField.size;
275
270
  if (updated.length) {
276
271
  selectedByField.set(fieldId, updated);
277
-
278
-
279
272
  queryParams.add({ [fieldTitle] : updated.map(val=>encodeURIComponent(val)).join(',') });
280
273
  } else {
281
274
  selectedByField.delete(fieldId);
282
- handleConsiderAllJobs(previousSelectedSize,selectedByField.size);
283
-
284
275
  queryParams.remove([fieldTitle ]);
285
276
  }
286
277
 
@@ -389,12 +380,8 @@ async function loadJobsRepeater(_$w) {
389
380
  let fieldTitle=field.title.toLowerCase().replace(' ', '');
390
381
  fieldTitle==="brands"? fieldTitle="brand":fieldTitle;
391
382
  ActivateURLOnchange=false;
392
- const previousSelectedSize=selectedByField.size;
393
-
394
383
  if (selected && selected.length) {
395
384
  selectedByField.set(field._id, selected);
396
-
397
-
398
385
  if(fieldTitle==="brand" || fieldTitle==="storename") {
399
386
  //in this case we need the label not valueid
400
387
  const valueLabels=getValueFromValueId(selected,value);
@@ -405,8 +392,7 @@ async function loadJobsRepeater(_$w) {
405
392
  }
406
393
 
407
394
  } else {
408
- selectedByField.delete(field._id);
409
- handleConsiderAllJobs(previousSelectedSize,selectedByField.size);
395
+ selectedByField.delete(field._id);
410
396
  queryParams.remove([fieldTitle ]);
411
397
  }
412
398
 
@@ -447,35 +433,14 @@ function getValueFromValueId(valueIds, value) {
447
433
  updateTotalJobsCountText(_$w);
448
434
  }
449
435
 
450
- function handleConsiderAllJobs(previousSelectedSize,currentSelectedSize) {
451
- if(previousSelectedSize===2 && currentSelectedSize===1) {
452
-
453
- considerAllJobs=true;
454
- }
455
- else{
456
- considerAllJobs=false;
457
- }
458
- }
459
-
460
436
  function updateOptionsUI(_$w,fieldTitle, fieldId, searchQuery,clearAll=false) {
461
437
  let base = optionsByFieldId.get(fieldId) || [];
462
- let countsMap=countsByFieldId.get(fieldId) || new Map();
463
- //const countsMap = countsByFieldId.get(fieldId) || new Map();
464
- if(considerAllJobs)
465
- {
466
- const selectedFieldId=Array.from( selectedByField.keys() )[0]
467
- if(selectedFieldId===fieldId) {
468
- const relevantFields=allvaluesobjects.filter(val=>val.customField===selectedFieldId)
469
- countsMap = new Map(relevantFields.map(val=>[val.valueId, val.count]));
470
- considerAllJobs=false;
471
- }
472
- }
438
+ const countsMap = countsByFieldId.get(fieldId) || new Map();
473
439
  if(dontUpdateThisCheckBox===fieldId && !clearAll && selectedByField.has(fieldId) )
474
440
  {
475
441
  dontUpdateThisCheckBox=null;
476
442
  return;
477
443
  }
478
-
479
444
  let filteredbase=[]
480
445
  for (const element of base)
481
446
  {
@@ -628,8 +593,8 @@ async function refreshFacetCounts(_$w,clearAll=false) {
628
593
 
629
594
  function countJobsPerField(jobs) {
630
595
  const fieldIds = Array.from(optionsByFieldId.keys());
631
-
632
596
  const currentJobsIds=jobs.map(job=>job._id);
597
+
633
598
  for (const fieldId of fieldIds) {
634
599
  let currentoptions = optionsByFieldId.get(fieldId)
635
600
  let counter=new Map();
@@ -700,8 +665,6 @@ async function secondarySearch(_$w,query) {
700
665
  }
701
666
  function bindSearchInput(_$w) {
702
667
  try {
703
- bindPrimarySearch(_$w, allvaluesobjects);
704
-
705
668
  const secondarySearchDebounced = debounce(async () => {
706
669
  const query = (_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.SECONDARY_SEARCH_INPUT).value || '').toLowerCase().trim();
707
670
  await secondarySearch(_$w, query);
@@ -6,7 +6,7 @@ const { location } = require("@wix/site-location");
6
6
  const { COLLECTIONS } = require('../backend/collectionConsts');
7
7
  const { careersMultiBoxesPageOnReady } = require('./careersMultiBoxesPage');
8
8
  const { debounce, getFilter} = require('../public/filterUtils');
9
- const { CAREERS_PAGE_SELECTORS, FILTER_FIELDS } = require('../public/selectors');
9
+ const { CAREERS_PAGE_SELECTORS, FILTER_FIELDS, GLOBAL_SECTIONS_SELECTORS } = require('../public/selectors');
10
10
  const { filterBrokenMarkers } = require('../public/utils');
11
11
 
12
12
  let currentLoadedItems =100;
@@ -58,10 +58,10 @@ async function careersPageOnReady(_$w,thisObject=null,queryParams=null) {
58
58
 
59
59
  function activateAutoLoad(_$w)
60
60
  {
61
- _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).onReady(() => {
61
+ _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).onReady(() => {
62
62
  updateCount(_$w);
63
63
  _$w(CAREERS_PAGE_SELECTORS.FOOTER).onViewportEnter(() => {
64
- if (currentLoadedItems<_$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).getTotalCount()) {
64
+ if (currentLoadedItems<_$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount()) {
65
65
  loadMoreJobs(_$w);
66
66
  }
67
67
  else {
@@ -81,7 +81,7 @@ async function loadMoreJobs(_$w) {
81
81
  pageParamSet = Number(pageParamSet) + 1;
82
82
  }
83
83
  if (shouldLoad) {
84
- _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).loadMore();
84
+ _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).loadMore();
85
85
  console.log("loading more jobs");
86
86
 
87
87
  currentLoadedItems = currentLoadedItems + itemsPerPage;
@@ -148,7 +148,7 @@ async function handlePageParam(_$w) {
148
148
  //scrolls a bit to load the dataset data
149
149
  await window.scrollTo(0, 200,{scrollAnimation:false});
150
150
  for (let i = 2; i <= queryPageVar; i++) {
151
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).loadMore();
151
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).loadMore();
152
152
  currentLoadedItems=currentLoadedItems+itemsPerPage
153
153
  }
154
154
  // the timeout is to wait for the repeater to render, then scroll to the last item.
@@ -170,7 +170,7 @@ async function handlePageParam(_$w) {
170
170
  }
171
171
 
172
172
  async function bind(_$w) {
173
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).onReady(async () => {
173
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).onReady(async () => {
174
174
  await updateCount(_$w);
175
175
  await updateMapMarkers(_$w);
176
176
 
@@ -337,8 +337,8 @@ async function applyFilters(_$w, skipUrlUpdate = false) {
337
337
  });
338
338
 
339
339
  const filter = await getFilter(filters, 'and');
340
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).setFilter(filter);
341
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).refresh();
340
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(filter);
341
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
342
342
 
343
343
  const count = await updateCount(_$w);
344
344
  console.log("updating map markers");
@@ -357,8 +357,8 @@ async function applyFilters(_$w, skipUrlUpdate = false) {
357
357
  async function resetFilters(_$w) {
358
358
  _$w(CAREERS_PAGE_SELECTORS.SEARCH_INPUT, CAREERS_PAGE_SELECTORS.DROPDOWN_DEPARTMENT, CAREERS_PAGE_SELECTORS.DROPDOWN_LOCATION, CAREERS_PAGE_SELECTORS.DROPDOWN_JOB_TYPE, CAREERS_PAGE_SELECTORS.DROPDOWN_BRAND).value = '';
359
359
 
360
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).setFilter(wixData.filter());
361
- await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).refresh();
360
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(wixData.filter());
361
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
362
362
 
363
363
  _$w(CAREERS_PAGE_SELECTORS.RESULTS_MULTI_STATE).changeState('results');
364
364
 
@@ -374,7 +374,7 @@ async function resetFilters(_$w) {
374
374
  }
375
375
 
376
376
  async function updateCount(_$w) {
377
- const count = await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).getTotalCount();
377
+ const count = await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
378
378
  _$w('#numOfPositionText').text = `Showing ${count} Open Positions`;
379
379
 
380
380
  return count;
@@ -485,8 +485,8 @@ async function handleJobTypeParam(_$w,jobType) {
485
485
  }
486
486
 
487
487
  async function updateMapMarkers(_$w){
488
- const numOfItems = await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).getTotalCount();
489
- const items = await _$w(CAREERS_PAGE_SELECTORS.JOBS_DATASET).getItems(0, numOfItems);
488
+ const numOfItems = await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
489
+ const items = await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getItems(0, numOfItems);
490
490
  const markers = filterBrokenMarkers(items.items).map(item => {
491
491
  const location = item.locationAddress.location;
492
492
  return {
package/pages/homePage.js CHANGED
@@ -4,7 +4,9 @@ const { filterBrokenMarkers } = require('../public/utils');
4
4
  const { location } = require('@wix/site-location');
5
5
  const {wixData} = require('wix-data');
6
6
  const { COLLECTIONS } = require('../backend/collectionConsts');
7
- const { bindPrimarySearch, getAllRecords, loadPrimarySearchRepeater } = require('./pagesUtils');
7
+ const { getAllRecords } = require('./pagesUtils');
8
+ const { handlePrimarySearch } = require('../public/primarySearchUtils');
9
+ const { GLOBAL_SECTIONS_SELECTORS } = require('../public/selectors');
8
10
 
9
11
  let thisObjectVar;
10
12
  let searchByCityFlag=false;
@@ -17,8 +19,7 @@ async function homePageOnReady(_$w,thisObject = null) {
17
19
 
18
20
  if(siteconfig.twg) {
19
21
  const allvaluesobjects = await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
20
- bindPrimarySearch(_$w, allvaluesobjects);
21
- loadPrimarySearchRepeater(_$w)
22
+ handlePrimarySearch(_$w, allvaluesobjects);
22
23
  console.log("siteconfig.twg: ",siteconfig.twg);
23
24
 
24
25
  if(siteconfig.twg === "external") {
@@ -161,10 +162,10 @@ async function handleSearchInput(_$w) {
161
162
 
162
163
  let filter = await getFilter(searchByTitle);
163
164
 
164
- await _$w('#jobsDataset').setFilter(filter);
165
- await _$w('#jobsDataset').refresh();
165
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(filter);
166
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
166
167
 
167
- count = _$w('#jobsDataset').getTotalCount();
168
+ count = _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
168
169
 
169
170
  if (count > 0) {
170
171
  searchByCityFlag = false;
@@ -172,9 +173,9 @@ async function handleSearchInput(_$w) {
172
173
  _$w('#searchMultiStateBox').changeState('results');
173
174
  } else {
174
175
  filter = await getFilter(searchByCity);
175
- await _$w('#jobsDataset').setFilter(filter);
176
- await _$w('#jobsDataset').refresh();
177
- count = _$w('#jobsDataset').getTotalCount();
176
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(filter);
177
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
178
+ count = _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
178
179
  if( count > 0 )
179
180
  {
180
181
  searchByCityFlag = true;
@@ -1,9 +1,6 @@
1
1
  const { items: wixData } = require('@wix/data');
2
2
  const { JOBS_COLLECTION_FIELDS,COLLECTIONS } = require('../backend/collectionConsts');
3
- const { CAREERS_MULTI_BOXES_PAGE_CONSTS, CATEGORY_CUSTOM_FIELD_ID_IN_CMS, TWG_JOBS_COLLECTION_FIELDS } = require('../backend/careersMultiBoxesPageIds');
4
- const { location } = require("@wix/site-location");
5
3
  const { normalizeString } = require('../backend/utils');
6
- const { getFilter } = require('../public/filterUtils');
7
4
 
8
5
  function groupValuesByField(values, refKey) {
9
6
  const map = new Map();
@@ -81,7 +78,13 @@ function getFieldByTitle(title,allFields) {
81
78
 
82
79
  function getCorrectOption(value,options,param) {
83
80
  const standardizedValue = normalizeString(value.toLowerCase())
84
- return options.find(option=>normalizeString(option.value.toLowerCase())===standardizedValue || normalizeString(option.label.toLowerCase())===standardizedValue);
81
+ if(param==="employmenttype" || param==="Employment Type" || param==="Store Name") //employmenttype have a problematic value, added Employment Type for updateOptionsUI fuinction, added Store Name because Store name and location have for example Blenheim
82
+ {
83
+ //option.value is the id,
84
+ return options.find(option=>normalizeString(option.value.toLowerCase())===standardizedValue);
85
+ }
86
+ //option.label is what we see live in the UI
87
+ return options.find(option=>normalizeString(option.label.toLowerCase())===standardizedValue);
85
88
  }
86
89
 
87
90
  function getOptionIndexFromCheckBox(options,value) {
@@ -93,151 +96,6 @@ function getOptionIndexFromCheckBox(options,value) {
93
96
  }
94
97
  }
95
98
 
96
- function loadPrimarySearchRepeater(_$w) {
97
-
98
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOB_RESULTS_REPEATER).onItemReady(async ($item, itemData) => {
99
- $item(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_POSITION_BUTTON).label = itemData.title || '';
100
- });
101
-
102
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOB_RESULTS_REPEATER_ITEM).onClick((event) => {
103
- const data = _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOB_RESULTS_REPEATER).data;
104
- const clickedItemData = data.find(
105
- (item) => item._id === event.context.itemId,
106
-
107
- );
108
- if(!clickedItemData[TWG_JOBS_COLLECTION_FIELDS.LINK_JOBS_TITLE] && !clickedItemData[TWG_JOBS_COLLECTION_FIELDS.LINK_JOBS_REF_ID_SLUG]) {
109
- console.error("clickedItemData does not have link-jobs-title or link-jobs-refId-slug");
110
- return;
111
- }
112
-
113
- location.to( clickedItemData[TWG_JOBS_COLLECTION_FIELDS.LINK_JOBS_TITLE]|| clickedItemData[TWG_JOBS_COLLECTION_FIELDS.LINK_JOBS_REF_ID_SLUG]);
114
-
115
-
116
- });
117
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).onItemReady(async ($item, itemData) => {
118
- $item(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_CATEGORY_BUTTON).label = itemData.title || '';
119
- });
120
-
121
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER_ITEM).onClick(async (event) => {
122
- const data = _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).data;
123
- const clickedItemData = data.find(
124
- (item) => item._id === event.context.itemId,
125
- );
126
- const baseUrl = await location.baseUrl();
127
- const encodedCategory=encodeURIComponent(clickedItemData._id);
128
- location.to(`${baseUrl}/search?category=${encodedCategory}`);
129
- });
130
-
131
- }
132
-
133
- function bindPrimarySearch(_$w, allvaluesobjects) {
134
-
135
- const handleSearchInput = async () => {
136
- const query = _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value?.toLowerCase().trim() || '';
137
- await primarySearch(_$w, query);
138
- }
139
-
140
- const primarySearchDebounced = debounce(() => handleSearchInput(), 400);
141
-
142
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onInput(async () => {
143
- await primarySearchDebounced();
144
- });
145
-
146
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onClick(async () => {
147
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
148
-
149
- if(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value.trim()!=='') {
150
- const query = _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value?.toLowerCase().trim() || '';
151
- await primarySearch(_$w, query);
152
- }
153
- else {
154
- await loadCategoriesListPrimarySearch(_$w,allvaluesobjects);
155
- }
156
- });
157
-
158
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).onMouseOut(async () => {
159
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
160
- });
161
-
162
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onKeyPress(async (event) => {
163
- if( event.key === 'Enter') {
164
- if(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value.trim()==='') {
165
- // _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
166
- const baseUrl = await location.baseUrl();
167
- location.to(`${baseUrl}/search`);
168
-
169
- }
170
- else {
171
- let encodedKeyWord=encodeURIComponent(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value);
172
- const baseUrl = await location.baseUrl();
173
- location.to(`${baseUrl}/search?keyword=${encodedKeyWord}`);
174
- }
175
- }
176
- });
177
-
178
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_BUTTON).onClick(async () => {
179
- if(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value.trim()==='') {
180
- const baseUrl = await location.baseUrl();
181
- location.to(`${baseUrl}/search`);
182
- }
183
- else {
184
- let encodedKeyWord=encodeURIComponent(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value);
185
- const baseUrl = await location.baseUrl();
186
- location.to(`${baseUrl}/search?keyword=${encodedKeyWord}`);
187
- }
188
- });
189
- }
190
-
191
- async function loadCategoriesListPrimarySearch(_$w, allvaluesobjects) {
192
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("categoryResults");
193
-
194
- let categoryValues=[]
195
- for(const value of allvaluesobjects) {
196
- if(value.customField === CATEGORY_CUSTOM_FIELD_ID_IN_CMS) {
197
- categoryValues.push({title: value.title+` (${value.count})` , _id: value.valueId});
198
- }
199
- }
200
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).data = categoryValues;
201
- }
202
-
203
- async function primarySearch(_$w, query) {
204
- if(query === undefined || query === '') {
205
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("categoryResults");
206
- return false;
207
- }
208
-
209
- const searchByTitle = [{field: 'title', searchTerm: query}];
210
- const searchByCity = [{field: 'location.fullLocation', searchTerm: query}];
211
-
212
- let filter = await getFilter(searchByTitle);
213
-
214
- await _$w('#jobsDataset').setFilter(filter);
215
- await _$w('#jobsDataset').refresh();
216
-
217
- let count = _$w('#jobsDataset').getTotalCount();
218
-
219
- if( count > 0 ) {
220
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
221
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("jobResults");
222
- }
223
- else {
224
- filter = await getFilter(searchByCity);
225
- await _$w('#jobsDataset').setFilter(filter);
226
- await _$w('#jobsDataset').refresh();
227
-
228
- count = _$w('#jobsDataset').getTotalCount();
229
- if (count > 0) {
230
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
231
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("jobResults");
232
- }
233
- else{
234
- _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("noResults");
235
- }
236
- }
237
-
238
- return count > 0;
239
- }
240
-
241
99
  async function getValueFromValueId(valueId) {
242
100
  const result = await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
243
101
  console.log("result: ",result);
@@ -262,9 +120,6 @@ module.exports = {
262
120
  getFieldByTitle,
263
121
  getCorrectOption,
264
122
  getOptionIndexFromCheckBox,
265
- loadPrimarySearchRepeater,
266
- bindPrimarySearch,
267
- primarySearch,
268
123
  getLatestJobsByValue,
269
124
  getValueFromValueId,
270
125
  getAllRecordsWithoutMultiRef,
package/public/index.js CHANGED
@@ -2,5 +2,6 @@ module.exports = {
2
2
  ...require('./utils'),
3
3
  ...require('./filterUtils'),
4
4
  ...require('./mapUtils'),
5
+ ...require('./primarySearchUtils'),
5
6
  };
6
7
 
@@ -0,0 +1,156 @@
1
+ const { location } = require("@wix/site-location");
2
+
3
+ const { CAREERS_MULTI_BOXES_PAGE_CONSTS, CATEGORY_CUSTOM_FIELD_ID_IN_CMS, PRIMARY_SEARCH_STATES } = require('../backend/careersMultiBoxesPageIds');
4
+ const { GLOBAL_SECTIONS_SELECTORS } = require('../public/selectors');
5
+ const { getFilter } = require('../public/filterUtils');
6
+ const { debounce } = require('../pages/pagesUtils');
7
+
8
+ async function handlePrimarySearch(_$w, allvaluesobjects) {
9
+ // load the categories list before clicking on the primary search input
10
+ loadCategoryRepeaterData(_$w, allvaluesobjects);
11
+
12
+ // wait for the jobs dataset to be ready
13
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).onReadyAsync();
14
+
15
+ await bindPrimarySearch(_$w);
16
+ }
17
+
18
+ function loadCategoryRepeaterData(_$w, allvaluesobjects) {
19
+ let categoryValues=[]
20
+ for(const value of allvaluesobjects) {
21
+ if(value.customField === CATEGORY_CUSTOM_FIELD_ID_IN_CMS) {
22
+ categoryValues.push({title: value.title+` (${value.count})` , _id: value.valueId});
23
+ }
24
+ }
25
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).data = categoryValues;
26
+ }
27
+
28
+ async function bindPrimarySearch(_$w) {
29
+ handleCategoryEvents(_$w);
30
+
31
+ await handleSearchInput(_$w);
32
+
33
+ // on mouse out collapse the results container
34
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).onMouseOut(async () => {
35
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
36
+ });
37
+
38
+ // handle the click on the search button
39
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_BUTTON).onClick(async () => {
40
+ if(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value.trim()==='') {
41
+ const baseUrl = await location.baseUrl();
42
+ location.to(`${baseUrl}/search`);
43
+ }
44
+ else {
45
+ let encodedKeyWord=encodeURIComponent(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value);
46
+ const baseUrl = await location.baseUrl();
47
+ location.to(`${baseUrl}/search?keyword=${encodedKeyWord}`);
48
+ }
49
+ });
50
+ }
51
+
52
+ function handleCategoryEvents(_$w) {
53
+ // set the label of the category repeater item
54
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).onItemReady(async ($item, itemData) => {
55
+ $item(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_CATEGORY_BUTTON).label = itemData.title || '';
56
+ });
57
+
58
+ // handle the category repeater item on click
59
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER_ITEM).onClick(async (event) => {
60
+ const data = _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).data;
61
+ const clickedItemData = data.find(
62
+ (item) => item._id === event.context.itemId,
63
+ );
64
+ const baseUrl = await location.baseUrl();
65
+ const encodedCategory=encodeURIComponent(clickedItemData._id);
66
+ location.to(`${baseUrl}/search?category=${encodedCategory}`);
67
+ });
68
+
69
+ }
70
+
71
+ function getSearchQuery(_$w) {
72
+ return _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value?.toLowerCase().trim() || '';
73
+ }
74
+
75
+ async function handleSearchInput(_$w) {
76
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).enable();
77
+
78
+ // on Input call the queryPrimarySearchResults function
79
+ const callQueryPrimarySearchResults = async () => {
80
+ await queryPrimarySearchResults(_$w, getSearchQuery(_$w));
81
+ }
82
+
83
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onInput(async () => {
84
+ await debounce(() => callQueryPrimarySearchResults(), 300)();
85
+ });
86
+
87
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onClick(async () => {
88
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
89
+
90
+ const searchQuery = getSearchQuery(_$w);
91
+ if(searchQuery !== '') {
92
+ await queryPrimarySearchResults(_$w, searchQuery);
93
+ }
94
+ else {
95
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState(PRIMARY_SEARCH_STATES.CATEGORY_RESULTS);
96
+ }
97
+ });
98
+
99
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).onKeyPress(async (event) => {
100
+ if( event.key === 'Enter') {
101
+ if(getSearchQuery(_$w) === '') {
102
+ // _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
103
+ const baseUrl = await location.baseUrl();
104
+ location.to(`${baseUrl}/search`);
105
+
106
+ }
107
+ else {
108
+ let encodedKeyWord=encodeURIComponent(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value);
109
+ const baseUrl = await location.baseUrl();
110
+ location.to(`${baseUrl}/search?keyword=${encodedKeyWord}`);
111
+ }
112
+ }
113
+ });
114
+ }
115
+
116
+ async function queryPrimarySearchResults(_$w, query) {
117
+ if(query === undefined || query === '') {
118
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState(PRIMARY_SEARCH_STATES.CATEGORY_RESULTS);
119
+ return false;
120
+ }
121
+
122
+ const searchByTitle = [{field: 'title', searchTerm: query}];
123
+ const searchByCity = [{field: 'location.fullLocation', searchTerm: query}];
124
+
125
+ let filter = await getFilter(searchByTitle);
126
+
127
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(filter);
128
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
129
+
130
+ let count = _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
131
+
132
+ if( count > 0 ) {
133
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
134
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState(PRIMARY_SEARCH_STATES.JOB_RESULTS);
135
+ }
136
+ else {
137
+ filter = await getFilter(searchByCity);
138
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).setFilter(filter);
139
+ await _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).refresh();
140
+
141
+ count = _$w(GLOBAL_SECTIONS_SELECTORS.JOBS_DATASET).getTotalCount();
142
+ if (count > 0) {
143
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).expand();
144
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState(PRIMARY_SEARCH_STATES.JOB_RESULTS);
145
+ }
146
+ else{
147
+ _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState(PRIMARY_SEARCH_STATES.NO_RESULTS);
148
+ }
149
+ }
150
+
151
+ return count > 0;
152
+ }
153
+
154
+ module.exports = {
155
+ handlePrimarySearch,
156
+ }
@@ -26,19 +26,22 @@ const CAREERS_PAGE_SELECTORS = {
26
26
  OPEN_FILTERS_BUTTON: '#openFiltersButton',
27
27
  CLOSE_FILTERS_BUTTON: '#closeFiltersButton',
28
28
  RESET_FILTERS_BUTTON: '#resetFiltersButton',
29
- RESET_FILTERS_BUTTON: '#resetFiltersButton',
30
29
 
31
30
  RESULTS_MULTI_STATE: '#resultsMultiState',
32
31
  BRANDS_DATASET: '#brandsDataset',
33
32
  DEPARTMENTS_DATASET: '#departmentsDataset',
34
33
  LOCATIONS_DATASET: '#locationsDataset',
35
34
  JOB_TYPES_DATASET: '#jobTypesDataset',
36
- JOBS_DATASET: '#jobsDataset',
37
35
 
38
36
  GOOGLE_MAPS: '#googleMaps',
39
37
  FOOTER: '#footer',
40
38
  }
41
39
 
40
+ const GLOBAL_SECTIONS_SELECTORS = {
41
+ JOBS_DATASET: '#jobsDataset',
42
+
43
+ }
44
+
42
45
  const FILTER_FIELDS = {
43
46
  DEPARTMENT: 'department',
44
47
  LOCATION: 'cityText',
@@ -49,5 +52,6 @@ const FILTER_FIELDS = {
49
52
 
50
53
  module.exports = {
51
54
  CAREERS_PAGE_SELECTORS,
55
+ GLOBAL_SECTIONS_SELECTORS,
52
56
  FILTER_FIELDS,
53
57
  }