sr-npm 1.2.40 → 1.2.41
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/collectionConsts.js +10 -1
- package/backend/data.js +72 -54
- package/backend/queries.js +1 -1
- package/backend/secretsData.js +8 -3
- package/package.json +1 -1
- package/pages/careersMultiBoxesPage.js +69 -46
- package/pages/homePage.js +5 -3
- package/pages/pagesUtils.js +22 -9
- package/pages/positionPage.js +1 -4
- package/pages/supportTeamsPage.js +6 -6
|
@@ -11,6 +11,7 @@ const COLLECTIONS = {
|
|
|
11
11
|
SUPPORT_TEAMS: 'SupportTeams',
|
|
12
12
|
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
const JOBS_COLLECTION_FIELDS = {
|
|
15
16
|
LOCATION: 'location',
|
|
16
17
|
TITLE: 'title',
|
|
@@ -34,25 +35,31 @@ const JOBS_COLLECTION_FIELDS = {
|
|
|
34
35
|
RELEASED_DATE: 'releasedDate',
|
|
35
36
|
REF_ID: 'refId',
|
|
36
37
|
}
|
|
38
|
+
|
|
37
39
|
const AMOUNT_OF_JOBS_PER_DEPARTMENT_COLLECTION_FIELDS = {
|
|
38
40
|
TITLE: 'title',
|
|
39
41
|
COUNT: 'count',
|
|
40
42
|
IMAGE: 'image',
|
|
41
43
|
}
|
|
44
|
+
|
|
42
45
|
const CUSTOM_VALUES_COLLECTION_FIELDS = {
|
|
46
|
+
VALUE_ID: 'valueId',
|
|
43
47
|
TITLE: 'title',
|
|
44
48
|
CUSTOM_FIELD: 'customField',
|
|
45
49
|
MULTI_REF_JOBS_CUSTOM_VALUES: 'multiRefJobsCustomValues',
|
|
46
50
|
count: 'count',
|
|
47
51
|
JOB_IDS: 'jobIds',
|
|
48
52
|
}
|
|
53
|
+
|
|
49
54
|
const CUSTOM_FIELDS_COLLECTION_FIELDS = {
|
|
50
55
|
TITLE: 'title',
|
|
51
56
|
}
|
|
57
|
+
|
|
52
58
|
const BRANDS_COLLECTION_FIELDS = {
|
|
53
59
|
TITLE: 'title',
|
|
54
60
|
COUNT: 'count',
|
|
55
61
|
}
|
|
62
|
+
|
|
56
63
|
const CITIES_COLLECTION_FIELDS = {
|
|
57
64
|
TITLE: 'title',
|
|
58
65
|
CITY: 'city',
|
|
@@ -61,6 +68,7 @@ const CITIES_COLLECTION_FIELDS = {
|
|
|
61
68
|
COUNTRY: 'country',
|
|
62
69
|
JOB_IDS: 'jobIds',
|
|
63
70
|
}
|
|
71
|
+
|
|
64
72
|
const COLLECTIONS_FIELDS = {
|
|
65
73
|
AMOUNT_OF_JOBS_PER_DEPARTMENT: [
|
|
66
74
|
{key:'title', type: 'TEXT'},
|
|
@@ -85,7 +93,7 @@ const COLLECTIONS_FIELDS = {
|
|
|
85
93
|
{key:'language', type: 'TEXT'},
|
|
86
94
|
{key:'remote', type: 'BOOLEAN'},
|
|
87
95
|
{key:'jobDescription', type: 'OBJECT'},
|
|
88
|
-
{key:'multiRefJobsCustomValues', type: 'MULTI_REFERENCE', typeMetadata: { multiReference: { referencedCollectionId: COLLECTIONS.CUSTOM_VALUES,referencingFieldKey:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,referencingDisplayName:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES } } },
|
|
96
|
+
{key:'multiRefJobsCustomValues', type: 'MULTI_REFERENCE', typeMetadata: { multiReference: { referencedCollectionId: COLLECTIONS.CUSTOM_VALUES, referencingFieldKey:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,referencingDisplayName:JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES } } },
|
|
89
97
|
{key:'cityText', type: 'TEXT'},
|
|
90
98
|
{key:'applyLink', type: 'URL'},
|
|
91
99
|
{key:'referFriendLink', type: 'URL'},
|
|
@@ -114,6 +122,7 @@ const COLLECTIONS_FIELDS = {
|
|
|
114
122
|
{ key: 'count', type: 'NUMBER' },
|
|
115
123
|
],
|
|
116
124
|
CUSTOM_VALUES: [
|
|
125
|
+
{key:'valueId', type: 'TEXT'},
|
|
117
126
|
{key:'title', type: 'TEXT'},
|
|
118
127
|
{key:'customField', type: 'REFERENCE', typeMetadata: { reference: { referencedCollectionId: COLLECTIONS.CUSTOM_FIELDS } } },
|
|
119
128
|
{key:'count', type: 'NUMBER'},
|
package/backend/data.js
CHANGED
|
@@ -40,7 +40,6 @@ function validatePosition(position) {
|
|
|
40
40
|
if (!position.location || !position.location.city || typeof position.location.remote !== 'boolean') {
|
|
41
41
|
throw new Error('Position location is required and must have a city and remote');
|
|
42
42
|
}
|
|
43
|
-
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
async function filterBasedOnBrand(positions) {
|
|
@@ -93,78 +92,83 @@ function getEmploymentType(position,customFieldsValues) {
|
|
|
93
92
|
customValuesToJobs[position.typeOfEmployment.id] ? customValuesToJobs[position.typeOfEmployment.id].add(position.id) : customValuesToJobs[position.typeOfEmployment.id]=new Set([position.id])
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
function getCustomFieldsAndValuesFromPosition(position,customFieldsLabels,customFieldsValues) {
|
|
95
|
+
function getCustomFieldsAndValuesFromPosition(position, customFieldsLabels, customFieldsValues) {
|
|
97
96
|
const customFieldsArray = Array.isArray(position?.customField) ? position.customField : [];
|
|
97
|
+
|
|
98
98
|
for (const field of customFieldsArray) {
|
|
99
99
|
if(EXCLUDED_CUSTOM_FIELDS.has(field.fieldLabel)) continue; //country and department are not custom fields, they are already in the job object
|
|
100
|
-
|
|
100
|
+
|
|
101
|
+
const fieldId = normalizeString(field.fieldId)
|
|
101
102
|
const fieldLabel = field.fieldLabel;
|
|
102
|
-
const valueId=normalizeString(field.valueId)
|
|
103
|
+
const valueId = normalizeString(field.valueId)
|
|
103
104
|
const valueLabel = field.valueLabel
|
|
104
105
|
customFieldsLabels[fieldId] = fieldLabel
|
|
106
|
+
|
|
105
107
|
// Build nested dictionary: fieldId -> { valueId: valueLabel }
|
|
106
108
|
if (!customFieldsValues[fieldId]) {
|
|
107
109
|
customFieldsValues[fieldId] = {};
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
customFieldsValues[fieldId][valueId] = valueLabel;
|
|
111
|
-
customValuesToJobs[valueId] ? customValuesToJobs[valueId].add(position.id) : customValuesToJobs[valueId]=new Set([position.id])
|
|
113
|
+
customValuesToJobs[valueId] ? customValuesToJobs[valueId].add(position.id) : customValuesToJobs[valueId] = new Set([position.id])
|
|
112
114
|
}
|
|
113
115
|
}
|
|
116
|
+
|
|
114
117
|
async function saveJobsDataToCMS() {
|
|
115
118
|
const positions = await fetchPositionsFromSRAPI();
|
|
116
119
|
const sourcePositions = await filterBasedOnBrand(positions);
|
|
117
120
|
const customFieldsLabels = {}
|
|
118
121
|
const customFieldsValues = {}
|
|
119
122
|
|
|
120
|
-
const {
|
|
123
|
+
const { templateType } = await getApiKeys();
|
|
121
124
|
if(siteconfig===undefined) {
|
|
122
125
|
await getSiteConfig();
|
|
123
126
|
}
|
|
124
127
|
// bulk insert to jobs collection without descriptions first
|
|
125
128
|
const jobsData = sourcePositions.map(position => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
129
|
+
const basicJob = {
|
|
130
|
+
_id: position.id,
|
|
131
|
+
title: position.name || '',
|
|
132
|
+
slug: generateSlug(position.name || ''),
|
|
133
|
+
department: position.department?.label || 'Other',
|
|
134
|
+
cityText: normalizeString(position.location?.city),
|
|
135
|
+
location: position.location && Object.keys(position.location).length > 0
|
|
136
|
+
? position.location
|
|
137
|
+
: {
|
|
138
|
+
countryCode: "",
|
|
139
|
+
country: "",
|
|
140
|
+
city: "",
|
|
141
|
+
postalCode: "",
|
|
142
|
+
address: "",
|
|
143
|
+
manual: false,
|
|
144
|
+
remote: false,
|
|
145
|
+
regionCode: ""
|
|
146
|
+
},
|
|
147
|
+
country: position.location?.country || '',
|
|
148
|
+
remote: position.location?.remote || false,
|
|
149
|
+
language: position.language?.label || '',
|
|
150
|
+
brand: siteconfig.disableMultiBrand==="false" ? getBrand(position.customField) : '',
|
|
151
|
+
jobDescription: null, // Will be filled later
|
|
152
|
+
employmentType: position.typeOfEmployment.label,
|
|
153
|
+
releasedDate: position.releasedDate,
|
|
154
|
+
refId: position.refNumber
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
getCustomFieldsAndValuesFromPosition(position, customFieldsLabels, customFieldsValues);
|
|
158
|
+
getEmploymentType(position, customFieldsValues);
|
|
159
|
+
getLocation(position,basicJob);
|
|
160
|
+
|
|
161
|
+
if(templateType === TEMPLATE_TYPE.INTERNAL){
|
|
162
|
+
getVisibility(position,customFieldsValues);
|
|
163
|
+
}
|
|
164
|
+
return basicJob;
|
|
162
165
|
});
|
|
163
166
|
|
|
164
167
|
if (siteconfig.customFields==="true") {
|
|
165
|
-
|
|
166
|
-
|
|
168
|
+
await populateCustomFieldsCollection(customFieldsLabels,templateType);
|
|
169
|
+
await populateCustomValuesCollection(customFieldsValues);
|
|
167
170
|
}
|
|
171
|
+
|
|
168
172
|
// Sort jobs by title (ascending, case-insensitive, numeric-aware)
|
|
169
173
|
jobsData.sort((a, b) => {
|
|
170
174
|
const titleA = a.title || '';
|
|
@@ -202,8 +206,8 @@ async function saveJobsDataToCMS() {
|
|
|
202
206
|
console.log(`✓ All chunks processed. Total jobs saved: ${totalSaved}/${jobsData.length}`);
|
|
203
207
|
}
|
|
204
208
|
|
|
205
|
-
async function insertJobsReference(valueId) {
|
|
206
|
-
await wixData.insertReference(COLLECTIONS.CUSTOM_VALUES, CUSTOM_VALUES_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,
|
|
209
|
+
async function insertJobsReference(id, valueId) {
|
|
210
|
+
await wixData.insertReference(COLLECTIONS.CUSTOM_VALUES, CUSTOM_VALUES_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES, id, Array.from(customValuesToJobs[valueId]));
|
|
207
211
|
}
|
|
208
212
|
|
|
209
213
|
async function populateCustomFieldsCollection(customFields,templateType) {
|
|
@@ -222,33 +226,38 @@ async function populateCustomFieldsCollection(customFields,templateType) {
|
|
|
222
226
|
}
|
|
223
227
|
async function populateCustomValuesCollection(customFieldsValues) {
|
|
224
228
|
let valuesToinsert=[]
|
|
229
|
+
|
|
225
230
|
for (const fieldId of Object.keys(customFieldsValues)) {
|
|
226
231
|
const valuesMap = customFieldsValues[fieldId] || {};
|
|
232
|
+
|
|
227
233
|
for (const valueId of Object.keys(valuesMap)) {
|
|
228
234
|
valuesToinsert.push({
|
|
229
|
-
|
|
235
|
+
valueId,
|
|
230
236
|
title: valuesMap[valueId],
|
|
231
237
|
customField: fieldId,
|
|
232
|
-
count:customValuesToJobs[valueId].size,
|
|
233
|
-
jobIds:Array.from(customValuesToJobs[valueId]),
|
|
238
|
+
count: customValuesToJobs[valueId].size,
|
|
239
|
+
jobIds: Array.from(customValuesToJobs[valueId]),
|
|
234
240
|
})
|
|
235
241
|
}
|
|
236
|
-
|
|
237
242
|
}
|
|
238
243
|
await wixData.bulkSave(COLLECTIONS.CUSTOM_VALUES, valuesToinsert);
|
|
239
244
|
}
|
|
245
|
+
|
|
240
246
|
async function saveJobsDescriptionsAndLocationApplyUrlReferencesToCMS() {
|
|
241
247
|
console.log('🚀 Starting job descriptions update process for ALL jobs');
|
|
242
248
|
|
|
243
249
|
try {
|
|
244
250
|
let jobsWithNoDescriptions = await getJobsWithNoDescriptions();
|
|
251
|
+
|
|
245
252
|
if (siteconfig.customFields==="true") {
|
|
246
|
-
let customValues=await getAllCustomValues();
|
|
253
|
+
let customValues = await getAllCustomValues();
|
|
254
|
+
|
|
247
255
|
console.log("inserting jobs references to custom values collection");
|
|
248
256
|
console.log("customValues: ",customValues)
|
|
249
257
|
console.log("customValues.items: ",customValues.items)
|
|
258
|
+
|
|
250
259
|
for (const value of customValues.items) {
|
|
251
|
-
await insertJobsReference(value._id);
|
|
260
|
+
await insertJobsReference(value._id, value.valueId);
|
|
252
261
|
}
|
|
253
262
|
console.log("inserted jobs references to custom values collection successfully");
|
|
254
263
|
}
|
|
@@ -360,10 +369,12 @@ async function aggregateJobsByFieldToCMS({ field, collection }) {
|
|
|
360
369
|
return { success: false, error: err.message };
|
|
361
370
|
}
|
|
362
371
|
}
|
|
372
|
+
|
|
363
373
|
async function getAllCustomValues() {
|
|
364
374
|
let customValuesQuery = await wixData.query(COLLECTIONS.CUSTOM_VALUES).limit(1000).find();
|
|
365
375
|
return customValuesQuery;
|
|
366
376
|
}
|
|
377
|
+
|
|
367
378
|
async function getJobsWithNoDescriptions() {
|
|
368
379
|
let jobswithoutdescriptionsQuery = await wixData
|
|
369
380
|
.query(COLLECTIONS.JOBS)
|
|
@@ -489,6 +500,7 @@ async function referenceJobs() {
|
|
|
489
500
|
}
|
|
490
501
|
|
|
491
502
|
async function syncJobsFast() {
|
|
503
|
+
try{
|
|
492
504
|
console.log("Syncing jobs fast");
|
|
493
505
|
await createCollections();
|
|
494
506
|
await clearCollections();
|
|
@@ -505,6 +517,12 @@ async function syncJobsFast() {
|
|
|
505
517
|
await aggregateJobs();
|
|
506
518
|
await referenceJobs();
|
|
507
519
|
console.log("syncing jobs fast finished successfully");
|
|
520
|
+
}
|
|
521
|
+
catch (error) {
|
|
522
|
+
error.message="Error syncing jobs: "+error.message;
|
|
523
|
+
throw error;
|
|
524
|
+
}
|
|
525
|
+
|
|
508
526
|
}
|
|
509
527
|
|
|
510
528
|
|
|
@@ -522,7 +540,7 @@ async function clearCollections() {
|
|
|
522
540
|
}
|
|
523
541
|
|
|
524
542
|
async function markTemplateAsExternal() {
|
|
525
|
-
await createCollectionIfMissing(COLLECTIONS.TEMPLATE_TYPE, COLLECTIONS_FIELDS.TEMPLATE_TYPE,null,'singleItem');
|
|
543
|
+
await createCollectionIfMissing(COLLECTIONS.TEMPLATE_TYPE, COLLECTIONS_FIELDS.TEMPLATE_TYPE, null, 'singleItem');
|
|
526
544
|
const tempalte = await wixData.save(COLLECTIONS.TEMPLATE_TYPE, {
|
|
527
545
|
templateType: TEMPLATE_TYPE.EXTERNAL
|
|
528
546
|
});
|
|
@@ -530,7 +548,7 @@ async function markTemplateAsExternal() {
|
|
|
530
548
|
}
|
|
531
549
|
|
|
532
550
|
async function markTemplateAsInternal() {
|
|
533
|
-
await createCollectionIfMissing(COLLECTIONS.TEMPLATE_TYPE, COLLECTIONS_FIELDS.TEMPLATE_TYPE,null,'singleItem');
|
|
551
|
+
await createCollectionIfMissing(COLLECTIONS.TEMPLATE_TYPE, COLLECTIONS_FIELDS.TEMPLATE_TYPE, null, 'singleItem');
|
|
534
552
|
const tempalte = await wixData.save(COLLECTIONS.TEMPLATE_TYPE, {
|
|
535
553
|
templateType: TEMPLATE_TYPE.INTERNAL
|
|
536
554
|
});
|
package/backend/queries.js
CHANGED
|
@@ -21,7 +21,7 @@ async function getPositionsByField(field, value) {
|
|
|
21
21
|
async function getPositionWithMultiRefField(jobId)
|
|
22
22
|
{
|
|
23
23
|
return wixData
|
|
24
|
-
.queryReferenced(COLLECTIONS.JOBS,jobId,JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES)
|
|
24
|
+
.queryReferenced(COLLECTIONS.JOBS, jobId,JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES)
|
|
25
25
|
.then(result => result.items);
|
|
26
26
|
}
|
|
27
27
|
|
package/backend/secretsData.js
CHANGED
|
@@ -37,9 +37,14 @@ const elevatedQuery = auth.elevate(wixData.query);
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
async function getApiKeys() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
try{
|
|
41
|
+
const companyId = await getTokenFromCMS(TOKEN_NAME.COMPANY_ID);
|
|
42
|
+
const templateType = await getTemplateTypeFromCMS();
|
|
43
|
+
return {companyId,templateType};
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error("Error getting api keys: ", error);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
module.exports = {
|
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ let allsecondarySearchJobs=[] // secondary search results that are displayed in
|
|
|
21
21
|
let currentSecondarySearchJobs=[] // current secondary search results that are displayed in the jobs repeater
|
|
22
22
|
let secondarySearchIsFilled=false // whether the secondary search is filled with results
|
|
23
23
|
let keywordAllJobs; // all jobs that are displayed in the jobs repeater when the keyword is filled
|
|
24
|
+
let ActivateURLOnchange=true; // whether to activate the url onchange
|
|
24
25
|
const pagination = {
|
|
25
26
|
pageSize: 10,
|
|
26
27
|
currentPage: 1,
|
|
@@ -33,7 +34,7 @@ async function careersMultiBoxesPageOnReady(_$w,urlParams) {
|
|
|
33
34
|
});
|
|
34
35
|
|
|
35
36
|
await loadData(_$w);
|
|
36
|
-
loadJobsRepeater(_$w);
|
|
37
|
+
await loadJobsRepeater(_$w); // if we remove the await here the job list will be flaky , it doesn't fill it properly
|
|
37
38
|
loadPrimarySearchRepeater(_$w);
|
|
38
39
|
await loadFilters(_$w);
|
|
39
40
|
loadSelectedValuesRepeater(_$w);
|
|
@@ -52,15 +53,23 @@ async function careersMultiBoxesPageOnReady(_$w,urlParams) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
async function handleBackAndForth(_$w){
|
|
56
|
+
if(ActivateURLOnchange) {
|
|
55
57
|
const newQueryParams=await location.query();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
console.log("newQueryParams: ", newQueryParams);
|
|
59
|
+
ActivateURLOnchange=false;
|
|
60
|
+
await clearAll(_$w,true);
|
|
61
|
+
await handleUrlParams(_$w,newQueryParams,true);
|
|
62
|
+
ActivateURLOnchange=true;
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
else{
|
|
66
|
+
ActivateURLOnchange=true;
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
async function clearAll(_$w,urlOnChange=false) {
|
|
63
71
|
if(selectedByField.size>0 || _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.SECONDARY_SEARCH_INPUT).value || _$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value) {
|
|
72
|
+
|
|
64
73
|
for(const field of allfields) {
|
|
65
74
|
_$w(`#${FiltersIds[field.title]}CheckBox`).selectedIndices = [];
|
|
66
75
|
}
|
|
@@ -71,9 +80,13 @@ async function clearAll(_$w,urlOnChange=false) {
|
|
|
71
80
|
currentJobs=alljobs;
|
|
72
81
|
keywordAllJobs=undefined;
|
|
73
82
|
if(!urlOnChange) {
|
|
83
|
+
console.log("inside clearAll removing url params");
|
|
84
|
+
ActivateURLOnchange=false;
|
|
74
85
|
queryParams.remove(possibleUrlParams.concat(["keyword", "page"]));
|
|
86
|
+
|
|
87
|
+
await updateJobsAndNumbersAndFilters(_$w,true);
|
|
75
88
|
}
|
|
76
|
-
|
|
89
|
+
|
|
77
90
|
}
|
|
78
91
|
}
|
|
79
92
|
|
|
@@ -112,7 +125,8 @@ function handleFilterInMobile(_$w) {
|
|
|
112
125
|
});
|
|
113
126
|
}
|
|
114
127
|
|
|
115
|
-
|
|
128
|
+
|
|
129
|
+
async function handleUrlParams(_$w,urlParams,handleBackAndForth=false) {
|
|
116
130
|
try {
|
|
117
131
|
let applyFiltering=false;
|
|
118
132
|
let currentApplyFilterFlag=false;
|
|
@@ -146,8 +160,9 @@ async function handleUrlParams(_$w,urlParams) {
|
|
|
146
160
|
}
|
|
147
161
|
currentApplyFilterFlag=false;
|
|
148
162
|
}
|
|
149
|
-
if(applyFiltering || keywordAllJobs) {
|
|
163
|
+
if(applyFiltering || keywordAllJobs || handleBackAndForth) {
|
|
150
164
|
await updateJobsAndNumbersAndFilters(_$w);
|
|
165
|
+
|
|
151
166
|
}
|
|
152
167
|
|
|
153
168
|
if(urlParams.page) {
|
|
@@ -186,17 +201,15 @@ async function handleParams(_$w,param,values) {
|
|
|
186
201
|
for(const value of valuesAsArray) {
|
|
187
202
|
|
|
188
203
|
const decodedValue = decodeURIComponent(value);
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
const option=getCorrectOption(decodedValue,options,param);
|
|
204
|
+
const options = optionsByFieldId.get(field._id);
|
|
205
|
+
const option = getCorrectOption(decodedValue, options, param);
|
|
193
206
|
|
|
194
207
|
if(option) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
applyFiltering=true;
|
|
199
|
-
dontUpdateThisCheckBox=field._id;
|
|
208
|
+
const optionIndex = getOptionIndexFromCheckBox(_$w(`#${FiltersIds[field.title]}CheckBox`).options,option.value);
|
|
209
|
+
selectedIndices.push(optionIndex);
|
|
210
|
+
existing.push(option.value);
|
|
211
|
+
applyFiltering = true;
|
|
212
|
+
dontUpdateThisCheckBox = field._id;
|
|
200
213
|
}
|
|
201
214
|
else {
|
|
202
215
|
console.warn(`${param} value not found in dropdown options`);
|
|
@@ -248,6 +261,7 @@ async function handleParams(_$w,param,values) {
|
|
|
248
261
|
const field=getFieldById(fieldId,allfields);
|
|
249
262
|
let fieldTitle=field.title.toLowerCase().replace(' ', '');
|
|
250
263
|
fieldTitle==="brands"? fieldTitle="brand":fieldTitle;
|
|
264
|
+
ActivateURLOnchange=false;
|
|
251
265
|
if (updated.length) {
|
|
252
266
|
selectedByField.set(fieldId, updated);
|
|
253
267
|
queryParams.add({ [fieldTitle] : updated.map(val=>encodeURIComponent(val)).join(',') });
|
|
@@ -255,10 +269,12 @@ async function handleParams(_$w,param,values) {
|
|
|
255
269
|
selectedByField.delete(fieldId);
|
|
256
270
|
queryParams.remove([fieldTitle ]);
|
|
257
271
|
}
|
|
272
|
+
|
|
258
273
|
const currentVals = _$w(`#${FiltersIds[field.title]}CheckBox`).value || [];
|
|
259
274
|
const nextVals = currentVals.filter(v => v !== valueId);
|
|
260
275
|
_$w(`#${FiltersIds[field.title]}CheckBox`).value = nextVals;
|
|
261
276
|
await updateJobsAndNumbersAndFilters(_$w);
|
|
277
|
+
|
|
262
278
|
});
|
|
263
279
|
});
|
|
264
280
|
updateSelectedValuesRepeater(_$w);
|
|
@@ -274,14 +290,14 @@ async function loadData() {
|
|
|
274
290
|
currentJobs=alljobs;
|
|
275
291
|
}
|
|
276
292
|
if(Object.keys(valueToJobs).length === 0){
|
|
277
|
-
allvaluesobjects=await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
|
|
293
|
+
allvaluesobjects = await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
|
|
278
294
|
for (const value of allvaluesobjects) {
|
|
279
|
-
valueToJobs[value.
|
|
295
|
+
valueToJobs[value.valueId]= value.jobIds;
|
|
280
296
|
}
|
|
281
297
|
}
|
|
282
298
|
if(allfields.length===0) {
|
|
283
|
-
allfields=await getAllRecords(COLLECTIONS.CUSTOM_FIELDS);
|
|
284
|
-
allfields.push({_id:"Location",title:"Location"});
|
|
299
|
+
allfields = await getAllRecords(COLLECTIONS.CUSTOM_FIELDS);
|
|
300
|
+
allfields.push({ _id:"Location", title:"Location" });
|
|
285
301
|
}
|
|
286
302
|
} catch (error) {
|
|
287
303
|
console.error('Failed to load data:', error);
|
|
@@ -318,44 +334,47 @@ async function loadJobsRepeater(_$w) {
|
|
|
318
334
|
async function loadFilters(_$w) {
|
|
319
335
|
try {
|
|
320
336
|
// 1) Load all categories (fields)
|
|
321
|
-
const cities=await getAllRecords(COLLECTIONS.CITIES);
|
|
337
|
+
const cities = await getAllRecords(COLLECTIONS.CITIES);
|
|
322
338
|
for(const city of cities) {
|
|
323
|
-
valueToJobs[city._id]=city.jobIds;
|
|
339
|
+
valueToJobs[city._id] = city.jobIds;
|
|
324
340
|
}
|
|
325
341
|
// 2) Load all values once and group them by referenced field
|
|
326
342
|
let valuesByFieldId = groupValuesByField(allvaluesobjects, CUSTOM_VALUES_COLLECTION_FIELDS.CUSTOM_FIELD);
|
|
327
343
|
valuesByFieldId.set("Location",cities)
|
|
328
|
-
// Build CheckboxGroup options for this field
|
|
329
|
-
|
|
344
|
+
// Build CheckboxGroup options for this field
|
|
330
345
|
const counter={}
|
|
331
346
|
for(const city of cities) {
|
|
332
347
|
counter[city.city]=city.count
|
|
333
348
|
}
|
|
349
|
+
|
|
334
350
|
for(const [key, value] of valuesByFieldId) {
|
|
335
|
-
const field=getFieldById(key,allfields);
|
|
351
|
+
const field = getFieldById(key,allfields);
|
|
336
352
|
let originalOptions=[];
|
|
337
|
-
if(key==="Location") {
|
|
338
|
-
originalOptions=value.map(city=>({
|
|
353
|
+
if(key === "Location") {
|
|
354
|
+
originalOptions = value.map(city=>({
|
|
339
355
|
label: city.city,
|
|
340
356
|
value: city._id
|
|
341
357
|
}));
|
|
342
358
|
}
|
|
343
359
|
else{
|
|
344
|
-
originalOptions=value
|
|
360
|
+
originalOptions = value
|
|
345
361
|
}
|
|
362
|
+
|
|
346
363
|
optionsByFieldId.set(key, originalOptions);
|
|
364
|
+
|
|
347
365
|
for (const val of allvaluesobjects) {
|
|
348
366
|
counter[val.title]=val.count
|
|
349
367
|
}
|
|
350
368
|
countsByFieldId.set(key, new Map(originalOptions.map(o => [o.value, counter[o.label]])));
|
|
351
|
-
updateOptionsUI(_$w,field.title, field._id, ''); // no search query
|
|
369
|
+
updateOptionsUI(_$w, field.title, field._id, ''); // no search query
|
|
370
|
+
|
|
352
371
|
_$w(`#${FiltersIds[field.title]}CheckBox`).selectedIndices = []; // start empty
|
|
353
372
|
_$w(`#${FiltersIds[field.title]}CheckBox`).onChange(async (ev) => {
|
|
354
373
|
dontUpdateThisCheckBox=field._id;
|
|
355
374
|
const selected = ev.target.value; // array of selected value IDs
|
|
356
375
|
let fieldTitle=field.title.toLowerCase().replace(' ', '');
|
|
357
376
|
fieldTitle==="brands"? fieldTitle="brand":fieldTitle;
|
|
358
|
-
|
|
377
|
+
ActivateURLOnchange=false;
|
|
359
378
|
if (selected && selected.length) {
|
|
360
379
|
selectedByField.set(field._id, selected);
|
|
361
380
|
if(fieldTitle==="brand" || fieldTitle==="storename") {
|
|
@@ -371,10 +390,11 @@ async function loadJobsRepeater(_$w) {
|
|
|
371
390
|
selectedByField.delete(field._id);
|
|
372
391
|
queryParams.remove([fieldTitle ]);
|
|
373
392
|
}
|
|
374
|
-
|
|
393
|
+
|
|
394
|
+
console.log("selectedByField: ",selectedByField)
|
|
375
395
|
await updateJobsAndNumbersAndFilters(_$w);
|
|
376
|
-
|
|
377
396
|
});
|
|
397
|
+
|
|
378
398
|
const runFilter = debounce(() => {
|
|
379
399
|
const query = (_$w(`#${FiltersIds[field.title]}input`).value || '').toLowerCase().trim();
|
|
380
400
|
updateOptionsUI(_$w, field.title, field._id, query);
|
|
@@ -389,11 +409,11 @@ async function loadJobsRepeater(_$w) {
|
|
|
389
409
|
}
|
|
390
410
|
}
|
|
391
411
|
|
|
392
|
-
function getValueFromValueId(valueIds,value) {
|
|
393
|
-
let valueLabels=[];
|
|
412
|
+
function getValueFromValueId(valueIds, value) {
|
|
413
|
+
let valueLabels = [];
|
|
394
414
|
let currentVal
|
|
395
|
-
for(const valueId of valueIds) {
|
|
396
|
-
currentVal=value.find(val=>val.value===valueId);
|
|
415
|
+
for (const valueId of valueIds) {
|
|
416
|
+
currentVal = value.find(val => val.value === valueId);
|
|
397
417
|
if(currentVal) {
|
|
398
418
|
valueLabels.push(currentVal.label);
|
|
399
419
|
}
|
|
@@ -402,10 +422,10 @@ function getValueFromValueId(valueIds,value) {
|
|
|
402
422
|
}
|
|
403
423
|
|
|
404
424
|
async function updateJobsAndNumbersAndFilters(_$w,clearAll=false) {
|
|
405
|
-
await applyJobFilters(_$w); // re-query jobs
|
|
425
|
+
await applyJobFilters(_$w,clearAll); // re-query jobs
|
|
406
426
|
await refreshFacetCounts(_$w,clearAll); // recompute and update counts in all lists
|
|
407
427
|
await updateSelectedValuesRepeater(_$w);
|
|
408
|
-
updateTotalJobsCountText(_$w);
|
|
428
|
+
updateTotalJobsCountText(_$w);
|
|
409
429
|
}
|
|
410
430
|
|
|
411
431
|
function updateOptionsUI(_$w,fieldTitle, fieldId, searchQuery,clearAll=false) {
|
|
@@ -452,7 +472,8 @@ function getValueFromValueId(valueIds,value) {
|
|
|
452
472
|
}
|
|
453
473
|
}
|
|
454
474
|
|
|
455
|
-
async function applyJobFilters(_$w) {
|
|
475
|
+
async function applyJobFilters(_$w,clearAll=false) {
|
|
476
|
+
// if(!clearAll) {
|
|
456
477
|
let tempFilteredJobs=[];
|
|
457
478
|
let finalFilteredJobs=[];
|
|
458
479
|
secondarySearchIsFilled? finalFilteredJobs=allsecondarySearchJobs:finalFilteredJobs=alljobs;
|
|
@@ -486,12 +507,13 @@ function getValueFromValueId(valueIds,value) {
|
|
|
486
507
|
finalFilteredJobs=tempFilteredJobs;
|
|
487
508
|
tempFilteredJobs=[];
|
|
488
509
|
}
|
|
489
|
-
|
|
490
510
|
secondarySearchIsFilled? currentSecondarySearchJobs=finalFilteredJobs:currentJobs=finalFilteredJobs;
|
|
491
511
|
|
|
492
512
|
|
|
493
513
|
let jobsFirstPage=[];
|
|
514
|
+
console.log("currentSecondarySearchJobs: ",currentSecondarySearchJobs)
|
|
494
515
|
secondarySearchIsFilled? jobsFirstPage=currentSecondarySearchJobs.slice(0,pagination.pageSize):jobsFirstPage=currentJobs.slice(0,pagination.pageSize);
|
|
516
|
+
console.log("jobsFirstPage: ",jobsFirstPage)
|
|
495
517
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.JOBS_REPEATER).data = jobsFirstPage;
|
|
496
518
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.paginationCurrentText).text = "1";
|
|
497
519
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.paginationTotalCountText).text = secondarySearchIsFilled? Math.ceil(currentSecondarySearchJobs.length/pagination.pageSize).toString():Math.ceil(currentJobs.length/pagination.pageSize).toString();
|
|
@@ -504,6 +526,7 @@ function getValueFromValueId(valueIds,value) {
|
|
|
504
526
|
pagination.currentPage=1;
|
|
505
527
|
handlePaginationButtons(_$w);
|
|
506
528
|
}
|
|
529
|
+
// }
|
|
507
530
|
|
|
508
531
|
function handlePaginationButtons(_$w)
|
|
509
532
|
{
|
|
@@ -527,14 +550,15 @@ function handlePaginationButtons(_$w)
|
|
|
527
550
|
}
|
|
528
551
|
|
|
529
552
|
function handlePageUrlParam() {
|
|
553
|
+
ActivateURLOnchange=false;
|
|
530
554
|
if(pagination.currentPage==1)
|
|
531
555
|
{
|
|
556
|
+
|
|
532
557
|
queryParams.remove(["page"]);
|
|
533
558
|
}
|
|
534
559
|
else{
|
|
535
560
|
queryParams.add({ page: pagination.currentPage });
|
|
536
561
|
}
|
|
537
|
-
|
|
538
562
|
}
|
|
539
563
|
async function refreshFacetCounts(_$w,clearAll=false) {
|
|
540
564
|
|
|
@@ -553,7 +577,7 @@ async function refreshFacetCounts(_$w,clearAll=false) {
|
|
|
553
577
|
const currentJobsIds=jobs.map(job=>job._id);
|
|
554
578
|
|
|
555
579
|
for (const fieldId of fieldIds) {
|
|
556
|
-
let currentoptions=optionsByFieldId.get(fieldId)
|
|
580
|
+
let currentoptions = optionsByFieldId.get(fieldId)
|
|
557
581
|
let counter=new Map();
|
|
558
582
|
for(const option of currentoptions) {
|
|
559
583
|
for (const jobId of currentJobsIds) {
|
|
@@ -566,8 +590,7 @@ async function refreshFacetCounts(_$w,clearAll=false) {
|
|
|
566
590
|
}
|
|
567
591
|
}
|
|
568
592
|
|
|
569
|
-
|
|
570
|
-
function updateSelectedValuesRepeater(_$w) {
|
|
593
|
+
function updateSelectedValuesRepeater(_$w) {
|
|
571
594
|
const selectedItems = [];
|
|
572
595
|
for (const [fieldId, valueIds] of selectedByField.entries()) {
|
|
573
596
|
const opts = optionsByFieldId.get(fieldId) || [];
|
|
@@ -578,7 +601,7 @@ async function refreshFacetCounts(_$w,clearAll=false) {
|
|
|
578
601
|
}
|
|
579
602
|
}
|
|
580
603
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.SELECTED_VALUES_REPEATER).data = selectedItems;
|
|
581
|
-
|
|
604
|
+
}
|
|
582
605
|
|
|
583
606
|
|
|
584
607
|
|
package/pages/homePage.js
CHANGED
|
@@ -14,14 +14,16 @@ async function homePageOnReady(_$w,thisObject = null) {
|
|
|
14
14
|
const queryResult = await wixData.query(COLLECTIONS.SITE_CONFIGS).find();
|
|
15
15
|
const siteconfig = queryResult.items[0];
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
if(siteconfig.twg) {
|
|
18
19
|
const allvaluesobjects = await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
|
|
19
20
|
bindPrimarySearch(_$w, allvaluesobjects);
|
|
20
21
|
loadPrimarySearchRepeater(_$w)
|
|
21
22
|
console.log("siteconfig.twg: ",siteconfig.twg);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
if(siteconfig.twg === "external") {
|
|
25
|
+
bindTeamRepeater(_$w)
|
|
26
|
+
bindViewAllButton(_$w)
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
else{
|
package/pages/pagesUtils.js
CHANGED
|
@@ -12,7 +12,7 @@ function groupValuesByField(values, refKey) {
|
|
|
12
12
|
if (!map.has(ref)) map.set(ref, []);
|
|
13
13
|
map.get(ref).push({
|
|
14
14
|
label: v.title ,
|
|
15
|
-
value: v.
|
|
15
|
+
value: v.valueId
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
return map;
|
|
@@ -144,6 +144,9 @@ function bindPrimarySearch(_$w, allvaluesobjects) {
|
|
|
144
144
|
}
|
|
145
145
|
});
|
|
146
146
|
|
|
147
|
+
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).onMouseOut(async () => {
|
|
148
|
+
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
|
|
149
|
+
});
|
|
147
150
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).onMouseOut(async () => {
|
|
148
151
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.RESULTS_CONTAINER).collapse();
|
|
149
152
|
});
|
|
@@ -163,6 +166,14 @@ function bindPrimarySearch(_$w, allvaluesobjects) {
|
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
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
|
+
});
|
|
166
177
|
|
|
167
178
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_BUTTON).onClick(async () => {
|
|
168
179
|
if(_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_INPUT).value.trim()==='') {
|
|
@@ -177,13 +188,13 @@ function bindPrimarySearch(_$w, allvaluesobjects) {
|
|
|
177
188
|
});
|
|
178
189
|
}
|
|
179
190
|
|
|
180
|
-
async function loadCategoriesListPrimarySearch(_$w,allvaluesobjects) {
|
|
191
|
+
async function loadCategoriesListPrimarySearch(_$w, allvaluesobjects) {
|
|
181
192
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.PRIMARY_SEARCH_MULTI_BOX).changeState("categoryResults");
|
|
182
193
|
|
|
183
194
|
let categoryValues=[]
|
|
184
195
|
for(const value of allvaluesobjects) {
|
|
185
|
-
if(value.customField===CATEGORY_CUSTOM_FIELD_ID_IN_CMS) {
|
|
186
|
-
categoryValues.push({title:value.title+` (${value.count})` ,_id:value.
|
|
196
|
+
if(value.customField === CATEGORY_CUSTOM_FIELD_ID_IN_CMS) {
|
|
197
|
+
categoryValues.push({title: value.title+` (${value.count})` , _id: value.valueId});
|
|
187
198
|
}
|
|
188
199
|
}
|
|
189
200
|
_$w(CAREERS_MULTI_BOXES_PAGE_CONSTS.CATEGORY_RESULTS_REPEATER).data = categoryValues;
|
|
@@ -227,11 +238,13 @@ async function primarySearch(_$w, query) {
|
|
|
227
238
|
return count > 0;
|
|
228
239
|
}
|
|
229
240
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
async function getValueFromValueId(valueId) {
|
|
242
|
+
const result = await getAllRecords(COLLECTIONS.CUSTOM_VALUES);
|
|
243
|
+
console.log("result: ",result);
|
|
244
|
+
console.log("valueId: ",valueId);
|
|
245
|
+
|
|
246
|
+
return result.find(value => value.valueId === valueId);
|
|
247
|
+
}
|
|
235
248
|
|
|
236
249
|
async function getLatestJobsByValue(Value) {
|
|
237
250
|
const jobs=Value.multiRefJobsCustomValues;
|
package/pages/positionPage.js
CHANGED
|
@@ -15,7 +15,6 @@ const {
|
|
|
15
15
|
console.log("positionPageOnReady called");
|
|
16
16
|
await bind(_$w);
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
|
|
20
19
|
}
|
|
21
20
|
|
|
@@ -58,7 +57,7 @@ async function getCategoryValue(customValues) {
|
|
|
58
57
|
_$w('#jobCategory').text = categoryValue.title;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
const relatedJobs = await getRelatedJobs({ categoryValueId:categoryValue._id, itemId: item._id ,limit:5});
|
|
60
|
+
const relatedJobs = await getRelatedJobs({ categoryValueId: categoryValue._id, itemId: item._id ,limit:5});
|
|
62
61
|
_$w('#relatedJobsRepNoDepartment').onItemReady(($item, itemData) => {
|
|
63
62
|
$item('#relatedJobTitle').text = itemData.title;
|
|
64
63
|
$item('#relatedJobLocation').text = itemData.location.fullLocation;
|
|
@@ -124,8 +123,6 @@ async function getCategoryValue(customValues) {
|
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
async function getRelatedJobs({ categoryValueId, itemId, limit = 1000 }) {
|
|
127
|
-
|
|
128
|
-
|
|
129
126
|
const relatedJobs=await wixData.query(COLLECTIONS.JOBS).include(JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES).hasSome(JOBS_COLLECTION_FIELDS.MULTI_REF_JOBS_CUSTOM_VALUES,[categoryValueId]).ne("_id",itemId).limit(limit).find();
|
|
130
127
|
return relatedJobs.items;
|
|
131
128
|
}
|
|
@@ -32,16 +32,16 @@ async function handlePeopleSection(_$w) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
async function handleRecentJobsSection(_$w) {
|
|
35
|
-
|
|
36
|
-
|
|
37
35
|
if(supportTeamsPageIds.excludeValues.has(currentItem.title_fld)) {
|
|
38
36
|
console.log("Value is excluded , collapsing recently Jobs Section ");
|
|
39
|
-
await collapseSection(_$w,supportTeamsPageSections.RECENT_JOBS);
|
|
37
|
+
await collapseSection(_$w, supportTeamsPageSections.RECENT_JOBS);
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
40
|
+
|
|
41
|
+
const valueId = supportTeamsPageIds.valueToValueIdMap[currentItem.title_fld]
|
|
42
|
+
const Value = await getValueFromValueId(valueId);
|
|
43
|
+
|
|
44
|
+
if( Value === undefined ) {
|
|
45
45
|
console.log("Value is undefined , collapsing recently Jobs Section ");
|
|
46
46
|
await collapseSection(_$w,supportTeamsPageSections.RECENT_JOBS);
|
|
47
47
|
return;
|