@reldens/cms 0.20.0 → 0.21.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/README.md +236 -11
- package/admin/reldens-admin-client.css +75 -21
- package/admin/reldens-admin-client.js +108 -133
- package/admin/templates/clear-all-cache-button.html +7 -7
- package/admin/templates/edit.html +7 -0
- package/admin/templates/layout.html +15 -9
- package/admin/templates/list-content.html +4 -2
- package/admin/templates/list.html +24 -8
- package/admin/templates/view.html +21 -0
- package/lib/admin-manager/admin-filters-manager.js +177 -0
- package/lib/admin-manager/contents-builder.js +1 -0
- package/lib/admin-manager/default-translations.js +38 -0
- package/lib/admin-manager/router-contents.js +50 -45
- package/lib/admin-manager/router.js +19 -0
- package/lib/frontend/content-renderer.js +178 -0
- package/lib/frontend/entity-access-manager.js +63 -0
- package/lib/frontend/request-processor.js +128 -0
- package/lib/frontend/response-manager.js +54 -0
- package/lib/frontend/template-cache.js +102 -0
- package/lib/frontend/template-resolver.js +111 -0
- package/lib/frontend.js +89 -630
- package/lib/manager.js +25 -12
- package/lib/search-renderer.js +15 -7
- package/lib/search-request-handler.js +67 -0
- package/lib/search.js +13 -1
- package/lib/template-engine/collections-single-transformer.js +11 -5
- package/lib/template-engine/collections-transformer.js +47 -34
- package/lib/template-engine/entities-transformer.js +3 -2
- package/lib/template-engine/partials-transformer.js +5 -6
- package/lib/template-engine/system-variables-provider.js +4 -1
- package/lib/template-engine.js +11 -5
- package/lib/template-reloader.js +307 -0
- package/package.json +4 -4
- package/templates/{browserconfig.xml → assets/favicons/default/browserconfig.xml} +1 -1
- package/templates/assets/favicons/default/favicon.ico +0 -0
- package/templates/{site.webmanifest → assets/favicons/default/site.webmanifest} +3 -3
- package/templates/js/functions.js +144 -0
- package/templates/js/scripts.js +5 -0
- package/templates/page.html +11 -5
- package/templates/partials/pagedCollection.html +1 -1
- package/lib/admin-translations.js +0 -56
- package/templates/favicon.ico +0 -0
- /package/templates/assets/favicons/{android-icon-144x144.png → default/android-icon-144x144.png} +0 -0
- /package/templates/assets/favicons/{android-icon-192x192.png → default/android-icon-192x192.png} +0 -0
- /package/templates/assets/favicons/{android-icon-512x512.png → default/android-icon-512x512.png} +0 -0
- /package/templates/assets/favicons/{apple-touch-icon.png → default/apple-touch-icon.png} +0 -0
- /package/templates/assets/favicons/{favicon-16x16.png → default/favicon-16x16.png} +0 -0
- /package/templates/assets/favicons/{favicon-32x32.png → default/favicon-32x32.png} +0 -0
- /package/templates/assets/favicons/{mstile-150x150.png → default/mstile-150x150.png} +0 -0
- /package/templates/assets/favicons/{safari-pinned-tab.svg → default/safari-pinned-tab.svg} +0 -0
package/lib/manager.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { TemplatesList } = require('./templates-list');
|
|
8
|
-
const {
|
|
8
|
+
const { DefaultTranslations } = require('./admin-manager/default-translations');
|
|
9
9
|
const { AdminTemplatesLoader } = require('./admin-templates-loader');
|
|
10
10
|
const { AdminManagerValidator } = require('./admin-manager-validator');
|
|
11
11
|
const { MimeTypes } = require('./mime-types');
|
|
@@ -18,6 +18,7 @@ const { CmsPagesRouteManager } = require('./cms-pages-route-manager');
|
|
|
18
18
|
const { Installer } = require('./installer');
|
|
19
19
|
const { Frontend } = require('./frontend');
|
|
20
20
|
const { CacheManager } = require('./cache/cache-manager');
|
|
21
|
+
const { TemplateReloader } = require('./template-reloader');
|
|
21
22
|
const { EventsManagerSingleton, Logger, sc } = require('@reldens/utils');
|
|
22
23
|
const { DriversMap } = require('@reldens/storage');
|
|
23
24
|
const { AppServerFactory, FileHandler, Encryptor } = require('@reldens/server-utils');
|
|
@@ -34,6 +35,7 @@ class Manager
|
|
|
34
35
|
this.installLockPath = FileHandler.joinPaths(this.projectRoot, 'install.lock');
|
|
35
36
|
dotenv.config({path: this.envFilePath});
|
|
36
37
|
this.config = this.loadConfigFromEnv();
|
|
38
|
+
this.adminTranslations = sc.get(props, 'adminTranslations', {});
|
|
37
39
|
this.adminEntities = sc.get(props, 'adminEntities', {});
|
|
38
40
|
this.rawRegisteredEntities = sc.get(props, 'rawRegisteredEntities', {});
|
|
39
41
|
this.entitiesTranslations = sc.get(props, 'entitiesTranslations', {});
|
|
@@ -60,6 +62,7 @@ class Manager
|
|
|
60
62
|
this.siteKeyMapping = sc.get(props, 'siteKeyMapping', sc.toJson(process.env.RELDENS_SITE_KEY_MAPPING));
|
|
61
63
|
this.templateExtensions = sc.get(props, 'templateExtensions', ['.html', '.template']);
|
|
62
64
|
this.cache = sc.get(props, 'cache', false);
|
|
65
|
+
this.reloadTime = sc.get(props, 'reloadTime', 0);
|
|
63
66
|
this.app = sc.get(props, 'app', false);
|
|
64
67
|
this.appServer = sc.get(props, 'appServer', false);
|
|
65
68
|
this.dataServer = sc.get(props, 'dataServer', false);
|
|
@@ -67,14 +70,8 @@ class Manager
|
|
|
67
70
|
this.frontend = sc.get(props, 'frontend', false);
|
|
68
71
|
this.renderEngine = sc.get(props, 'renderEngine', mustache);
|
|
69
72
|
this.prismaClient = sc.get(props, 'prismaClient', false);
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
'127.0.0.1',
|
|
73
|
-
'.local',
|
|
74
|
-
'.test',
|
|
75
|
-
'.dev',
|
|
76
|
-
'.staging'
|
|
77
|
-
]);
|
|
73
|
+
this.defaultDevelopmentPatterns = ['localhost', '127.0.0.1', '.local', '.test', '.dev'];
|
|
74
|
+
this.developmentPatterns = sc.get(props, 'developmentPatterns', this.defaultDevelopmentPatterns);
|
|
78
75
|
this.developmentEnvironments = sc.get(props, 'developmentEnvironments', ['development', 'dev', 'test']);
|
|
79
76
|
this.developmentPorts = sc.get(props, 'developmentPorts', [3000, 8080, 8081]);
|
|
80
77
|
this.developmentMultiplier = sc.get(props, 'developmentMultiplier', 10);
|
|
@@ -83,6 +80,14 @@ class Manager
|
|
|
83
80
|
this.appServerFactory = new AppServerFactory();
|
|
84
81
|
this.adminEntitiesGenerator = new AdminEntitiesGenerator();
|
|
85
82
|
this.cacheManager = new CacheManager({projectRoot: this.projectRoot, enabled: this.cache});
|
|
83
|
+
this.templateReloader = new TemplateReloader({
|
|
84
|
+
reloadTime: this.reloadTime,
|
|
85
|
+
events: this.events,
|
|
86
|
+
adminTemplatesLoader: AdminTemplatesLoader,
|
|
87
|
+
mappedAdminTemplates: this.mappedAdminTemplates,
|
|
88
|
+
templatesPath: FileHandler.joinPaths(this.projectRoot, 'templates'),
|
|
89
|
+
templateExtensions: this.templateExtensions
|
|
90
|
+
});
|
|
86
91
|
this.installer = new Installer({
|
|
87
92
|
projectRoot: this.projectRoot,
|
|
88
93
|
prismaClient: this.prismaClient,
|
|
@@ -411,8 +416,12 @@ class Manager
|
|
|
411
416
|
return passwordResult;
|
|
412
417
|
};
|
|
413
418
|
}
|
|
419
|
+
this.templateReloader.trackTemplateFiles(this.mappedAdminTemplates);
|
|
414
420
|
let adminFilesContents = await AdminTemplatesLoader.fetchAdminFilesContents(this.mappedAdminTemplates);
|
|
415
|
-
let translations =
|
|
421
|
+
let translations = sc.deepMergeProperties(
|
|
422
|
+
sc.deepMergeProperties({}, DefaultTranslations),
|
|
423
|
+
sc.deepMergeProperties(this.entitiesTranslations, this.adminTranslations)
|
|
424
|
+
);
|
|
416
425
|
this.events.emit('reldens.manager.initializeAdminManager', {
|
|
417
426
|
manager: this,
|
|
418
427
|
authenticationCallback,
|
|
@@ -430,7 +439,7 @@ class Manager
|
|
|
430
439
|
renderCallback: this.renderCallback.bind(this),
|
|
431
440
|
secret: this.config.adminSecret,
|
|
432
441
|
rootPath: this.config.adminPath,
|
|
433
|
-
translations
|
|
442
|
+
translations,
|
|
434
443
|
adminFilesContents,
|
|
435
444
|
mimeTypes: this.mimeTypes,
|
|
436
445
|
allowedExtensions: this.allowedExtensions,
|
|
@@ -448,6 +457,9 @@ class Manager
|
|
|
448
457
|
}
|
|
449
458
|
};
|
|
450
459
|
this.adminManager = new AdminManager(adminConfig);
|
|
460
|
+
this.adminManager.router.checkAndReloadAdminTemplates = async () => {
|
|
461
|
+
return await this.templateReloader.handleAdminTemplateReload(this.adminManager);
|
|
462
|
+
};
|
|
451
463
|
await this.adminManager.setupAdmin();
|
|
452
464
|
return true;
|
|
453
465
|
}
|
|
@@ -485,7 +497,8 @@ class Manager
|
|
|
485
497
|
siteKeyMapping: this.siteKeyMapping,
|
|
486
498
|
templateExtensions: this.templateExtensions,
|
|
487
499
|
entitiesConfig: this.entitiesConfig,
|
|
488
|
-
cacheManager: this.cacheManager
|
|
500
|
+
cacheManager: this.cacheManager,
|
|
501
|
+
handleFrontendTemplateReload: this.templateReloader.handleFrontendTemplateReload.bind(this.templateReloader)
|
|
489
502
|
});
|
|
490
503
|
return await this.frontend.initialize();
|
|
491
504
|
}
|
package/lib/search-renderer.js
CHANGED
|
@@ -35,8 +35,9 @@ class SearchRenderer
|
|
|
35
35
|
Logger.error('Search result partial template not found: ' + partialName);
|
|
36
36
|
continue;
|
|
37
37
|
}
|
|
38
|
+
let templateData = sc.get(config, 'render.templateData', {});
|
|
38
39
|
if(sc.hasOwn(entityResult, 'pagination')){
|
|
39
|
-
let entityContent = await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain);
|
|
40
|
+
let entityContent = await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain, templateData);
|
|
40
41
|
let totalPages = sc.get(entityResult.pagination, 'totalPages', 1);
|
|
41
42
|
if(1 < totalPages){
|
|
42
43
|
let paginationContainer = sc.get(config, 'render.paginationContainer', 'pagedCollection');
|
|
@@ -46,22 +47,30 @@ class SearchRenderer
|
|
|
46
47
|
hasResults: 0 < entityResult.results.length,
|
|
47
48
|
noResultsMessage: entityResult.noResultsMessage || 'No results found.'
|
|
48
49
|
});
|
|
49
|
-
renderedContent += this.renderEngine.render(
|
|
50
|
+
renderedContent += this.renderEngine.render(
|
|
51
|
+
paginationTemplate,
|
|
52
|
+
paginationData,
|
|
53
|
+
this.getPartialsForDomain(domain)
|
|
54
|
+
);
|
|
50
55
|
continue;
|
|
51
56
|
}
|
|
52
57
|
renderedContent += entityContent;
|
|
53
58
|
continue;
|
|
54
59
|
}
|
|
55
|
-
renderedContent += await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain);
|
|
60
|
+
renderedContent += await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain, templateData);
|
|
56
61
|
}
|
|
57
62
|
return renderedContent;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
async renderSearchEntityResults(results, partialTemplate, domain)
|
|
65
|
+
async renderSearchEntityResults(results, partialTemplate, domain, templateData = {})
|
|
61
66
|
{
|
|
62
67
|
let renderedContent = '';
|
|
68
|
+
if(!sc.hasOwn(templateData, 'columnsClass') || '' === templateData.columnsClass){
|
|
69
|
+
templateData.columnsClass = 'col-lg-6';
|
|
70
|
+
}
|
|
63
71
|
for(let row of results){
|
|
64
|
-
|
|
72
|
+
let rowData = Object.assign({}, templateData, {row});
|
|
73
|
+
renderedContent += this.renderEngine.render(partialTemplate, rowData, this.getPartialsForDomain(domain));
|
|
65
74
|
}
|
|
66
75
|
return renderedContent;
|
|
67
76
|
}
|
|
@@ -85,8 +94,7 @@ class SearchRenderer
|
|
|
85
94
|
|
|
86
95
|
loadPartialTemplate(partialName, domain)
|
|
87
96
|
{
|
|
88
|
-
|
|
89
|
-
return sc.get(partials, partialName, false);
|
|
97
|
+
return sc.get(this.getPartialsForDomain(domain), partialName, false);
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
loadPaginationTemplate(containerName, domain)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - SearchRequestHandler
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class SearchRequestHandler
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor(props)
|
|
13
|
+
{
|
|
14
|
+
this.search = sc.get(props, 'search', false);
|
|
15
|
+
this.searchRenderer = sc.get(props, 'searchRenderer', false);
|
|
16
|
+
this.contentRenderer = sc.get(props, 'contentRenderer', false);
|
|
17
|
+
this.requestProcessor = sc.get(props, 'requestProcessor', false);
|
|
18
|
+
this.cacheManager = sc.get(props, 'cacheManager', false);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async handleSearchRequest(req, res)
|
|
22
|
+
{
|
|
23
|
+
try {
|
|
24
|
+
let domain = this.requestProcessor.getDomainFromRequest(req);
|
|
25
|
+
let config = this.search.parseSearchParameters(req.query);
|
|
26
|
+
if(!config){
|
|
27
|
+
return res.redirect('/?error-message=searchInvalidParameters');
|
|
28
|
+
}
|
|
29
|
+
let cacheKey = this.requestProcessor.buildCacheKey(req.path, req);
|
|
30
|
+
if(this.cacheManager && this.cacheManager.isEnabled()){
|
|
31
|
+
let cachedContent = await this.cacheManager.get(domain, cacheKey);
|
|
32
|
+
if(cachedContent){
|
|
33
|
+
return res.send(cachedContent);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
let searchResults = await this.search.executeSearch(config);
|
|
37
|
+
if(false === searchResults){
|
|
38
|
+
return res.redirect('/?error-message=searchExecutionFailed');
|
|
39
|
+
}
|
|
40
|
+
let content = await this.contentRenderer.renderWithTemplateContent(
|
|
41
|
+
{
|
|
42
|
+
template: config.render.page,
|
|
43
|
+
layout: config.render.layout,
|
|
44
|
+
content: await this.searchRenderer.renderSearchResults(searchResults, config, domain, req)
|
|
45
|
+
},
|
|
46
|
+
Object.assign({}, {
|
|
47
|
+
search_query: sc.get(req.query, 'search', ''),
|
|
48
|
+
searchConfig: config,
|
|
49
|
+
query: req.query
|
|
50
|
+
}),
|
|
51
|
+
domain,
|
|
52
|
+
req,
|
|
53
|
+
null
|
|
54
|
+
);
|
|
55
|
+
if(this.cacheManager && this.cacheManager.isEnabled()){
|
|
56
|
+
await this.cacheManager.set(domain, cacheKey, content);
|
|
57
|
+
}
|
|
58
|
+
return res.send(content);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
Logger.error('Search request handling error: ' + error.message);
|
|
61
|
+
return res.redirect('/?error-message=searchError');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports.SearchRequestHandler = SearchRequestHandler;
|
package/lib/search.js
CHANGED
|
@@ -38,7 +38,8 @@ class Search
|
|
|
38
38
|
page: 'page',
|
|
39
39
|
layout: 'search',
|
|
40
40
|
paginationContainer: 'pagedCollection',
|
|
41
|
-
partial: 'entriesListView'
|
|
41
|
+
partial: 'entriesListView',
|
|
42
|
+
templateData: {}
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -184,6 +185,17 @@ class Search
|
|
|
184
185
|
if(partial){
|
|
185
186
|
config.render.partial = partial;
|
|
186
187
|
}
|
|
188
|
+
for(let key of Object.keys(query)){
|
|
189
|
+
if(!key.startsWith('templateData[')){
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
let templateMatch = key.match(/templateData\[([^\]]+)\]/);
|
|
193
|
+
if(!templateMatch){
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
let templateKey = templateMatch[1];
|
|
197
|
+
config.render.templateData[templateKey] = query[key];
|
|
198
|
+
}
|
|
187
199
|
return config;
|
|
188
200
|
}
|
|
189
201
|
|
|
@@ -25,7 +25,7 @@ class CollectionsSingleTransformer extends CollectionsTransformerBase
|
|
|
25
25
|
return /<collection\s+([^>]+)\/>/g;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
async transform(template, domain, req, systemVariables)
|
|
28
|
+
async transform(template, domain, req, systemVariables, enhancedData = {})
|
|
29
29
|
{
|
|
30
30
|
let processedTemplate = template;
|
|
31
31
|
for(let match of template.matchAll(this.getSingleFieldCollectionRegex())){
|
|
@@ -45,21 +45,27 @@ class CollectionsSingleTransformer extends CollectionsTransformerBase
|
|
|
45
45
|
fieldName,
|
|
46
46
|
domain,
|
|
47
47
|
req,
|
|
48
|
-
systemVariables
|
|
48
|
+
systemVariables,
|
|
49
|
+
enhancedData
|
|
49
50
|
)
|
|
50
51
|
);
|
|
51
52
|
}
|
|
52
53
|
return processedTemplate;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
async extractFieldValues(collectionData, fieldName, domain, req, systemVariables)
|
|
56
|
+
async extractFieldValues(collectionData, fieldName, domain, req, systemVariables, enhancedData)
|
|
56
57
|
{
|
|
57
58
|
let fieldValues = '';
|
|
58
59
|
for(let row of collectionData){
|
|
59
60
|
let fieldValue = sc.get(row, fieldName, '');
|
|
60
|
-
if(fieldValue
|
|
61
|
-
|
|
61
|
+
if(!fieldValue){
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if(!this.processAllTemplateFunctions){
|
|
65
|
+
fieldValues += fieldValue;
|
|
66
|
+
continue;
|
|
62
67
|
}
|
|
68
|
+
fieldValue = await this.processAllTemplateFunctions(fieldValue, domain, req, systemVariables, enhancedData);
|
|
63
69
|
fieldValues += fieldValue;
|
|
64
70
|
}
|
|
65
71
|
return fieldValues;
|
|
@@ -32,7 +32,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
32
32
|
return new RegExp('<\\/collection>');
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
async transform(template, domain, req, systemVariables)
|
|
35
|
+
async transform(template, domain, req, systemVariables, enhancedData = {})
|
|
36
36
|
{
|
|
37
37
|
let processedTemplate = template;
|
|
38
38
|
let matches = [...template.matchAll(this.getLoopCollectionStartRegex())];
|
|
@@ -64,7 +64,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
64
64
|
nextPages,
|
|
65
65
|
domain,
|
|
66
66
|
req,
|
|
67
|
-
systemVariables
|
|
67
|
+
systemVariables,
|
|
68
|
+
enhancedData
|
|
68
69
|
);
|
|
69
70
|
if(loopResult){
|
|
70
71
|
processedTemplate = loopResult;
|
|
@@ -80,7 +81,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
80
81
|
queryOptionsJson,
|
|
81
82
|
domain,
|
|
82
83
|
req,
|
|
83
|
-
systemVariables
|
|
84
|
+
systemVariables,
|
|
85
|
+
enhancedData
|
|
84
86
|
);
|
|
85
87
|
if(loopResult){
|
|
86
88
|
processedTemplate = loopResult;
|
|
@@ -98,7 +100,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
98
100
|
queryOptionsJson,
|
|
99
101
|
domain,
|
|
100
102
|
req,
|
|
101
|
-
systemVariables
|
|
103
|
+
systemVariables,
|
|
104
|
+
enhancedData
|
|
102
105
|
){
|
|
103
106
|
return await this.processCollectionBase(
|
|
104
107
|
template,
|
|
@@ -110,7 +113,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
110
113
|
domain,
|
|
111
114
|
false,
|
|
112
115
|
req,
|
|
113
|
-
systemVariables
|
|
116
|
+
systemVariables,
|
|
117
|
+
enhancedData
|
|
114
118
|
);
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -127,7 +131,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
127
131
|
nextPages,
|
|
128
132
|
domain,
|
|
129
133
|
req,
|
|
130
|
-
systemVariables
|
|
134
|
+
systemVariables,
|
|
135
|
+
enhancedData
|
|
131
136
|
){
|
|
132
137
|
if(!req){
|
|
133
138
|
Logger.warning('No request provided for pagination, falling back to regular collection');
|
|
@@ -140,7 +145,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
140
145
|
queryOptionsJson,
|
|
141
146
|
domain,
|
|
142
147
|
req,
|
|
143
|
-
systemVariables
|
|
148
|
+
systemVariables,
|
|
149
|
+
enhancedData
|
|
144
150
|
);
|
|
145
151
|
}
|
|
146
152
|
return await this.processCollectionBase(
|
|
@@ -159,7 +165,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
159
165
|
req
|
|
160
166
|
},
|
|
161
167
|
req,
|
|
162
|
-
systemVariables
|
|
168
|
+
systemVariables,
|
|
169
|
+
enhancedData
|
|
163
170
|
);
|
|
164
171
|
}
|
|
165
172
|
|
|
@@ -173,7 +180,8 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
173
180
|
domain,
|
|
174
181
|
paginationOptions,
|
|
175
182
|
req,
|
|
176
|
-
systemVariables
|
|
183
|
+
systemVariables,
|
|
184
|
+
enhancedData
|
|
177
185
|
){
|
|
178
186
|
let startPos = startMatch.index;
|
|
179
187
|
let startEnd = startPos + startMatch[0].length;
|
|
@@ -226,13 +234,14 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
226
234
|
this.jsonFieldsParser.getJsonFieldsForEntity(tableName)
|
|
227
235
|
);
|
|
228
236
|
}
|
|
229
|
-
let collectionContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables);
|
|
237
|
+
let collectionContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables, enhancedData);
|
|
230
238
|
finalContent = this.renderEngine.render(
|
|
231
239
|
1 < paginationData.totalPages
|
|
232
240
|
? this.loadPaginationTemplate(paginationOptions.containerName, domain)
|
|
233
241
|
: '{{&collectionContentForCurrentPage}}',
|
|
234
242
|
Object.assign(
|
|
235
243
|
{},
|
|
244
|
+
enhancedData,
|
|
236
245
|
paginationData,
|
|
237
246
|
{
|
|
238
247
|
collectionContentForCurrentPage: collectionContent,
|
|
@@ -250,7 +259,7 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
250
259
|
queryOptionsJson,
|
|
251
260
|
relationsString
|
|
252
261
|
);
|
|
253
|
-
finalContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables);
|
|
262
|
+
finalContent = await this.renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables, enhancedData);
|
|
254
263
|
}
|
|
255
264
|
return template.substring(0, startPos) + finalContent + template.substring(endPos + endMatch[0].length);
|
|
256
265
|
}
|
|
@@ -296,36 +305,40 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
296
305
|
return '{{&collectionContentForCurrentPage}}';
|
|
297
306
|
}
|
|
298
307
|
|
|
299
|
-
async renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables)
|
|
308
|
+
async renderCollectionLoop(loopContent, collectionData, domain, req, systemVariables, enhancedData)
|
|
300
309
|
{
|
|
301
310
|
if(!collectionData || 0 === collectionData.length){
|
|
302
|
-
return this.renderNoResultsMessage(domain);
|
|
311
|
+
return this.renderNoResultsMessage(domain, enhancedData);
|
|
303
312
|
}
|
|
304
313
|
let renderedContent = '';
|
|
305
314
|
for(let row of collectionData){
|
|
306
|
-
renderedContent += await this.processPartialsInLoop(loopContent, row, domain, req, systemVariables);
|
|
315
|
+
renderedContent += await this.processPartialsInLoop(loopContent, row, domain, req, systemVariables, enhancedData);
|
|
307
316
|
}
|
|
308
317
|
return renderedContent;
|
|
309
318
|
}
|
|
310
319
|
|
|
311
|
-
renderNoResultsMessage(domain)
|
|
320
|
+
renderNoResultsMessage(domain, enhancedData)
|
|
312
321
|
{
|
|
313
322
|
let noResultsTemplate = this.loadPartialTemplate('noResults', domain);
|
|
314
323
|
if(noResultsTemplate){
|
|
315
324
|
return this.renderEngine.render(
|
|
316
325
|
noResultsTemplate,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
326
|
+
Object.assign(
|
|
327
|
+
{},
|
|
328
|
+
enhancedData,
|
|
329
|
+
{
|
|
330
|
+
message: 'No results found.',
|
|
331
|
+
cssClass: 'no-results',
|
|
332
|
+
alertClass: 'alert-info'
|
|
333
|
+
}
|
|
334
|
+
),
|
|
322
335
|
this.getPartials(domain)
|
|
323
336
|
);
|
|
324
337
|
}
|
|
325
338
|
return '';
|
|
326
339
|
}
|
|
327
340
|
|
|
328
|
-
async processPartialsInLoop(content, rowData, domain, req, systemVariables)
|
|
341
|
+
async processPartialsInLoop(content, rowData, domain, req, systemVariables, enhancedData)
|
|
329
342
|
{
|
|
330
343
|
let processedContent = content;
|
|
331
344
|
let partialTags = this.findAllPartialTags(content);
|
|
@@ -338,25 +351,25 @@ class CollectionsTransformer extends CollectionsTransformerBase
|
|
|
338
351
|
continue;
|
|
339
352
|
}
|
|
340
353
|
if(this.processAllTemplateFunctions){
|
|
341
|
-
partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables);
|
|
354
|
+
partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables, enhancedData);
|
|
342
355
|
}
|
|
356
|
+
let renderData = Object.assign({}, enhancedData);
|
|
343
357
|
if(sc.hasOwn(tag.attributes, 'row')){
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
358
|
+
renderData.row = rowData;
|
|
359
|
+
}
|
|
360
|
+
for(let key of Object.keys(tag.attributes)){
|
|
361
|
+
if('row' !== key){
|
|
362
|
+
renderData[key] = tag.attributes[key];
|
|
363
|
+
}
|
|
348
364
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
processedContent = processedContent.substring(0, tag.start) +
|
|
353
|
-
this.renderEngine.render(wrapperTemplate, renderData, partials) +
|
|
354
|
-
processedContent.substring(tag.end);
|
|
365
|
+
processedContent = processedContent.substring(0, tag.start)
|
|
366
|
+
+this.renderEngine.render(partialContent, renderData, this.getPartials(domain))
|
|
367
|
+
+processedContent.substring(tag.end);
|
|
355
368
|
}
|
|
356
369
|
if(this.processAllTemplateFunctions){
|
|
357
|
-
processedContent = await this.processAllTemplateFunctions(processedContent, domain, req, systemVariables);
|
|
370
|
+
processedContent = await this.processAllTemplateFunctions(processedContent, domain, req, systemVariables, enhancedData);
|
|
358
371
|
}
|
|
359
|
-
return this.renderEngine.render(processedContent, {row: rowData}, this.getPartials(domain));
|
|
372
|
+
return this.renderEngine.render(processedContent, Object.assign({}, enhancedData, {row: rowData}), this.getPartials(domain));
|
|
360
373
|
}
|
|
361
374
|
|
|
362
375
|
getCurrentUrl(req)
|
|
@@ -21,7 +21,7 @@ class EntitiesTransformer
|
|
|
21
21
|
return /<entity\s+name="([^"]+)"(?:\s+field="([^"]+)"\s+value="([^"]+)"|\s+id="([^"]+)")?\s*\/?>/g;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
async transform(template, domain, req, systemVariables)
|
|
24
|
+
async transform(template, domain, req, systemVariables, enhancedData = {})
|
|
25
25
|
{
|
|
26
26
|
let processedTemplate = template;
|
|
27
27
|
for(let match of template.matchAll(this.getEntityRegex())){
|
|
@@ -38,7 +38,8 @@ class EntitiesTransformer
|
|
|
38
38
|
sc.get(await this.fetchEntityForTemplate(tableName, value, field), 'content', ''),
|
|
39
39
|
domain,
|
|
40
40
|
req,
|
|
41
|
-
systemVariables
|
|
41
|
+
systemVariables,
|
|
42
|
+
enhancedData
|
|
42
43
|
)
|
|
43
44
|
);
|
|
44
45
|
}
|
|
@@ -16,7 +16,7 @@ class PartialsTransformer
|
|
|
16
16
|
this.processAllTemplateFunctions = sc.get(props, 'processAllTemplateFunctions', false);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
async transform(template, domain, req, systemVariables)
|
|
19
|
+
async transform(template, domain, req, systemVariables, enhancedData = {})
|
|
20
20
|
{
|
|
21
21
|
let processedTemplate = template;
|
|
22
22
|
let partialTags = this.findAllPartialTags(template);
|
|
@@ -29,13 +29,12 @@ class PartialsTransformer
|
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
if(this.processAllTemplateFunctions){
|
|
32
|
-
partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables);
|
|
32
|
+
partialContent = await this.processAllTemplateFunctions(partialContent, domain, req, systemVariables, enhancedData);
|
|
33
33
|
}
|
|
34
|
-
let
|
|
35
|
-
let
|
|
36
|
-
let partials = {[tag.name]: partialContent};
|
|
34
|
+
let partialData = Object.assign({}, enhancedData, tag.attributes);
|
|
35
|
+
let renderedPartial = this.renderEngine.render(partialContent, partialData, {});
|
|
37
36
|
processedTemplate = processedTemplate.substring(0, tag.start) +
|
|
38
|
-
|
|
37
|
+
renderedPartial +
|
|
39
38
|
processedTemplate.substring(tag.end);
|
|
40
39
|
}
|
|
41
40
|
return processedTemplate;
|
|
@@ -89,6 +89,7 @@ class SystemVariablesProvider
|
|
|
89
89
|
|
|
90
90
|
buildSystemInfo()
|
|
91
91
|
{
|
|
92
|
+
let date = new Date();
|
|
92
93
|
return {
|
|
93
94
|
projectRoot: this.projectRoot,
|
|
94
95
|
publicPath: this.publicPath,
|
|
@@ -96,7 +97,9 @@ class SystemVariablesProvider
|
|
|
96
97
|
platform: process.platform,
|
|
97
98
|
environment: process.env.NODE_ENV || 'development',
|
|
98
99
|
timestamp: sc.getCurrentDate(),
|
|
99
|
-
uptime: process.uptime()
|
|
100
|
+
uptime: process.uptime(),
|
|
101
|
+
currentDate: sc.formatDate(date),
|
|
102
|
+
currentYear: sc.formatDate(date, 'Y')
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
105
|
|
package/lib/template-engine.js
CHANGED
|
@@ -59,7 +59,8 @@ class TemplateEngine
|
|
|
59
59
|
});
|
|
60
60
|
this.partialsTransformer = new PartialsTransformer({
|
|
61
61
|
renderEngine: this.renderEngine,
|
|
62
|
-
getPartials: this.getPartials
|
|
62
|
+
getPartials: this.getPartials,
|
|
63
|
+
processAllTemplateFunctions: this.processAllTemplateFunctions.bind(this)
|
|
63
64
|
});
|
|
64
65
|
this.urlTransformer = new UrlTransformer();
|
|
65
66
|
this.assetTransformer = new AssetTransformer();
|
|
@@ -83,13 +84,17 @@ class TemplateEngine
|
|
|
83
84
|
];
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
async processAllTemplateFunctions(template, domain, req, systemVariables)
|
|
87
|
+
async processAllTemplateFunctions(template, domain, req, systemVariables, enhancedData = {})
|
|
87
88
|
{
|
|
88
89
|
let processedTemplate = template;
|
|
89
90
|
for(let transformer of this.transformers){
|
|
90
|
-
if(
|
|
91
|
-
|
|
91
|
+
if(!transformer){
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if(!sc.isFunction(transformer.transform)){
|
|
95
|
+
continue;
|
|
92
96
|
}
|
|
97
|
+
processedTemplate = await transformer.transform(processedTemplate, domain, req, systemVariables, enhancedData);
|
|
93
98
|
}
|
|
94
99
|
return processedTemplate;
|
|
95
100
|
}
|
|
@@ -134,7 +139,8 @@ class TemplateEngine
|
|
|
134
139
|
beforeProcessData.content,
|
|
135
140
|
domain,
|
|
136
141
|
req,
|
|
137
|
-
eventData.variables
|
|
142
|
+
eventData.variables,
|
|
143
|
+
enhancedData
|
|
138
144
|
);
|
|
139
145
|
let afterProcessData = {
|
|
140
146
|
processedContent: processedTemplate,
|