sr-npm 3.1.25 → 3.1.27
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.
|
@@ -119,8 +119,10 @@ async function htmlRichContentConverter(sections,richContentConverterToken) {
|
|
|
119
119
|
const richContentObject = {}
|
|
120
120
|
for (const [sectionTitle, sectionData] of Object.entries(sections)) {
|
|
121
121
|
if (sectionData.text) {
|
|
122
|
+
// Strip span tags but keep their content , since <span> tags paragraphs are deleted by the converter
|
|
123
|
+
const cleanedHtml = sectionData.text.replace(/<\/?span[^>]*>/gi, '');
|
|
122
124
|
const raw = JSON.stringify({
|
|
123
|
-
content:
|
|
125
|
+
content: cleanedHtml,
|
|
124
126
|
});
|
|
125
127
|
const requestOptions = {
|
|
126
128
|
method: 'post',
|
|
@@ -137,7 +139,10 @@ async function htmlRichContentConverter(sections,richContentConverterToken) {
|
|
|
137
139
|
);
|
|
138
140
|
if (response.ok) {
|
|
139
141
|
const data = await response.json();
|
|
140
|
-
|
|
142
|
+
// Fix list items with nested paragraphs (causes line breaks after bold text)
|
|
143
|
+
const flattenedContent = flattenListItems(data.richContent.richContent);
|
|
144
|
+
// const richContentWithSpacing=addSpacingToRichContent(cleanedHtml,flattenedContent);
|
|
145
|
+
const richContentWithSpacing=addEmptyParagraphsBetweenConsecutive(cleanedHtml,flattenedContent);
|
|
141
146
|
richContentObject[sectionTitle] = richContentWithSpacing
|
|
142
147
|
}
|
|
143
148
|
else {
|
|
@@ -148,148 +153,6 @@ async function htmlRichContentConverter(sections,richContentConverterToken) {
|
|
|
148
153
|
return richContentObject;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
//Adds empty paragraph nodes between sections in rich content
|
|
152
|
-
// to create visual spacing that the Wix RICOS converter strips out
|
|
153
|
-
function addSpacingToRichContent(html, richContent) {
|
|
154
|
-
if (!richContent || !richContent.nodes) {
|
|
155
|
-
return richContent;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Extract paragraph texts from HTML that end with  
|
|
159
|
-
const htmlParagraphsWithSpace = [];
|
|
160
|
-
// Extract paragraphs with <br> tags
|
|
161
|
-
const htmlParagraphsWithBr = new Map(); // text -> array of parts split by <br>
|
|
162
|
-
|
|
163
|
-
const pTagRegex = /<p>(.*?)<\/p>/gi;
|
|
164
|
-
let match;
|
|
165
|
-
|
|
166
|
-
while ((match = pTagRegex.exec(html)) !== null) {
|
|
167
|
-
const content = match[1];
|
|
168
|
-
|
|
169
|
-
// Check if this paragraph ends with   (before closing tags)
|
|
170
|
-
if (content.includes(' ')) {
|
|
171
|
-
const textOnly = content.replace(/<[^>]+>/g, '').trim();
|
|
172
|
-
htmlParagraphsWithSpace.push(textOnly);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Check if this paragraph contains <br> tags
|
|
176
|
-
if (content.includes('<br>') || content.includes('<br/>') || content.includes('<br />')) {
|
|
177
|
-
// Split by <br> tags and extract text parts
|
|
178
|
-
const parts = content.split(/<br\s*\/?>/i).map(part =>
|
|
179
|
-
part.replace(/<[^>]+>/g, '').trim()
|
|
180
|
-
).filter(part => part.length > 0);
|
|
181
|
-
|
|
182
|
-
if (parts.length > 1) {
|
|
183
|
-
// Store the parts for this paragraph
|
|
184
|
-
const fullText = content.replace(/<[^>]+>/g, '').replace(/\s+/g, '').trim();
|
|
185
|
-
htmlParagraphsWithBr.set(fullText, parts);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const nodes = richContent.nodes;
|
|
191
|
-
const newNodes = [];
|
|
192
|
-
let nodeIdCounter = 0;
|
|
193
|
-
|
|
194
|
-
// Check if a paragraph is bold (has BOLD decoration)
|
|
195
|
-
const isBoldParagraph = (node) => {
|
|
196
|
-
if (node.type !== 'PARAGRAPH') return false;
|
|
197
|
-
const decorations = node.nodes?.[0]?.textData?.decorations || [];
|
|
198
|
-
return decorations.some(d => d.type === 'BOLD');
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// Check if a paragraph node's text matches one with   in HTML
|
|
202
|
-
const needsSpacingAfter = (node) => {
|
|
203
|
-
if (node.type !== 'PARAGRAPH') return false;
|
|
204
|
-
|
|
205
|
-
// Add spacing after bold paragraphs
|
|
206
|
-
if (isBoldParagraph(node)) {
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const text = node.nodes?.[0]?.textData?.text || '';
|
|
211
|
-
const trimmedText = text.trim();
|
|
212
|
-
|
|
213
|
-
// Check if this text matches any HTML paragraph that had  
|
|
214
|
-
return htmlParagraphsWithSpace.some(htmlText => {
|
|
215
|
-
const cleanHtml = htmlText.replace(/ /g, ' ').trim();
|
|
216
|
-
return trimmedText.includes(cleanHtml) || cleanHtml.includes(trimmedText);
|
|
217
|
-
});
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
// Check if a paragraph contains text that should be split by <br>
|
|
221
|
-
const shouldSplitByBr = (node) => {
|
|
222
|
-
if (node.type !== 'PARAGRAPH') return null;
|
|
223
|
-
|
|
224
|
-
const text = node.nodes?.[0]?.textData?.text || '';
|
|
225
|
-
const normalizedText = text.replace(/\s+/g, '').trim();
|
|
226
|
-
|
|
227
|
-
// Find matching HTML paragraph with <br>
|
|
228
|
-
for (const [htmlText, parts] of htmlParagraphsWithBr.entries()) {
|
|
229
|
-
if (normalizedText.includes(htmlText) || htmlText.includes(normalizedText)) {
|
|
230
|
-
return parts;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return null;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
// Add spacing after bulleted lists
|
|
237
|
-
const isListEnd = (currentNode, nextNode) => {
|
|
238
|
-
return currentNode.type === 'BULLETED_LIST' &&
|
|
239
|
-
nextNode &&
|
|
240
|
-
nextNode.type === 'PARAGRAPH';
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
244
|
-
const currentNode = nodes[i];
|
|
245
|
-
const nextNode = nodes[i + 1];
|
|
246
|
-
|
|
247
|
-
// Check if this paragraph should be split by <br>
|
|
248
|
-
const brParts = shouldSplitByBr(currentNode);
|
|
249
|
-
if (brParts && brParts.length > 1) {
|
|
250
|
-
// Split into multiple paragraphs and add spacing between them
|
|
251
|
-
const decorations = currentNode.nodes?.[0]?.textData?.decorations || [];
|
|
252
|
-
|
|
253
|
-
brParts.forEach((part, idx) => {
|
|
254
|
-
newNodes.push({
|
|
255
|
-
...currentNode,
|
|
256
|
-
id: `${currentNode.id}_split_${idx}`,
|
|
257
|
-
nodes: [{
|
|
258
|
-
type: "TEXT",
|
|
259
|
-
id: "",
|
|
260
|
-
nodes: [],
|
|
261
|
-
textData: {
|
|
262
|
-
text: part,
|
|
263
|
-
decorations: decorations
|
|
264
|
-
}
|
|
265
|
-
}]
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
// Add empty paragraph after each split part except the last
|
|
269
|
-
if (idx < brParts.length - 1) {
|
|
270
|
-
newNodes.push(createEmptyParagraph(`empty_br_${nodeIdCounter++}`));
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
// Add spacing after the split paragraphs if there's a next node
|
|
275
|
-
if (nextNode) {
|
|
276
|
-
newNodes.push(createEmptyParagraph(`empty_${nodeIdCounter++}`));
|
|
277
|
-
}
|
|
278
|
-
} else {
|
|
279
|
-
newNodes.push(currentNode);
|
|
280
|
-
|
|
281
|
-
// Add empty paragraph ONLY after paragraphs with   or after lists
|
|
282
|
-
if ((needsSpacingAfter(currentNode) || isListEnd(currentNode, nextNode)) && nextNode) {
|
|
283
|
-
newNodes.push(createEmptyParagraph(`empty_${nodeIdCounter++}`));
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return {
|
|
289
|
-
...richContent,
|
|
290
|
-
nodes: newNodes
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
156
|
|
|
294
157
|
function createEmptyParagraph(id) {
|
|
295
158
|
return {
|
|
@@ -314,6 +177,84 @@ function createEmptyParagraph(id) {
|
|
|
314
177
|
};
|
|
315
178
|
}
|
|
316
179
|
|
|
180
|
+
// Flattens LIST_ITEM nodes by removing nested PARAGRAPH wrappers
|
|
181
|
+
// Fixes Wix converter bug where bold text + regular text in <li> creates line breaks
|
|
182
|
+
function flattenListItems(richContent) {
|
|
183
|
+
if (!richContent || !richContent.nodes) return richContent;
|
|
184
|
+
|
|
185
|
+
const processNode = (node) => {
|
|
186
|
+
if (node.type === 'BULLETED_LIST' || node.type === 'ORDERED_LIST') {
|
|
187
|
+
return {
|
|
188
|
+
...node,
|
|
189
|
+
nodes: node.nodes.map(listItem => {
|
|
190
|
+
if (listItem.type !== 'LIST_ITEM') return listItem;
|
|
191
|
+
|
|
192
|
+
// Flatten: extract TEXT nodes from nested PARAGRAPHs
|
|
193
|
+
const flattenedChildren = [];
|
|
194
|
+
for (const child of listItem.nodes) {
|
|
195
|
+
if (child.type === 'PARAGRAPH' && child.nodes) {
|
|
196
|
+
// Pull TEXT nodes out of the PARAGRAPH
|
|
197
|
+
flattenedChildren.push(...child.nodes);
|
|
198
|
+
} else {
|
|
199
|
+
flattenedChildren.push(child);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return { ...listItem, nodes: flattenedChildren };
|
|
204
|
+
})
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return node;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
...richContent,
|
|
212
|
+
nodes: richContent.nodes.map(processNode)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Adds empty paragraph nodes between consecutive paragraphs and before lists
|
|
217
|
+
function addEmptyParagraphsBetweenConsecutive(html, richContent) {
|
|
218
|
+
if (!richContent || !richContent.nodes) return richContent;
|
|
219
|
+
const hasConsecutiveParagraphs = /<\/p>\s*<p/i.test(html);
|
|
220
|
+
const hasParagraphBeforeList = /<\/p>\s*<ul/i.test(html);
|
|
221
|
+
const hasParagraphAfterList = /<\/ul>\s*<p/i.test(html);
|
|
222
|
+
|
|
223
|
+
if (!hasConsecutiveParagraphs && !hasParagraphBeforeList && !hasParagraphAfterList) return richContent;
|
|
224
|
+
|
|
225
|
+
const nodes = richContent.nodes;
|
|
226
|
+
const newNodes = [];
|
|
227
|
+
let nodeIdCounter = 0;
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
230
|
+
const currentNode = nodes[i];
|
|
231
|
+
const nextNode = nodes[i + 1];
|
|
232
|
+
|
|
233
|
+
newNodes.push(currentNode);
|
|
234
|
+
|
|
235
|
+
if (currentNode.type === 'PARAGRAPH' && nextNode) {
|
|
236
|
+
// Add empty paragraph between consecutive paragraphs
|
|
237
|
+
if (hasConsecutiveParagraphs && nextNode.type === 'PARAGRAPH') {
|
|
238
|
+
newNodes.push(createEmptyParagraph(`empty_consecutive_${nodeIdCounter++}`));
|
|
239
|
+
}
|
|
240
|
+
// Add empty paragraph before list
|
|
241
|
+
if (hasParagraphBeforeList && nextNode.type === 'BULLETED_LIST') {
|
|
242
|
+
newNodes.push(createEmptyParagraph(`empty_before_list_${nodeIdCounter++}`));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Add empty paragraph after list
|
|
247
|
+
if (hasParagraphAfterList && currentNode.type === 'BULLETED_LIST' && nextNode && nextNode.type === 'PARAGRAPH') {
|
|
248
|
+
newNodes.push(createEmptyParagraph(`empty_after_list_${nodeIdCounter++}`));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
...richContent,
|
|
254
|
+
nodes: newNodes
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
317
258
|
|
|
318
259
|
|
|
319
260
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sr-npm",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.27",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"@wix/essentials": "^0.1.24",
|
|
23
23
|
"@wix/secrets": "1.0.53",
|
|
24
24
|
"@wix/site-location": "^1.0.0",
|
|
25
|
+
"@wix/site-seo": "^1.21.0",
|
|
25
26
|
"@wix/site-window": "^1.0.0",
|
|
26
27
|
"axios": "^1.11.0",
|
|
27
28
|
"jest": "^30.0.5",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { COLLECTIONS,CUSTOM_VALUES_COLLECTION_FIELDS,JOBS_COLLECTION_FIELDS } = require('../backend/collectionConsts');
|
|
2
|
-
const { CAREERS_PAGE_SELECTORS, GLOBAL_SECTIONS_SELECTORS } = require('../public/selectors');
|
|
2
|
+
const { CAREERS_PAGE_SELECTORS, GLOBAL_SECTIONS_SELECTORS, SEARCH_RESULTS_SELECTORS, MOBILE_FILTER_BOX_SELECTORS } = require('../public/selectors');
|
|
3
3
|
|
|
4
4
|
const { window } = require('@wix/site-window');
|
|
5
5
|
const { queryParams,onChange} = require('wix-location-frontend');
|
|
@@ -18,7 +18,8 @@ const { groupValuesByField,
|
|
|
18
18
|
getFieldByTitle,
|
|
19
19
|
getCorrectOption,
|
|
20
20
|
getOptionIndexFromCheckBox,
|
|
21
|
-
getAllDatasetItems
|
|
21
|
+
getAllDatasetItems,
|
|
22
|
+
handleSEOTitle
|
|
22
23
|
} = require('./pagesUtils');
|
|
23
24
|
const { handlePrimarySearch, queryPrimarySearchResults } = require('../public/primarySearchUtils');
|
|
24
25
|
|
|
@@ -30,6 +31,7 @@ const countsByFieldId = new Map(); // fieldId -> {valueId: count} map of counts
|
|
|
30
31
|
let allfields=[] // all fields in the database
|
|
31
32
|
let alljobs=[] // all jobs in the database
|
|
32
33
|
let allvaluesobjects=[] // all values in the database
|
|
34
|
+
let cities=[] // all cities in the database
|
|
33
35
|
let valueToJobs={} // valueId -> array of jobIds
|
|
34
36
|
let currentJobs=[] // current jobs that are displayed in the jobs repeater
|
|
35
37
|
let allsecondarySearchJobs=[] // secondary search results that are displayed in the jobs repeater
|
|
@@ -38,7 +40,6 @@ let secondarySearchIsFilled=false // whether the secondary search is filled with
|
|
|
38
40
|
let keywordAllJobs; // all jobs that are displayed in the jobs repeater when the keyword is filled
|
|
39
41
|
let ActivateURLOnchange=true; // whether to activate the url onchange
|
|
40
42
|
let considerAllJobs=false; // whether to consider all jobs or not
|
|
41
|
-
|
|
42
43
|
const pagination = {
|
|
43
44
|
pageSize: 10,
|
|
44
45
|
currentPage: 1,
|
|
@@ -61,32 +62,68 @@ async function careersMultiBoxesPageOnReady(_$w,urlParams) {
|
|
|
61
62
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CLEAR_ALL_BUTTON_ID).onClick(async () => {
|
|
62
63
|
await clearAll(_$w);
|
|
63
64
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
|
|
66
|
+
handleFilterButton(_$w);
|
|
67
|
+
|
|
68
|
+
setInterval(async () => {
|
|
69
|
+
const windowinfo=await window.getBoundingRect();
|
|
70
|
+
if(windowinfo.window.width>1000){
|
|
71
|
+
handleWindowResize(_$w,true);
|
|
72
|
+
}
|
|
73
|
+
else{
|
|
74
|
+
handleWindowResize(_$w);
|
|
75
|
+
}
|
|
76
|
+
}, 600);
|
|
77
|
+
|
|
67
78
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_MULTI_STATE_BOX).changeState("results");
|
|
68
79
|
}
|
|
69
80
|
|
|
81
|
+
async function handleWindowResize(_$w,desktop=false) {
|
|
82
|
+
if(desktop){
|
|
83
|
+
MOBILE_FILTER_BOX_SELECTORS.forEach(selector => {
|
|
84
|
+
_$w(selector).expand();
|
|
85
|
+
});
|
|
86
|
+
SEARCH_RESULTS_SELECTORS.forEach(selector => {
|
|
87
|
+
_$w(selector).expand();
|
|
88
|
+
});
|
|
89
|
+
_$w(CAREERS_PAGE_SELECTORS.FILTER_ICON).collapse();
|
|
90
|
+
_$w(CAREERS_PAGE_SELECTORS.EXIT_BUTTON).collapse();
|
|
91
|
+
_$w(CAREERS_PAGE_SELECTORS.REFINE_SEARCH_BUTTON).collapse();
|
|
92
|
+
}
|
|
93
|
+
else{
|
|
94
|
+
if(_$w(CAREERS_PAGE_SELECTORS.FILTER_ICON).collapsed && _$w(CAREERS_PAGE_SELECTORS.EXIT_BUTTON).collapsed && _$w(CAREERS_PAGE_SELECTORS.REFINE_SEARCH_BUTTON).collapsed){
|
|
95
|
+
_$w(CAREERS_PAGE_SELECTORS.FILTER_ICON).expand();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
70
100
|
async function handleBackAndForth(_$w){
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
ActivateURLOnchange=true;
|
|
101
|
+
if(ActivateURLOnchange) {
|
|
102
|
+
await clearAll(_$w);
|
|
103
|
+
}
|
|
104
|
+
else{
|
|
105
|
+
ActivateURLOnchange=true;
|
|
106
|
+
}
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
108
|
+
// if(ActivateURLOnchange) {
|
|
109
|
+
// const newQueryParams=await location.query();
|
|
110
|
+
// console.log("newQueryParams: ", newQueryParams);
|
|
111
|
+
// ActivateURLOnchange=false;
|
|
112
|
+
// await clearAll(_$w,true);
|
|
113
|
+
// await handleUrlParams(_$w,newQueryParams,true);
|
|
114
|
+
// ActivateURLOnchange=true;
|
|
115
|
+
|
|
116
|
+
// }
|
|
117
|
+
// else{
|
|
118
|
+
// ActivateURLOnchange=true;
|
|
119
|
+
// }
|
|
83
120
|
}
|
|
84
121
|
|
|
85
122
|
async function clearAll(_$w,urlOnChange=false) {
|
|
86
|
-
if(selectedByField.size>0 || _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.SECONDARY_SEARCH_INPUT).value || _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value) {
|
|
87
123
|
|
|
88
124
|
for(const field of allfields) {
|
|
89
125
|
_$w(`#${FiltersIds[field.title]}CheckBox`).selectedIndices = [];
|
|
126
|
+
_$w(`#${FiltersIds[field.title]}input`).value='';
|
|
90
127
|
}
|
|
91
128
|
selectedByField.clear();
|
|
92
129
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.SECONDARY_SEARCH_INPUT).value='';
|
|
@@ -102,41 +139,26 @@ async function clearAll(_$w,urlOnChange=false) {
|
|
|
102
139
|
await updateJobsAndNumbersAndFilters(_$w,true);
|
|
103
140
|
}
|
|
104
141
|
|
|
105
|
-
}
|
|
106
142
|
}
|
|
107
143
|
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
CAREERS_PAGE_SELECTORS.PAGINATION_BTN,
|
|
112
|
-
CAREERS_PAGE_SELECTORS.HEAD_BTNS,
|
|
113
|
-
CAREERS_PAGE_SELECTORS.SELECTED_VALUES_REPEATER,
|
|
114
|
-
CAREERS_PAGE_SELECTORS.BUTTOM_TXT,
|
|
115
|
-
CAREERS_PAGE_SELECTORS.SECTION_24,
|
|
116
|
-
CAREERS_PAGE_SELECTORS.SECTION_3,
|
|
117
|
-
CAREERS_PAGE_SELECTORS.LINE_3,
|
|
118
|
-
CAREERS_PAGE_SELECTORS.FILTER_ICON];
|
|
119
|
-
|
|
120
|
-
const mobileFilterBoxSelectors = [
|
|
121
|
-
CAREERS_PAGE_SELECTORS.FILTER_BOX,
|
|
122
|
-
CAREERS_PAGE_SELECTORS.REFINE_SEARCH_BUTTON,
|
|
123
|
-
CAREERS_PAGE_SELECTORS.EXIT_BUTTON,
|
|
124
|
-
];
|
|
144
|
+
async function handleFilterButton(_$w) {
|
|
145
|
+
|
|
146
|
+
|
|
125
147
|
|
|
126
148
|
_$w(CAREERS_PAGE_SELECTORS.FILTER_ICON).onClick(()=>{
|
|
127
|
-
|
|
149
|
+
MOBILE_FILTER_BOX_SELECTORS.forEach(selector => {
|
|
128
150
|
_$w(selector).expand();
|
|
129
151
|
});
|
|
130
|
-
|
|
152
|
+
SEARCH_RESULTS_SELECTORS.forEach(selector => {
|
|
131
153
|
_$w(selector).collapse();
|
|
132
154
|
});
|
|
133
155
|
});
|
|
134
156
|
|
|
135
157
|
const exitFilterBox = () => {
|
|
136
|
-
|
|
158
|
+
MOBILE_FILTER_BOX_SELECTORS.forEach(selector => {
|
|
137
159
|
_$w(selector).collapse();
|
|
138
160
|
});
|
|
139
|
-
|
|
161
|
+
SEARCH_RESULTS_SELECTORS.forEach(selector => {
|
|
140
162
|
_$w(selector).expand();
|
|
141
163
|
});
|
|
142
164
|
}
|
|
@@ -150,11 +172,15 @@ function handleFilterInMobile(_$w) {
|
|
|
150
172
|
});
|
|
151
173
|
|
|
152
174
|
//onmobile we should collapse the filter box and the refine search button by default
|
|
153
|
-
|
|
175
|
+
const formFactor = await window.formFactor();
|
|
176
|
+
if(formFactor === "Mobile" || formFactor === "Tablet") {
|
|
177
|
+
MOBILE_FILTER_BOX_SELECTORS.forEach(selector => {
|
|
154
178
|
_$w(selector).collapse();
|
|
155
179
|
});
|
|
156
180
|
}
|
|
157
181
|
|
|
182
|
+
}
|
|
183
|
+
|
|
158
184
|
|
|
159
185
|
async function handleUrlParams(_$w,urlParams,handleBackAndForth=false) {
|
|
160
186
|
try {
|
|
@@ -169,6 +195,7 @@ async function handleUrlParams(_$w,urlParams,handleBackAndForth=false) {
|
|
|
169
195
|
|
|
170
196
|
currentJobs = items;
|
|
171
197
|
keywordAllJobs = items;
|
|
198
|
+
await handleSEOTitle(`${decodeURIComponent(urlParams.keyword)} Search Results | The Warehouse Group`);
|
|
172
199
|
}
|
|
173
200
|
|
|
174
201
|
for (const url of possibleUrlParams)
|
|
@@ -364,7 +391,7 @@ async function loadJobsRepeater(_$w) {
|
|
|
364
391
|
async function loadFilters(_$w) {
|
|
365
392
|
try {
|
|
366
393
|
// 1) Load all categories (fields)
|
|
367
|
-
|
|
394
|
+
cities = await getAllRecords(COLLECTIONS.CITIES);
|
|
368
395
|
for(const city of cities) {
|
|
369
396
|
valueToJobs[city._id] = city.jobIds;
|
|
370
397
|
}
|
|
@@ -400,6 +427,7 @@ async function loadJobsRepeater(_$w) {
|
|
|
400
427
|
|
|
401
428
|
_$w(`#${FiltersIds[field.title]}CheckBox`).selectedIndices = []; // start empty
|
|
402
429
|
_$w(`#${FiltersIds[field.title]}CheckBox`).onChange(async (ev) => {
|
|
430
|
+
|
|
403
431
|
dontUpdateThisCheckBox=field._id;
|
|
404
432
|
const selected = ev.target.value; // array of selected value IDs
|
|
405
433
|
let fieldTitle=field.title.toLowerCase().replace(' ', '');
|
|
@@ -480,8 +508,13 @@ function getValueFromValueId(valueIds, value) {
|
|
|
480
508
|
{
|
|
481
509
|
const selectedFieldId=Array.from( selectedByField.keys() )[0]
|
|
482
510
|
if(selectedFieldId===fieldId) {
|
|
511
|
+
if(selectedFieldId==="Location") {
|
|
512
|
+
countsMap = new Map(cities.map(city=>[city._id, city.count]));
|
|
513
|
+
}
|
|
514
|
+
else{
|
|
483
515
|
const relevantFields=allvaluesobjects.filter(val=>val.customField===selectedFieldId)
|
|
484
516
|
countsMap = new Map(relevantFields.map(val=>[val.valueId, val.count]));
|
|
517
|
+
}
|
|
485
518
|
considerAllJobs=false;
|
|
486
519
|
}
|
|
487
520
|
}
|
|
@@ -518,11 +551,7 @@ function getValueFromValueId(valueIds, value) {
|
|
|
518
551
|
|
|
519
552
|
// Sort alphabetically by label
|
|
520
553
|
filtered.sort((a, b) => (a.label || '').localeCompare(b.label || ''));
|
|
521
|
-
// Preserve currently selected values that are still visible
|
|
522
|
-
// let prevSelected=[]
|
|
523
|
-
// clearAll? prevSelected=[]:prevSelected= _$w(`#${FiltersIds[fieldTitle]}CheckBox`).value;
|
|
524
554
|
const visibleSet = new Set(filtered.map(o => o.value));
|
|
525
|
-
//const preserved = prevSelected.filter(v => visibleSet.has(v));
|
|
526
555
|
if(filtered.length===0) {
|
|
527
556
|
_$w(`#${FiltersIds[fieldTitle]}MultiBox`).changeState(`${FiltersIds[fieldTitle]}NoResults`);
|
|
528
557
|
}
|
|
@@ -591,11 +620,14 @@ function getValueFromValueId(valueIds, value) {
|
|
|
591
620
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.paginationTotalCountText).text = secondarySearchIsFilled? Math.ceil(currentSecondarySearchJobs.length/pagination.pageSize).toString():Math.ceil(currentJobs.length/pagination.pageSize).toString();
|
|
592
621
|
if(jobsFirstPage.length===0) {
|
|
593
622
|
await _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_MULTI_STATE_BOX).changeState("noJobs");
|
|
623
|
+
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.paginationCurrentText).text = "0";
|
|
624
|
+
pagination.currentPage=0;
|
|
594
625
|
}
|
|
595
626
|
else{
|
|
596
627
|
await _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_MULTI_STATE_BOX).changeState("searchResult");
|
|
628
|
+
pagination.currentPage=1;
|
|
597
629
|
}
|
|
598
|
-
|
|
630
|
+
|
|
599
631
|
handlePaginationButtons(_$w);
|
|
600
632
|
}
|
|
601
633
|
|
|
@@ -603,7 +635,7 @@ function handlePaginationButtons(_$w)
|
|
|
603
635
|
{
|
|
604
636
|
handlePageUrlParam();
|
|
605
637
|
|
|
606
|
-
pagination.currentPage===1? _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PAGE_BUTTON_PREVIOUS).disable():_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PAGE_BUTTON_PREVIOUS).enable();
|
|
638
|
+
pagination.currentPage===1 || pagination.currentPage===0? _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PAGE_BUTTON_PREVIOUS).disable():_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PAGE_BUTTON_PREVIOUS).enable();
|
|
607
639
|
if(secondarySearchIsFilled) {
|
|
608
640
|
if(currentSecondarySearchJobs.length===0) {
|
|
609
641
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PAGE_BUTTON_NEXT).disable();
|
|
@@ -622,9 +654,8 @@ function handlePaginationButtons(_$w)
|
|
|
622
654
|
|
|
623
655
|
function handlePageUrlParam() {
|
|
624
656
|
ActivateURLOnchange=false;
|
|
625
|
-
if(pagination.currentPage==1)
|
|
657
|
+
if(pagination.currentPage==1 || pagination.currentPage==0)
|
|
626
658
|
{
|
|
627
|
-
|
|
628
659
|
queryParams.remove(["page"]);
|
|
629
660
|
}
|
|
630
661
|
else{
|
|
@@ -704,6 +735,8 @@ async function secondarySearch(_$w,query) {
|
|
|
704
735
|
|
|
705
736
|
if(jobsFirstPage.length===0) {
|
|
706
737
|
await _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_MULTI_STATE_BOX).changeState("noJobs");
|
|
738
|
+
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.paginationCurrentText).text = "0";
|
|
739
|
+
pagination.currentPage=0;
|
|
707
740
|
}
|
|
708
741
|
else{
|
|
709
742
|
await _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_MULTI_STATE_BOX).changeState("searchResult");
|
|
@@ -730,6 +763,7 @@ async function secondarySearch(_$w,query) {
|
|
|
730
763
|
}
|
|
731
764
|
|
|
732
765
|
|
|
766
|
+
|
|
733
767
|
module.exports = {
|
|
734
768
|
careersMultiBoxesPageOnReady,
|
|
735
769
|
secondarySearch
|
package/pages/pagesUtils.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { items: wixData } = require('@wix/data');
|
|
2
2
|
const { JOBS_COLLECTION_FIELDS,COLLECTIONS } = require('../backend/collectionConsts');
|
|
3
3
|
const { normalizeString } = require('../backend/utils');
|
|
4
|
-
|
|
4
|
+
const { seo } = require('@wix/site-seo');
|
|
5
5
|
function groupValuesByField(values, refKey) {
|
|
6
6
|
const map = new Map();
|
|
7
7
|
for (const v of values) {
|
|
@@ -106,6 +106,11 @@ async function getLatestJobsByValue(Value) {
|
|
|
106
106
|
return latestJobs;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
async function handleSEOTitle(title) {
|
|
110
|
+
await seo.setTitle(title);
|
|
111
|
+
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
module.exports = {
|
|
110
115
|
groupValuesByField,
|
|
111
116
|
debounce,
|
|
@@ -117,5 +122,6 @@ module.exports = {
|
|
|
117
122
|
getLatestJobsByValue,
|
|
118
123
|
getValueFromValueId,
|
|
119
124
|
getAllRecordsWithoutMultiRef,
|
|
120
|
-
getAllDatasetItems
|
|
125
|
+
getAllDatasetItems,
|
|
126
|
+
handleSEOTitle
|
|
121
127
|
}
|
package/public/selectors.js
CHANGED
|
@@ -50,8 +50,27 @@ const FILTER_FIELDS = {
|
|
|
50
50
|
SEARCH: 'title',
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
|
|
54
|
+
const SEARCH_RESULTS_SELECTORS = [
|
|
55
|
+
CAREERS_PAGE_SELECTORS.RESULT_BOX,
|
|
56
|
+
CAREERS_PAGE_SELECTORS.PAGINATION_BTN,
|
|
57
|
+
CAREERS_PAGE_SELECTORS.HEAD_BTNS,
|
|
58
|
+
CAREERS_PAGE_SELECTORS.SELECTED_VALUES_REPEATER,
|
|
59
|
+
CAREERS_PAGE_SELECTORS.BUTTOM_TXT,
|
|
60
|
+
CAREERS_PAGE_SELECTORS.SECTION_24,
|
|
61
|
+
CAREERS_PAGE_SELECTORS.SECTION_3,
|
|
62
|
+
CAREERS_PAGE_SELECTORS.LINE_3,
|
|
63
|
+
CAREERS_PAGE_SELECTORS.FILTER_ICON];
|
|
64
|
+
|
|
65
|
+
const MOBILE_FILTER_BOX_SELECTORS = [
|
|
66
|
+
CAREERS_PAGE_SELECTORS.FILTER_BOX,
|
|
67
|
+
CAREERS_PAGE_SELECTORS.REFINE_SEARCH_BUTTON,
|
|
68
|
+
CAREERS_PAGE_SELECTORS.EXIT_BUTTON,
|
|
69
|
+
];
|
|
53
70
|
module.exports = {
|
|
54
71
|
CAREERS_PAGE_SELECTORS,
|
|
55
72
|
GLOBAL_SECTIONS_SELECTORS,
|
|
56
73
|
FILTER_FIELDS,
|
|
74
|
+
SEARCH_RESULTS_SELECTORS,
|
|
75
|
+
MOBILE_FILTER_BOX_SELECTORS,
|
|
57
76
|
}
|