@reldens/cms 0.18.0 → 0.20.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 +260 -20
- package/admin/reldens-admin-client.css +127 -80
- package/admin/reldens-admin-client.js +24 -0
- package/admin/templates/clear-all-cache-button.html +18 -0
- package/lib/admin-manager/contents-builder.js +7 -6
- package/lib/admin-manager/router-contents.js +58 -16
- package/lib/admin-manager-validator.js +2 -1
- package/lib/admin-manager.js +4 -2
- package/lib/admin-translations.js +9 -1
- package/lib/cache/add-cache-button-subscriber.js +53 -5
- package/lib/cache/cache-manager.js +47 -8
- package/lib/cache/cache-routes-handler.js +23 -0
- package/lib/cms-pages-route-manager.js +16 -4
- package/lib/frontend.js +310 -119
- package/lib/manager.js +43 -3
- package/lib/pagination-handler.js +243 -0
- package/lib/search-renderer.js +116 -0
- package/lib/search.js +344 -0
- package/lib/template-engine/asset-transformer.js +41 -0
- package/lib/template-engine/collections-single-transformer.js +70 -0
- package/lib/template-engine/collections-transformer-base.js +84 -0
- package/lib/template-engine/collections-transformer.js +374 -0
- package/lib/template-engine/date-transformer.js +53 -0
- package/lib/template-engine/entities-transformer.js +67 -0
- package/lib/template-engine/partials-transformer.js +175 -0
- package/lib/template-engine/system-variables-provider.js +105 -0
- package/lib/template-engine/translate-transformer.js +98 -0
- package/lib/template-engine/translation-service.js +104 -0
- package/lib/template-engine/url-transformer.js +41 -0
- package/lib/template-engine.js +133 -438
- package/lib/templates-list.js +1 -0
- package/migrations/install.sql +18 -18
- package/package.json +4 -4
- package/templates/page.html +19 -2
- package/templates/partials/entriesListView.html +14 -0
- package/templates/partials/pagedCollection.html +33 -0
package/lib/manager.js
CHANGED
|
@@ -47,7 +47,7 @@ class Manager
|
|
|
47
47
|
this.projectAdminPath = FileHandler.joinPaths(this.projectRoot, 'admin');
|
|
48
48
|
this.projectAdminTemplatesPath = FileHandler.joinPaths(this.projectAdminPath, 'templates');
|
|
49
49
|
this.mimeTypes = sc.get(props, 'mimeTypes', MimeTypes);
|
|
50
|
-
this.allowedExtensions = sc.get(props, 'allowedExtensions', AllowedExtensions)
|
|
50
|
+
this.allowedExtensions = sc.get(props, 'allowedExtensions', AllowedExtensions);
|
|
51
51
|
this.adminRoleId = sc.get(props, 'adminRoleId', 99);
|
|
52
52
|
this.mappedAdminTemplates = TemplatesToPathMapper.map(this.adminTemplatesList, this.projectAdminTemplatesPath);
|
|
53
53
|
this.stylesFilePath = sc.get(props, 'stylesFilePath', '/css/reldens-admin-client.css');
|
|
@@ -67,6 +67,19 @@ class Manager
|
|
|
67
67
|
this.frontend = sc.get(props, 'frontend', false);
|
|
68
68
|
this.renderEngine = sc.get(props, 'renderEngine', mustache);
|
|
69
69
|
this.prismaClient = sc.get(props, 'prismaClient', false);
|
|
70
|
+
this.developmentPatterns = sc.get(props, 'developmentPatterns', [
|
|
71
|
+
'localhost',
|
|
72
|
+
'127.0.0.1',
|
|
73
|
+
'.local',
|
|
74
|
+
'.test',
|
|
75
|
+
'.dev',
|
|
76
|
+
'.staging'
|
|
77
|
+
]);
|
|
78
|
+
this.developmentEnvironments = sc.get(props, 'developmentEnvironments', ['development', 'dev', 'test']);
|
|
79
|
+
this.developmentPorts = sc.get(props, 'developmentPorts', [3000, 8080, 8081]);
|
|
80
|
+
this.developmentMultiplier = sc.get(props, 'developmentMultiplier', 10);
|
|
81
|
+
this.appServerConfig = sc.get(props, 'appServerConfig', {});
|
|
82
|
+
this.developmentExternalDomains = sc.get(props, 'developmentExternalDomains', {});
|
|
70
83
|
this.appServerFactory = new AppServerFactory();
|
|
71
84
|
this.adminEntitiesGenerator = new AdminEntitiesGenerator();
|
|
72
85
|
this.cacheManager = new CacheManager({projectRoot: this.projectRoot, enabled: this.cache});
|
|
@@ -172,7 +185,8 @@ class Manager
|
|
|
172
185
|
async start()
|
|
173
186
|
{
|
|
174
187
|
if(!this.useProvidedServer){
|
|
175
|
-
let
|
|
188
|
+
let appServerConfig = this.buildAppServerConfiguration();
|
|
189
|
+
let createdAppServer = this.appServerFactory.createAppServer(appServerConfig);
|
|
176
190
|
if(this.appServerFactory.error.message){
|
|
177
191
|
Logger.error('App server error: '+this.appServerFactory.error.message);
|
|
178
192
|
return false;
|
|
@@ -199,6 +213,30 @@ class Manager
|
|
|
199
213
|
}
|
|
200
214
|
}
|
|
201
215
|
|
|
216
|
+
buildAppServerConfiguration()
|
|
217
|
+
{
|
|
218
|
+
let baseConfig = {
|
|
219
|
+
port: this.config.port,
|
|
220
|
+
useHttps: this.config.host.startsWith('https://'),
|
|
221
|
+
domainMapping: this.domainMapping || {},
|
|
222
|
+
defaultDomain: this.defaultDomain,
|
|
223
|
+
developmentPatterns: this.developmentPatterns,
|
|
224
|
+
developmentEnvironments: this.developmentEnvironments,
|
|
225
|
+
developmentPorts: this.developmentPorts,
|
|
226
|
+
developmentMultiplier: this.developmentMultiplier,
|
|
227
|
+
developmentExternalDomains: this.developmentExternalDomains
|
|
228
|
+
};
|
|
229
|
+
let appServerConfig = Object.assign({}, baseConfig, this.appServerConfig);
|
|
230
|
+
if(this.domainMapping && 'object' === typeof this.domainMapping){
|
|
231
|
+
let mappingKeys = Object.keys(this.domainMapping);
|
|
232
|
+
for(let domain of mappingKeys){
|
|
233
|
+
this.appServerFactory.addDevelopmentDomain(domain);
|
|
234
|
+
}
|
|
235
|
+
this.appServerFactory.setDomainMapping(this.domainMapping);
|
|
236
|
+
}
|
|
237
|
+
return appServerConfig;
|
|
238
|
+
}
|
|
239
|
+
|
|
202
240
|
async initializeCmsAfterInstall(props)
|
|
203
241
|
{
|
|
204
242
|
try {
|
|
@@ -325,7 +363,8 @@ class Manager
|
|
|
325
363
|
user: this.config.database.user,
|
|
326
364
|
password: this.config.database.password
|
|
327
365
|
},
|
|
328
|
-
rawEntities: this.rawRegisteredEntities
|
|
366
|
+
rawEntities: this.rawRegisteredEntities,
|
|
367
|
+
entitiesConfig: this.entitiesConfig
|
|
329
368
|
};
|
|
330
369
|
let driverClass = DriversMap[this.config.database.driver];
|
|
331
370
|
if(!driverClass){
|
|
@@ -437,6 +476,7 @@ class Manager
|
|
|
437
476
|
this.frontend = new Frontend({
|
|
438
477
|
app: this.app,
|
|
439
478
|
dataServer: this.dataServer,
|
|
479
|
+
events: this.events,
|
|
440
480
|
renderEngine: this.renderEngine,
|
|
441
481
|
projectRoot: this.projectRoot,
|
|
442
482
|
appServerFactory: this.appServerFactory,
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - PaginationHandler
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class PaginationHandler
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor()
|
|
13
|
+
{
|
|
14
|
+
this.defaultLimit = 10;
|
|
15
|
+
this.prevPageLabel = 'Previous';
|
|
16
|
+
this.nextPageLabel = 'Next';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
sanitizeCollectionKey(collectionKey)
|
|
20
|
+
{
|
|
21
|
+
if(!collectionKey || 'object' !== typeof collectionKey){
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
let sanitizedKey = {};
|
|
25
|
+
let page = sc.parseNumber(sc.get(collectionKey, 'page', 0));
|
|
26
|
+
if(1 <= page){
|
|
27
|
+
sanitizedKey.page = page;
|
|
28
|
+
}
|
|
29
|
+
let limit = sc.parseNumber(sc.get(collectionKey, 'limit', 0));
|
|
30
|
+
if(0 < limit){
|
|
31
|
+
sanitizedKey.limit = limit;
|
|
32
|
+
}
|
|
33
|
+
let sortBy = sc.get(collectionKey, 'sortBy', '');
|
|
34
|
+
if(sc.isString(sortBy) && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(sortBy)){
|
|
35
|
+
sanitizedKey.sortBy = sortBy;
|
|
36
|
+
}
|
|
37
|
+
let sortDirection = sc.get(collectionKey, 'sortDirection');
|
|
38
|
+
if('asc' === sortDirection || 'desc' === sortDirection){
|
|
39
|
+
sanitizedKey.sortDirection = sortDirection;
|
|
40
|
+
}
|
|
41
|
+
let filters = sc.get(collectionKey, 'filters', false);
|
|
42
|
+
if('object' === typeof filters){
|
|
43
|
+
sanitizedKey.filters = this.sanitizeFilters(filters);
|
|
44
|
+
}
|
|
45
|
+
return sanitizedKey;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
sanitizeFilters(filters)
|
|
49
|
+
{
|
|
50
|
+
let sanitizedFilters = {};
|
|
51
|
+
for(let key of Object.keys(filters)){
|
|
52
|
+
if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)){
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
let value = filters[key];
|
|
56
|
+
if(sc.isString(value) || sc.isNumber(value) || sc.isBoolean(value)){
|
|
57
|
+
sanitizedFilters[key] = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return sanitizedFilters;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
extractCollectionKeyFromRequest(req, collectionId)
|
|
64
|
+
{
|
|
65
|
+
if(!req || !req.query){
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
let paramName = collectionId + '-key';
|
|
69
|
+
let paramValue = sc.get(req.query, paramName, '');
|
|
70
|
+
if(!paramValue){
|
|
71
|
+
return {};
|
|
72
|
+
}
|
|
73
|
+
let decodedValue = decodeURIComponent(paramValue);
|
|
74
|
+
let parsedKey = sc.parseJson(decodedValue, {});
|
|
75
|
+
if(!parsedKey){
|
|
76
|
+
Logger.warning('Invalid collection key JSON: ' + decodedValue);
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
return this.sanitizeCollectionKey(parsedKey);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
mergeCollectionParameters(templateParams, requestParams)
|
|
83
|
+
{
|
|
84
|
+
let templateFilters = sc.get(templateParams, 'filters', {});
|
|
85
|
+
let requestFilters = sc.get(requestParams, 'filters', {});
|
|
86
|
+
let mergedFilters = Object.assign({}, templateFilters, requestFilters);
|
|
87
|
+
return {
|
|
88
|
+
limit: sc.get(requestParams, 'limit', sc.get(templateParams, 'limit', this.defaultLimit)),
|
|
89
|
+
page: sc.get(requestParams, 'page', 1),
|
|
90
|
+
sortBy: sc.get(requestParams, 'sortBy', sc.get(templateParams, 'sortBy', 'id')),
|
|
91
|
+
sortDirection: sc.get(requestParams, 'sortDirection', sc.get(templateParams, 'sortDirection', 'asc')),
|
|
92
|
+
filters: mergedFilters
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
calculatePaginationData(totalRecords, currentPage, limit, baseUrl, collectionId, params, templateDefaults)
|
|
97
|
+
{
|
|
98
|
+
if(0 >= totalRecords){
|
|
99
|
+
return this.createEmptyPaginationData();
|
|
100
|
+
}
|
|
101
|
+
let totalPages = Math.ceil(totalRecords / limit);
|
|
102
|
+
if(currentPage > totalPages){
|
|
103
|
+
currentPage = totalPages;
|
|
104
|
+
}
|
|
105
|
+
let offset = (currentPage - 1) * limit;
|
|
106
|
+
let hasNextPage = currentPage < totalPages;
|
|
107
|
+
let hasPrevPage = 1 < currentPage;
|
|
108
|
+
let prevPageUrl = '';
|
|
109
|
+
let nextPageUrl = '';
|
|
110
|
+
if(hasPrevPage){
|
|
111
|
+
prevPageUrl = this.buildPageUrl(baseUrl, collectionId, params, currentPage - 1, templateDefaults);
|
|
112
|
+
}
|
|
113
|
+
if(hasNextPage){
|
|
114
|
+
nextPageUrl = this.buildPageUrl(baseUrl, collectionId, params, currentPage + 1, templateDefaults);
|
|
115
|
+
}
|
|
116
|
+
let prevPages = this.calculatePrevPages(currentPage, params, baseUrl, collectionId, templateDefaults);
|
|
117
|
+
let nextPages = this.calculateNextPages(
|
|
118
|
+
currentPage,
|
|
119
|
+
totalPages,
|
|
120
|
+
params,
|
|
121
|
+
baseUrl,
|
|
122
|
+
collectionId,
|
|
123
|
+
templateDefaults
|
|
124
|
+
);
|
|
125
|
+
return {
|
|
126
|
+
currentPage,
|
|
127
|
+
totalPages,
|
|
128
|
+
totalRecords,
|
|
129
|
+
limit,
|
|
130
|
+
offset,
|
|
131
|
+
hasNextPage,
|
|
132
|
+
hasPrevPage,
|
|
133
|
+
prevPageUrl,
|
|
134
|
+
nextPageUrl,
|
|
135
|
+
prevPageLabel: this.prevPageLabel,
|
|
136
|
+
nextPageLabel: this.nextPageLabel,
|
|
137
|
+
prevPages,
|
|
138
|
+
nextPages
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
createEmptyPaginationData()
|
|
143
|
+
{
|
|
144
|
+
return {
|
|
145
|
+
currentPage: 1,
|
|
146
|
+
totalPages: 0,
|
|
147
|
+
totalRecords: 0,
|
|
148
|
+
limit: this.defaultLimit,
|
|
149
|
+
offset: 0,
|
|
150
|
+
hasNextPage: false,
|
|
151
|
+
hasPrevPage: false,
|
|
152
|
+
prevPageUrl: '',
|
|
153
|
+
nextPageUrl: '',
|
|
154
|
+
prevPageLabel: this.prevPageLabel,
|
|
155
|
+
nextPageLabel: this.nextPageLabel,
|
|
156
|
+
prevPages: [],
|
|
157
|
+
nextPages: []
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
calculatePrevPages(currentPage, params, baseUrl, collectionId, templateDefaults)
|
|
162
|
+
{
|
|
163
|
+
let prevPagesCount = sc.parseNumber(sc.get(params, 'prevPages', 2));
|
|
164
|
+
if(!prevPagesCount || 0 >= prevPagesCount || 1 >= currentPage){
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
let prevPages = [];
|
|
168
|
+
let startPage = Math.max(1, currentPage - prevPagesCount);
|
|
169
|
+
for(let page = startPage; page < currentPage; page++){
|
|
170
|
+
prevPages.push({
|
|
171
|
+
pageLabel: page,
|
|
172
|
+
pageUrl: this.buildPageUrl(baseUrl, collectionId, params, page, templateDefaults)
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return prevPages;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
calculateNextPages(currentPage, totalPages, params, baseUrl, collectionId, templateDefaults)
|
|
179
|
+
{
|
|
180
|
+
let nextPagesCount = sc.parseNumber(sc.get(params, 'nextPages', 2));
|
|
181
|
+
if(!nextPagesCount || 0 >= nextPagesCount || currentPage >= totalPages){
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
let nextPages = [];
|
|
185
|
+
let endPage = Math.min(totalPages, currentPage + nextPagesCount);
|
|
186
|
+
for(let page = currentPage + 1; page <= endPage; page++){
|
|
187
|
+
nextPages.push({
|
|
188
|
+
pageLabel: page,
|
|
189
|
+
pageUrl: this.buildPageUrl(baseUrl, collectionId, params, page, templateDefaults)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return nextPages;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
buildPageUrl(baseUrl, collectionId, params, page, templateDefaults)
|
|
196
|
+
{
|
|
197
|
+
let urlParams = {};
|
|
198
|
+
urlParams.page = page;
|
|
199
|
+
let templateFilters = sc.get(templateDefaults, 'filters', {});
|
|
200
|
+
let templateLimit = sc.get(templateDefaults, 'limit', this.defaultLimit);
|
|
201
|
+
let templateSortBy = sc.get(templateDefaults, 'sortBy', 'id');
|
|
202
|
+
let templateSortDirection = sc.get(templateDefaults, 'sortDirection', 'asc');
|
|
203
|
+
let currentFilters = sc.get(params, 'filters', {});
|
|
204
|
+
for(let filterKey of Object.keys(currentFilters)){
|
|
205
|
+
if(!sc.hasOwn(templateFilters, filterKey) || templateFilters[filterKey] !== currentFilters[filterKey]){
|
|
206
|
+
if(!sc.hasOwn(urlParams, 'filters')){
|
|
207
|
+
urlParams.filters = {};
|
|
208
|
+
}
|
|
209
|
+
urlParams.filters[filterKey] = currentFilters[filterKey];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if(params.limit !== templateLimit){
|
|
213
|
+
urlParams.limit = params.limit;
|
|
214
|
+
}
|
|
215
|
+
if(params.sortBy !== templateSortBy){
|
|
216
|
+
urlParams.sortBy = params.sortBy;
|
|
217
|
+
}
|
|
218
|
+
if(params.sortDirection !== templateSortDirection){
|
|
219
|
+
urlParams.sortDirection = params.sortDirection;
|
|
220
|
+
}
|
|
221
|
+
let collectionKey = encodeURIComponent(JSON.stringify(urlParams));
|
|
222
|
+
let paramName = collectionId + '-key';
|
|
223
|
+
let separator = -1 !== baseUrl.indexOf('?') ? '&' : '?';
|
|
224
|
+
return baseUrl + separator + paramName + '=' + collectionKey;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async getCollectionTotal(entity, filters)
|
|
228
|
+
{
|
|
229
|
+
if(!entity || !sc.isFunction(entity.count)){
|
|
230
|
+
Logger.critical('Entity does not support count method');
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
return await entity.count(filters || {});
|
|
235
|
+
} catch (error) {
|
|
236
|
+
Logger.critical('Failed to count collection records: ' + error.message);
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
module.exports.PaginationHandler = PaginationHandler;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - CMS - SearchRenderer
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class SearchRenderer
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor(props)
|
|
13
|
+
{
|
|
14
|
+
this.renderEngine = sc.get(props, 'renderEngine', false);
|
|
15
|
+
this.getPartials = sc.get(props, 'getPartials', false);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async renderSearchResults(searchResults, config, domain, req)
|
|
19
|
+
{
|
|
20
|
+
if(!searchResults || !sc.isArray(searchResults) || 0 === searchResults.length){
|
|
21
|
+
return this.renderNoSearchResults(domain);
|
|
22
|
+
}
|
|
23
|
+
let renderedContent = '';
|
|
24
|
+
for(let entityResult of searchResults){
|
|
25
|
+
if(!sc.hasOwn(entityResult, 'results') || !sc.isArray(entityResult.results)){
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if(0 === entityResult.results.length){
|
|
29
|
+
renderedContent += this.renderNoSearchResults(domain);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
let partialName = sc.get(config, 'render.partial', 'entriesListView');
|
|
33
|
+
let partialTemplate = this.loadPartialTemplate(partialName, domain);
|
|
34
|
+
if(!partialTemplate){
|
|
35
|
+
Logger.error('Search result partial template not found: ' + partialName);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if(sc.hasOwn(entityResult, 'pagination')){
|
|
39
|
+
let entityContent = await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain);
|
|
40
|
+
let totalPages = sc.get(entityResult.pagination, 'totalPages', 1);
|
|
41
|
+
if(1 < totalPages){
|
|
42
|
+
let paginationContainer = sc.get(config, 'render.paginationContainer', 'pagedCollection');
|
|
43
|
+
let paginationTemplate = this.loadPaginationTemplate(paginationContainer, domain);
|
|
44
|
+
let paginationData = Object.assign({}, entityResult.pagination, {
|
|
45
|
+
collectionContentForCurrentPage: entityContent,
|
|
46
|
+
hasResults: 0 < entityResult.results.length,
|
|
47
|
+
noResultsMessage: entityResult.noResultsMessage || 'No results found.'
|
|
48
|
+
});
|
|
49
|
+
renderedContent += this.renderEngine.render(paginationTemplate, paginationData, this.getPartialsForDomain(domain));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
renderedContent += entityContent;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
renderedContent += await this.renderSearchEntityResults(entityResult.results, partialTemplate, domain);
|
|
56
|
+
}
|
|
57
|
+
return renderedContent;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async renderSearchEntityResults(results, partialTemplate, domain)
|
|
61
|
+
{
|
|
62
|
+
let renderedContent = '';
|
|
63
|
+
for(let row of results){
|
|
64
|
+
renderedContent += this.renderEngine.render(partialTemplate, {row}, this.getPartialsForDomain(domain));
|
|
65
|
+
}
|
|
66
|
+
return renderedContent;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
renderNoSearchResults(domain)
|
|
70
|
+
{
|
|
71
|
+
let noResultsTemplate = this.loadPartialTemplate('noResults', domain);
|
|
72
|
+
if(noResultsTemplate){
|
|
73
|
+
return this.renderEngine.render(
|
|
74
|
+
noResultsTemplate,
|
|
75
|
+
{
|
|
76
|
+
message: 'No search results found.',
|
|
77
|
+
cssClass: 'no-search-results',
|
|
78
|
+
alertClass: 'alert-info'
|
|
79
|
+
},
|
|
80
|
+
this.getPartialsForDomain(domain)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return '<div class="no-search-results alert alert-info">No search results found.</div>';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
loadPartialTemplate(partialName, domain)
|
|
87
|
+
{
|
|
88
|
+
let partials = this.getPartialsForDomain(domain);
|
|
89
|
+
return sc.get(partials, partialName, false);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
loadPaginationTemplate(containerName, domain)
|
|
93
|
+
{
|
|
94
|
+
if(!containerName || '' === containerName){
|
|
95
|
+
containerName = 'pagedCollection';
|
|
96
|
+
}
|
|
97
|
+
let partialContent = this.loadPartialTemplate(containerName, domain);
|
|
98
|
+
if(partialContent){
|
|
99
|
+
return partialContent;
|
|
100
|
+
}
|
|
101
|
+
Logger.critical('Pagination template not found: ' + containerName + '. Please create the template file.');
|
|
102
|
+
return '{{&collectionContentForCurrentPage}}';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
getPartialsForDomain(domain)
|
|
106
|
+
{
|
|
107
|
+
if(!this.getPartials){
|
|
108
|
+
Logger.error('getPartials function not provided to SearchRenderer');
|
|
109
|
+
return {};
|
|
110
|
+
}
|
|
111
|
+
return this.getPartials(domain);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports.SearchRenderer = SearchRenderer;
|