@reldens/cms 0.57.0 → 0.59.0
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/admin/assets/admin/alert.png +0 -0
- package/admin/reldens-admin-client.css +2 -0
- package/admin/reldens-admin-client.js +65 -41
- package/admin/templates/fields/edit/file.html +16 -1
- package/admin/templates/list-content.html +8 -0
- package/admin/templates/view.html +2 -2
- package/lib/admin-manager/contents-builder.js +2 -1
- package/lib/admin-manager/router-contents.js +85 -29
- package/lib/frontend/content-renderer.js +1 -1
- package/lib/sitemap-loader.js +3 -6
- package/package.json +3 -3
|
Binary file
|
|
@@ -177,8 +177,7 @@ window.addEventListener('DOMContentLoaded', () => {
|
|
|
177
177
|
params.set('sortBy', columnName);
|
|
178
178
|
params.set('sortDirection', sortDirection);
|
|
179
179
|
}
|
|
180
|
-
|
|
181
|
-
window.location.href = newUrl;
|
|
180
|
+
window.location.href = url.pathname+'?'+params;
|
|
182
181
|
return false;
|
|
183
182
|
});
|
|
184
183
|
}
|
|
@@ -190,44 +189,35 @@ window.addEventListener('DOMContentLoaded', () => {
|
|
|
190
189
|
if(sortableHeaders){
|
|
191
190
|
for(let header of sortableHeaders){
|
|
192
191
|
header.addEventListener('click', () => {
|
|
192
|
+
let sortForm = header.querySelector('.sort-form');
|
|
193
|
+
if(!sortForm){
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
193
196
|
let columnName = header.getAttribute('data-column');
|
|
194
|
-
let currentSortDirection = header.classList.contains('sorted-asc')
|
|
197
|
+
let currentSortDirection = header.classList.contains('sorted-asc')
|
|
198
|
+
? 'asc'
|
|
199
|
+
: header.classList.contains('sorted-desc') ? 'desc' : '';
|
|
195
200
|
let newSortDirection = 'asc';
|
|
196
201
|
if('asc' === currentSortDirection){
|
|
197
202
|
newSortDirection = 'desc';
|
|
198
203
|
}
|
|
199
|
-
let
|
|
200
|
-
|
|
201
|
-
sortForm.action = window.location.pathname;
|
|
202
|
-
let sortByInput = document.createElement('input');
|
|
203
|
-
sortByInput.type = 'hidden';
|
|
204
|
-
sortByInput.name = 'sortBy';
|
|
204
|
+
let sortByInput = sortForm.querySelector('input[name="sortBy"]');
|
|
205
|
+
let sortDirectionInput = sortForm.querySelector('input[name="sortDirection"]');
|
|
205
206
|
sortByInput.value = columnName;
|
|
206
|
-
sortForm.appendChild(sortByInput);
|
|
207
|
-
let sortDirectionInput = document.createElement('input');
|
|
208
|
-
sortDirectionInput.type = 'hidden';
|
|
209
|
-
sortDirectionInput.name = 'sortDirection';
|
|
210
207
|
sortDirectionInput.value = newSortDirection;
|
|
211
|
-
sortForm.appendChild(sortDirectionInput);
|
|
212
208
|
let entitySearchInput = document.querySelector('#entityFilterTerm');
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
filterTermInput.name = 'entityFilterTerm';
|
|
217
|
-
filterTermInput.value = entitySearchInput.value;
|
|
218
|
-
sortForm.appendChild(filterTermInput);
|
|
209
|
+
let entityFilterTermInput = sortForm.querySelector('input[name="entityFilterTerm"]');
|
|
210
|
+
if(entityFilterTermInput){
|
|
211
|
+
entityFilterTermInput.value = entitySearchInput?.value || '';
|
|
219
212
|
}
|
|
220
213
|
let allFilters = document.querySelectorAll('.filters-toggle-content .filter input');
|
|
221
214
|
for(let filterInput of allFilters){
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
filterFieldInput.value = filterInput.value;
|
|
227
|
-
sortForm.appendChild(filterFieldInput);
|
|
215
|
+
let filterName = filterInput.name.replace(/^filters\[/, '').replace(/\]$/, '');
|
|
216
|
+
let sortFormFilterInput = sortForm.querySelector('input[data-filter-key="'+filterName+'"]');
|
|
217
|
+
if(sortFormFilterInput){
|
|
218
|
+
sortFormFilterInput.value = filterInput.value;
|
|
228
219
|
}
|
|
229
220
|
}
|
|
230
|
-
document.body.appendChild(sortForm);
|
|
231
221
|
sortForm.submit();
|
|
232
222
|
});
|
|
233
223
|
}
|
|
@@ -349,26 +339,60 @@ window.addEventListener('DOMContentLoaded', () => {
|
|
|
349
339
|
button.addEventListener('click', (event) => {
|
|
350
340
|
event.preventDefault();
|
|
351
341
|
let fieldName = button.getAttribute('data-field');
|
|
342
|
+
let fileName = button.getAttribute('data-filename');
|
|
352
343
|
let fileInput = document.getElementById(fieldName);
|
|
353
|
-
let
|
|
344
|
+
let form = fileInput?.closest('form');
|
|
345
|
+
if(!fileInput){
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if(!form){
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
let currentFileDisplay = button.closest('.upload-current-file');
|
|
352
|
+
let container = button.closest('.upload-files-container');
|
|
353
|
+
let isRequired = container && 'true' === container.dataset.required;
|
|
354
|
+
if(isRequired){
|
|
355
|
+
let remainingFiles = container.querySelectorAll('.upload-current-file');
|
|
356
|
+
if(2 === remainingFiles.length){
|
|
357
|
+
let allRemoveButtons = container.querySelectorAll('.remove-upload-btn');
|
|
358
|
+
for(let removeBtn of allRemoveButtons){
|
|
359
|
+
removeBtn.remove();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
354
363
|
if(currentFileDisplay){
|
|
355
|
-
currentFileDisplay.
|
|
364
|
+
currentFileDisplay.remove();
|
|
356
365
|
}
|
|
357
|
-
if(
|
|
358
|
-
|
|
359
|
-
let
|
|
360
|
-
if(
|
|
361
|
-
let
|
|
362
|
-
let
|
|
363
|
-
if(
|
|
364
|
-
|
|
365
|
-
clearInput.type = 'hidden';
|
|
366
|
-
clearInput.name = clearFieldName;
|
|
367
|
-
clearInput.value = '1';
|
|
368
|
-
form.appendChild(clearInput);
|
|
366
|
+
if(fileName){
|
|
367
|
+
let hiddenFieldName = 'removed_'+fieldName;
|
|
368
|
+
let existingHiddenInput = form.querySelector('input[name="'+hiddenFieldName+'"]');
|
|
369
|
+
if(existingHiddenInput){
|
|
370
|
+
let currentValue = existingHiddenInput.value;
|
|
371
|
+
let filesArray = currentValue ? currentValue.split(',') : [];
|
|
372
|
+
if(-1 === filesArray.indexOf(fileName)){
|
|
373
|
+
filesArray.push(fileName);
|
|
369
374
|
}
|
|
375
|
+
existingHiddenInput.value = filesArray.join(',');
|
|
376
|
+
return;
|
|
370
377
|
}
|
|
378
|
+
let hiddenInput = document.createElement('input');
|
|
379
|
+
hiddenInput.type = 'hidden';
|
|
380
|
+
hiddenInput.name = hiddenFieldName;
|
|
381
|
+
hiddenInput.value = fileName;
|
|
382
|
+
form.appendChild(hiddenInput);
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
fileInput.value = '';
|
|
386
|
+
let clearFieldName = 'clear_'+fieldName;
|
|
387
|
+
let existingClearInput = form.querySelector('input[name="'+clearFieldName+'"]');
|
|
388
|
+
if(existingClearInput){
|
|
389
|
+
return;
|
|
371
390
|
}
|
|
391
|
+
let clearInput = document.createElement('input');
|
|
392
|
+
clearInput.type = 'hidden';
|
|
393
|
+
clearInput.name = clearFieldName;
|
|
394
|
+
clearInput.value = '1';
|
|
395
|
+
form.appendChild(clearInput);
|
|
372
396
|
});
|
|
373
397
|
}
|
|
374
398
|
}
|
|
@@ -1,2 +1,17 @@
|
|
|
1
|
-
{{
|
|
1
|
+
{{{renderedAlert}}}
|
|
2
|
+
{{{renderedFiles}}}
|
|
3
|
+
{{#fieldValue}}
|
|
4
|
+
{{^renderedFiles}}
|
|
5
|
+
<div class="upload-files-container" data-field="{{&fieldName}}" data-required="{{isRequired}}">
|
|
6
|
+
{{#filesArray}}
|
|
7
|
+
<p class="upload-current-file" data-field="{{&fieldName}}" data-filename="{{&filename}}">
|
|
8
|
+
{{#isRemovable}}
|
|
9
|
+
<button type="button" class="remove-upload-btn" data-field="{{&fieldName}}" data-filename="{{&filename}}" title="REMOVE">X</button> -
|
|
10
|
+
{{/isRemovable}}
|
|
11
|
+
{{&filename}}
|
|
12
|
+
</p>
|
|
13
|
+
{{/filesArray}}
|
|
14
|
+
</div>
|
|
15
|
+
{{/renderedFiles}}
|
|
16
|
+
{{/fieldValue}}
|
|
2
17
|
<input type="file" name="{{&fieldName}}" id="{{&fieldName}}"{{&required}}{{&fieldDisabled}}{{&multiple}}/>
|
|
@@ -27,6 +27,14 @@
|
|
|
27
27
|
</svg>
|
|
28
28
|
</span>
|
|
29
29
|
</div>
|
|
30
|
+
<form class="sort-form hidden" method="POST" action="{{&listRoute}}">
|
|
31
|
+
<input type="hidden" name="sortBy" value=""/>
|
|
32
|
+
<input type="hidden" name="sortDirection" value=""/>
|
|
33
|
+
<input type="hidden" name="entityFilterTerm" value=""/>
|
|
34
|
+
{{#filters}}
|
|
35
|
+
<input type="hidden" name="filters[{{&propertyKey}}]" value="" data-filter-key="{{&propertyKey}}"/>
|
|
36
|
+
{{/filters}}
|
|
37
|
+
</form>
|
|
30
38
|
</th>
|
|
31
39
|
{{/fieldsHeaders}}
|
|
32
40
|
<th class="field field-edit"></th>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</form>
|
|
13
13
|
</div>
|
|
14
14
|
<div class="extra-actions">
|
|
15
|
-
{{&
|
|
15
|
+
{{&extraContentTop}}
|
|
16
16
|
</div>
|
|
17
17
|
{{#fields}}
|
|
18
18
|
<div class="view-field">
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
</span>
|
|
33
33
|
</form>
|
|
34
34
|
<div class="extra-actions">
|
|
35
|
-
{{&
|
|
35
|
+
{{&extraContentBottom}}
|
|
36
36
|
</div>
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
@@ -185,7 +185,8 @@ class ContentsBuilder
|
|
|
185
185
|
id: '{{&id}}',
|
|
186
186
|
entityEditRoute: '{{&entityEditRoute}}',
|
|
187
187
|
entityNewRoute: '{{&entityNewRoute}}',
|
|
188
|
-
|
|
188
|
+
extraContentTop: '{{&extraContentForViewTop}}',
|
|
189
|
+
extraContentBottom: '{{&extraContentForViewBottom}}'+extraContentForView,
|
|
189
190
|
extraFormContent: '{{&extraFormContentForView}}'+extraFormContentForView
|
|
190
191
|
}
|
|
191
192
|
),
|
|
@@ -197,6 +197,8 @@ class RouterContents
|
|
|
197
197
|
await this.emitEvent('adminEntityExtraData', extraDataEvent);
|
|
198
198
|
renderedViewProperties.entitySerializedData = JSON.stringify(extraDataEvent.entitySerializedData)
|
|
199
199
|
.replace(/"/g, '"');
|
|
200
|
+
renderedViewProperties.extraContentForViewTop = '';
|
|
201
|
+
renderedViewProperties.extraContentForViewBottom = '';
|
|
200
202
|
await this.emitEvent('reldens.adminViewPropertiesPopulation', {
|
|
201
203
|
idProperty,
|
|
202
204
|
req,
|
|
@@ -228,26 +230,53 @@ class RouterContents
|
|
|
228
230
|
req,
|
|
229
231
|
driverResource,
|
|
230
232
|
renderedEditProperties,
|
|
231
|
-
loadedEntity
|
|
233
|
+
loadedEntity,
|
|
234
|
+
entityId: driverResource.id(),
|
|
235
|
+
entityData: loadedEntity
|
|
232
236
|
});
|
|
233
237
|
for(let propertyKey of Object.keys(driverResource.options.properties)){
|
|
234
238
|
let property = driverResource.options.properties[propertyKey];
|
|
235
239
|
let fieldDisabled = -1 === driverResource.options.editProperties.indexOf(propertyKey);
|
|
240
|
+
let fieldValue = await this.generatePropertyEditRenderedValue(
|
|
241
|
+
loadedEntity,
|
|
242
|
+
propertyKey,
|
|
243
|
+
property,
|
|
244
|
+
fieldDisabled
|
|
245
|
+
);
|
|
246
|
+
let templateData = {
|
|
247
|
+
fieldName: propertyKey,
|
|
248
|
+
fieldValue,
|
|
249
|
+
fieldDisabled: fieldDisabled ? ' disabled="disabled"' : '',
|
|
250
|
+
required: (!property.isUpload || !loadedEntity) && property.isRequired ? ' required="required"' : '',
|
|
251
|
+
multiple: property.isArray ? ' multiple="multiple"' : '',
|
|
252
|
+
inputType: this.getInputType(property, propertyKey, fieldDisabled),
|
|
253
|
+
isArray: property.isArray || '',
|
|
254
|
+
arraySeparator: property.isArray || '',
|
|
255
|
+
isRequired: property.isRequired || false
|
|
256
|
+
};
|
|
257
|
+
if(property.isUpload && fieldValue && '' !== fieldValue){
|
|
258
|
+
let filesArray = property.isArray ? fieldValue.split(property.isArray) : [fieldValue];
|
|
259
|
+
templateData.filesArray = filesArray.map((filename) => {
|
|
260
|
+
return {
|
|
261
|
+
filename,
|
|
262
|
+
isRemovable: !property.isRequired || filesArray.length > 1
|
|
263
|
+
};
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
await this.emitEvent('reldens.adminBeforeFieldRender', {
|
|
267
|
+
req,
|
|
268
|
+
driverResource,
|
|
269
|
+
propertyKey,
|
|
270
|
+
property,
|
|
271
|
+
templateData,
|
|
272
|
+
loadedEntity,
|
|
273
|
+
renderedEditProperties,
|
|
274
|
+
adminContentsRender: this.adminContentsRender.bind(this),
|
|
275
|
+
adminFilesContents: this.adminFilesContents
|
|
276
|
+
});
|
|
236
277
|
renderedEditProperties[propertyKey] = await this.adminContentsRender(
|
|
237
278
|
this.adminFilesContents.fields.edit[this.propertyType(property, 'edit')],
|
|
238
|
-
|
|
239
|
-
fieldName: propertyKey,
|
|
240
|
-
fieldValue: await this.generatePropertyEditRenderedValue(
|
|
241
|
-
loadedEntity,
|
|
242
|
-
propertyKey,
|
|
243
|
-
property,
|
|
244
|
-
fieldDisabled
|
|
245
|
-
),
|
|
246
|
-
fieldDisabled: fieldDisabled ? ' disabled="disabled"' : '',
|
|
247
|
-
required: (!property.isUpload || !loadedEntity) && property.isRequired ? ' required="required"' : '',
|
|
248
|
-
multiple: property.isArray ? ' multiple="multiple"' : '',
|
|
249
|
-
inputType: this.getInputType(property, propertyKey, fieldDisabled)
|
|
250
|
-
}
|
|
279
|
+
templateData
|
|
251
280
|
);
|
|
252
281
|
}
|
|
253
282
|
return await this.adminContentsRenderRoute(
|
|
@@ -282,6 +311,10 @@ class RouterContents
|
|
|
282
311
|
|
|
283
312
|
async processSaveEntity(req, res, driverResource, entityPath)
|
|
284
313
|
{
|
|
314
|
+
let idProperty = this.fetchEntityIdPropertyKey(driverResource);
|
|
315
|
+
let id = (req?.body[idProperty] || '');
|
|
316
|
+
let entityRepository = this.dataServer.getEntity(driverResource.entityKey);
|
|
317
|
+
let loadedEntity = id ? await this.loadEntityById(driverResource, id) : null;
|
|
285
318
|
let uploadProperties = this.fetchUploadProperties(driverResource);
|
|
286
319
|
if(0 < Object.keys(uploadProperties).length){
|
|
287
320
|
if(this.uploaderFactory?.error?.message){
|
|
@@ -289,22 +322,20 @@ class RouterContents
|
|
|
289
322
|
return this.rootPath+'/'+entityPath+'?result=uploadError&error='
|
|
290
323
|
+encodeURIComponent(this.uploaderFactory.error.message);
|
|
291
324
|
}
|
|
292
|
-
let uploadValidationResult = this.validateUploadedFiles(req, uploadProperties);
|
|
325
|
+
let uploadValidationResult = this.validateUploadedFiles(req, uploadProperties, loadedEntity);
|
|
293
326
|
if(!uploadValidationResult.success){
|
|
294
327
|
Logger.error('Upload validation failed', uploadValidationResult.error);
|
|
295
328
|
return this.rootPath+'/'+entityPath+'?result=uploadValidationError&error='
|
|
296
329
|
+encodeURIComponent(uploadValidationResult.error.message);
|
|
297
330
|
}
|
|
298
331
|
}
|
|
299
|
-
let idProperty = this.fetchEntityIdPropertyKey(driverResource);
|
|
300
|
-
let id = (req?.body[idProperty] || '');
|
|
301
|
-
let entityRepository = this.dataServer.getEntity(driverResource.entityKey);
|
|
302
332
|
let entityDataPatch = this.preparePatchData(
|
|
303
333
|
driverResource,
|
|
304
334
|
idProperty,
|
|
305
335
|
req,
|
|
306
336
|
driverResource.options.properties,
|
|
307
|
-
id
|
|
337
|
+
id,
|
|
338
|
+
loadedEntity
|
|
308
339
|
);
|
|
309
340
|
if(!entityDataPatch){
|
|
310
341
|
Logger.error('Bad patch data.', entityDataPatch);
|
|
@@ -351,14 +382,21 @@ class RouterContents
|
|
|
351
382
|
}
|
|
352
383
|
}
|
|
353
384
|
|
|
354
|
-
validateUploadedFiles(req, uploadProperties)
|
|
385
|
+
validateUploadedFiles(req, uploadProperties, loadedEntity)
|
|
355
386
|
{
|
|
356
387
|
for(let uploadPropertyKey of Object.keys(uploadProperties)){
|
|
357
388
|
let property = uploadProperties[uploadPropertyKey];
|
|
358
389
|
let uploadedFiles = req.files?.[uploadPropertyKey];
|
|
359
390
|
if(!uploadedFiles || 0 === uploadedFiles.length){
|
|
360
391
|
if(property.isRequired){
|
|
361
|
-
|
|
392
|
+
let isExplicitClear = '1' === sc.get(req.body, 'clear_'+uploadPropertyKey, false);
|
|
393
|
+
if(isExplicitClear){
|
|
394
|
+
return {success: false, error: {message: 'Required file upload missing: '+uploadPropertyKey}};
|
|
395
|
+
}
|
|
396
|
+
let existingValue = loadedEntity ? sc.get(loadedEntity, uploadPropertyKey, '') : '';
|
|
397
|
+
if(!existingValue || '' === existingValue){
|
|
398
|
+
return {success: false, error: {message: 'Required file upload missing: '+uploadPropertyKey}};
|
|
399
|
+
}
|
|
362
400
|
}
|
|
363
401
|
continue;
|
|
364
402
|
}
|
|
@@ -484,7 +522,7 @@ class RouterContents
|
|
|
484
522
|
}
|
|
485
523
|
}
|
|
486
524
|
|
|
487
|
-
preparePatchData(driverResource, idProperty, req, resourceProperties, id)
|
|
525
|
+
preparePatchData(driverResource, idProperty, req, resourceProperties, id, loadedEntity)
|
|
488
526
|
{
|
|
489
527
|
let entityDataPatch = {};
|
|
490
528
|
for(let i of Object.keys(resourceProperties)){
|
|
@@ -512,7 +550,8 @@ class RouterContents
|
|
|
512
550
|
propertyUpdateValue = null;
|
|
513
551
|
}
|
|
514
552
|
if(!isExplicitClear){
|
|
515
|
-
|
|
553
|
+
let currentValue = loadedEntity ? sc.get(loadedEntity, i, '') : '';
|
|
554
|
+
propertyUpdateValue = this.prepareUploadPatchData(req, i, currentValue, property);
|
|
516
555
|
}
|
|
517
556
|
}
|
|
518
557
|
if('boolean' === propertyType){
|
|
@@ -539,7 +578,6 @@ class RouterContents
|
|
|
539
578
|
}
|
|
540
579
|
let isUploadCreate = property.isUpload && !id;
|
|
541
580
|
if(property.isRequired && (isNull || isEmpty) && (!property.isUpload || isUploadCreate)){
|
|
542
|
-
// missing required fields would break the update:
|
|
543
581
|
Logger.critical(
|
|
544
582
|
'Missing property on prepare patch data.',
|
|
545
583
|
{propertyKey: i, config: property, propertyUpdateValue, entity: driverResource.entityKey}
|
|
@@ -562,14 +600,32 @@ class RouterContents
|
|
|
562
600
|
prepareUploadPatchData(req, i, propertyUpdateValue, property)
|
|
563
601
|
{
|
|
564
602
|
let filesData = sc.get(req.files, i, null);
|
|
565
|
-
|
|
603
|
+
let removedFiles = sc.get(req.body, 'removed_'+i, '');
|
|
604
|
+
let existingFiles = propertyUpdateValue || '';
|
|
605
|
+
if(property.isArray && removedFiles && '' !== removedFiles){
|
|
606
|
+
let removedFilesArray = removedFiles.split(',');
|
|
607
|
+
let existingFilesArray = existingFiles ? existingFiles.split(property.isArray) : [];
|
|
608
|
+
existingFilesArray = existingFilesArray.filter(file => {
|
|
609
|
+
return -1 === removedFilesArray.indexOf(file);
|
|
610
|
+
});
|
|
611
|
+
existingFiles = existingFilesArray.join(property.isArray);
|
|
612
|
+
}
|
|
613
|
+
if(!filesData || 0 === filesData.length){
|
|
614
|
+
if(removedFiles && '' !== removedFiles){
|
|
615
|
+
return existingFiles;
|
|
616
|
+
}
|
|
566
617
|
return null;
|
|
567
618
|
}
|
|
568
|
-
let
|
|
619
|
+
let newFileNames = [];
|
|
569
620
|
for(let file of filesData){
|
|
570
|
-
|
|
621
|
+
newFileNames.push(file.filename);
|
|
622
|
+
}
|
|
623
|
+
if(property.isArray && existingFiles && '' !== existingFiles){
|
|
624
|
+
let existingFilesArray = existingFiles.split(property.isArray);
|
|
625
|
+
let allFiles = existingFilesArray.concat(newFileNames);
|
|
626
|
+
return allFiles.join(property.isArray);
|
|
571
627
|
}
|
|
572
|
-
return
|
|
628
|
+
return newFileNames.join(property.isArray);
|
|
573
629
|
}
|
|
574
630
|
|
|
575
631
|
async generatePropertyRenderedValue(fieldValue, fieldName, resourceProperty, templateType)
|
|
@@ -611,7 +667,7 @@ class RouterContents
|
|
|
611
667
|
fieldValue = '' !== fieldValue ? sc.formatDate(new Date(fieldValue)) : '';
|
|
612
668
|
}
|
|
613
669
|
if('reference' === resourceProperty.type){
|
|
614
|
-
let relationEntity = entity[resourceProperty.alias || resourceProperty.reference];
|
|
670
|
+
let relationEntity = entity[resourceProperty.alias || 'related_'+resourceProperty.reference];
|
|
615
671
|
if(relationEntity){
|
|
616
672
|
let relation = this.relations()[resourceProperty.reference];
|
|
617
673
|
if(relation){
|
|
@@ -123,7 +123,7 @@ class ContentRenderer
|
|
|
123
123
|
return layoutContent;
|
|
124
124
|
}
|
|
125
125
|
let routerKey = route?.router;
|
|
126
|
-
let categoryName = currentEntityData?.
|
|
126
|
+
let categoryName = currentEntityData?.related_cms_categories?.name;
|
|
127
127
|
let siteHandle = this.templateResolver.resolveDomainToSiteKey(domain)
|
|
128
128
|
+ (routerKey ? ' '+routerKey : '')
|
|
129
129
|
+ (categoryName ? ' cat-'+categoryName : '');
|
package/lib/sitemap-loader.js
CHANGED
|
@@ -65,14 +65,11 @@ class SitemapLoader
|
|
|
65
65
|
try {
|
|
66
66
|
let routesWithPages = await this.routesRepository.loadWithRelations(filters, 'cms_pages');
|
|
67
67
|
let sitemapPages = routesWithPages.filter(route => {
|
|
68
|
-
if(!route.
|
|
68
|
+
if(!route.related_cms_pages || 0 === route.related_cms_pages.length){
|
|
69
69
|
return false;
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
return true;
|
|
71
|
+
return 'noindex,nofollow' !== route.related_cms_pages[0].meta_robots;
|
|
72
|
+
|
|
76
73
|
});
|
|
77
74
|
req.sitemapPages = sitemapPages;
|
|
78
75
|
eventData.variables.sitemapPages = sitemapPages;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reldens/cms",
|
|
3
3
|
"scope": "@reldens",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.59.0",
|
|
5
5
|
"description": "Reldens - CMS",
|
|
6
6
|
"author": "Damian A. Pastorini",
|
|
7
7
|
"license": "MIT",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@reldens/server-utils": "^0.46.0",
|
|
38
|
-
"@reldens/storage": "^0.
|
|
38
|
+
"@reldens/storage": "^0.91.0",
|
|
39
39
|
"@reldens/utils": "^0.54.0",
|
|
40
|
-
"dotenv": "17.
|
|
40
|
+
"dotenv": "17.3.1",
|
|
41
41
|
"mustache": "4.2.0"
|
|
42
42
|
}
|
|
43
43
|
}
|