@reldens/cms 0.15.0 → 0.18.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 +150 -34
- package/admin/reldens-admin-client.css +39 -23
- package/admin/reldens-admin-client.js +7 -0
- package/admin/templates/cache-clean-button.html +4 -0
- package/admin/templates/edit.html +3 -1
- package/admin/templates/fields/view/textarea.html +1 -0
- package/admin/templates/sections/editForm/cms-pages.html +15 -0
- package/admin/templates/sections/viewForm/cms-pages.html +15 -0
- package/admin/templates/view.html +1 -0
- package/bin/reldens-cms-generate-entities.js +116 -5
- package/bin/reldens-cms.js +26 -8
- package/install/js/installer.js +5 -0
- package/install/success.html +1 -1
- package/lib/admin-manager/contents-builder.js +256 -0
- package/lib/admin-manager/router-contents.js +576 -0
- package/lib/admin-manager/router.js +208 -0
- package/lib/admin-manager.js +114 -944
- package/lib/cache/add-cache-button-subscriber.js +101 -0
- package/lib/cache/cache-manager.js +129 -0
- package/lib/cache/cache-routes-handler.js +76 -0
- package/lib/cms-pages-route-manager.js +117 -0
- package/lib/frontend.js +207 -64
- package/lib/installer.js +44 -20
- package/lib/json-fields-parser.js +74 -0
- package/lib/manager.js +55 -10
- package/lib/template-engine.js +361 -41
- package/lib/templates-list.js +10 -0
- package/migrations/default-blocks.sql +1 -1
- package/migrations/default-entity-access.sql +2 -2
- package/migrations/default-homepage.sql +27 -7
- package/migrations/install.sql +33 -36
- package/package.json +3 -3
- package/templates/index.js.dist +3 -3
- package/templates/js/scripts.js +5 -0
- package/templates/layouts/default.html +4 -4
- package/templates/page.html +14 -10
- package/templates/partials/footer.html +2 -23
- package/templates/partials/header.html +2 -35
package/bin/reldens-cms.js
CHANGED
|
@@ -2,20 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
5
|
-
* Reldens - CMS - CLI
|
|
5
|
+
* Reldens - CMS - CLI
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const { Manager } = require('../index');
|
|
10
10
|
const { Logger } = require('@reldens/utils');
|
|
11
|
+
const { FileHandler } = require('@reldens/server-utils');
|
|
11
12
|
|
|
12
13
|
let args = process.argv.slice(2);
|
|
13
14
|
let projectRoot = args[0] || process.cwd();
|
|
15
|
+
let indexPath = FileHandler.joinPaths(projectRoot, 'index.js');
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
if(FileHandler.exists(indexPath)){
|
|
18
|
+
require(indexPath);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let managerConfig = {projectRoot};
|
|
23
|
+
let entitiesPath = FileHandler.joinPaths(
|
|
24
|
+
projectRoot,
|
|
25
|
+
'generated-entities',
|
|
26
|
+
'models',
|
|
27
|
+
'prisma',
|
|
28
|
+
'registered-models-prisma.js'
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if(FileHandler.exists(entitiesPath)){
|
|
32
|
+
let entitiesModule = require(entitiesPath);
|
|
33
|
+
managerConfig.rawRegisteredEntities = entitiesModule.rawRegisteredEntities;
|
|
34
|
+
managerConfig.entitiesConfig = entitiesModule.entitiesConfig;
|
|
35
|
+
managerConfig.entitiesTranslations = entitiesModule.entitiesTranslations;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let manager = new Manager(managerConfig);
|
|
16
39
|
Logger.debug('Reldens CMS Manager instance created.', {configuration: manager.config});
|
|
17
40
|
|
|
18
|
-
|
|
41
|
+
manager.start().then((result) => {
|
|
19
42
|
if(!result){
|
|
20
43
|
Logger.info('Reldens CMS started by command failed.');
|
|
21
44
|
return false;
|
|
@@ -26,8 +49,3 @@ let started = manager.start().then((result) => {
|
|
|
26
49
|
Logger.critical('Failed to start CMS:', error);
|
|
27
50
|
process.exit();
|
|
28
51
|
});
|
|
29
|
-
|
|
30
|
-
if(!started){
|
|
31
|
-
Logger.error('Reldens CMS start process failed.');
|
|
32
|
-
process.exit();
|
|
33
|
-
}
|
package/install/js/installer.js
CHANGED
|
@@ -29,4 +29,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
29
29
|
installButton.disabled = true;
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
|
+
|
|
33
|
+
let copyRightYear = document.querySelector('.copyright-year');
|
|
34
|
+
if(copyRightYear){
|
|
35
|
+
copyRightYear.innerHTML = String((new Date()).getFullYear());
|
|
36
|
+
}
|
|
32
37
|
});
|
package/install/success.html
CHANGED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - ContentsBuilder
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { sc } = require('@reldens/utils');
|
|
8
|
+
|
|
9
|
+
class ContentsBuilder
|
|
10
|
+
{
|
|
11
|
+
|
|
12
|
+
constructor(props)
|
|
13
|
+
{
|
|
14
|
+
this.renderCallback = props.renderCallback;
|
|
15
|
+
this.adminFilesContents = props.adminFilesContents;
|
|
16
|
+
this.stylesFilePath = props.stylesFilePath;
|
|
17
|
+
this.scriptsFilePath = props.scriptsFilePath;
|
|
18
|
+
this.rootPath = props.rootPath;
|
|
19
|
+
this.branding = props.branding;
|
|
20
|
+
this.translations = props.translations;
|
|
21
|
+
this.resources = props.resources;
|
|
22
|
+
this.buildAdminCssOnActivation = props.buildAdminCssOnActivation;
|
|
23
|
+
this.buildAdminScriptsOnActivation = props.buildAdminScriptsOnActivation;
|
|
24
|
+
this.updateAdminAssetsDistOnActivation = props.updateAdminAssetsDistOnActivation;
|
|
25
|
+
this.emitEvent = props.emitEvent;
|
|
26
|
+
this.editPath = props.editPath;
|
|
27
|
+
this.savePath = props.savePath;
|
|
28
|
+
this.deletePath = props.deletePath;
|
|
29
|
+
this.fetchUploadProperties = props.fetchUploadProperties;
|
|
30
|
+
this.fetchTranslation = props.fetchTranslation;
|
|
31
|
+
this.fetchEntityIdPropertyKey = props.fetchEntityIdPropertyKey;
|
|
32
|
+
this.adminContents = {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async buildAdminContents()
|
|
36
|
+
{
|
|
37
|
+
this.adminContents.layout = await this.buildLayout();
|
|
38
|
+
this.adminContents.sideBar = await this.buildSideBar();
|
|
39
|
+
this.adminContents.login = await this.renderRoute(this.adminFilesContents.login, '');
|
|
40
|
+
this.adminContents.dashboard = await this.renderRoute(this.adminFilesContents.dashboard, this.adminContents.sideBar);
|
|
41
|
+
this.adminContents.entities = await this.buildEntitiesContents();
|
|
42
|
+
await this.emitEvent('reldens.buildAdminContentsAfter');
|
|
43
|
+
return this.adminContents;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async buildLayout()
|
|
47
|
+
{
|
|
48
|
+
return await this.render(
|
|
49
|
+
this.adminFilesContents.layout,
|
|
50
|
+
{
|
|
51
|
+
sideBar: '{{&sideBar}}',
|
|
52
|
+
pageContent: '{{&pageContent}}',
|
|
53
|
+
stylesFilePath: this.stylesFilePath,
|
|
54
|
+
scriptsFilePath: this.scriptsFilePath,
|
|
55
|
+
rootPath: this.rootPath,
|
|
56
|
+
brandingCompanyName: this.branding.companyName,
|
|
57
|
+
copyRight: this.branding.copyRight
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async buildSideBar()
|
|
63
|
+
{
|
|
64
|
+
let navigationContents = {};
|
|
65
|
+
let eventBuildSideBarBefore = {navigationContents};
|
|
66
|
+
await this.emitEvent('reldens.eventBuildSideBarBefore', eventBuildSideBarBefore);
|
|
67
|
+
navigationContents = eventBuildSideBarBefore.navigationContents;
|
|
68
|
+
for(let driverResource of this.resources()){
|
|
69
|
+
let navigation = driverResource.options?.navigation;
|
|
70
|
+
let name = this.translations.labels[driverResource.id()] || this.translations.labels[driverResource.entityKey];
|
|
71
|
+
let path = this.rootPath+'/'+(driverResource.id().replace(/_/g, '-'));
|
|
72
|
+
if(navigation?.name){
|
|
73
|
+
if(!navigationContents[navigation.name]){
|
|
74
|
+
navigationContents[navigation.name] = {};
|
|
75
|
+
}
|
|
76
|
+
navigationContents[navigation.name][driverResource.id()] = await this.render(
|
|
77
|
+
this.adminFilesContents.sideBarItem,
|
|
78
|
+
{name, path}
|
|
79
|
+
);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
navigationContents[driverResource.id()] = await this.render(
|
|
83
|
+
this.adminFilesContents.sideBarItem,
|
|
84
|
+
{name, path}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
let eventAdminSideBarBeforeSubItems = {navigationContents};
|
|
88
|
+
await this.emitEvent('reldens.adminSideBarBeforeSubItems', eventAdminSideBarBeforeSubItems);
|
|
89
|
+
let navigationView = '';
|
|
90
|
+
for(let id of Object.keys(navigationContents)){
|
|
91
|
+
if(sc.isObject(navigationContents[id])){
|
|
92
|
+
let subItems = '';
|
|
93
|
+
for(let subId of Object.keys(navigationContents[id])){
|
|
94
|
+
subItems += navigationContents[id][subId];
|
|
95
|
+
}
|
|
96
|
+
navigationView += await this.render(
|
|
97
|
+
this.adminFilesContents.sideBarHeader,
|
|
98
|
+
{name: id, subItems}
|
|
99
|
+
);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
navigationView += navigationContents[id];
|
|
103
|
+
}
|
|
104
|
+
let eventAdminSideBarBeforeRender = {navigationContents, navigationView};
|
|
105
|
+
await this.emitEvent('reldens.adminSideBarBeforeRender', eventAdminSideBarBeforeRender);
|
|
106
|
+
return await this.render(
|
|
107
|
+
this.adminFilesContents.sideBar,
|
|
108
|
+
{
|
|
109
|
+
rootPath: this.rootPath,
|
|
110
|
+
navigationView: eventAdminSideBarBeforeRender.navigationView
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async buildEntitiesContents()
|
|
116
|
+
{
|
|
117
|
+
let entitiesContents = {};
|
|
118
|
+
for(let driverResource of this.resources()){
|
|
119
|
+
let templateTitle = this.translations.labels[driverResource.id()];
|
|
120
|
+
let entityName = (driverResource.id().replace(/_/g, '-'));
|
|
121
|
+
let entityListRoute = this.rootPath+'/'+entityName;
|
|
122
|
+
let entityEditRoute = entityListRoute+this.editPath;
|
|
123
|
+
let entitySaveRoute = entityListRoute+this.savePath;
|
|
124
|
+
let entityDeleteRoute = entityListRoute+this.deletePath;
|
|
125
|
+
let uploadProperties = this.fetchUploadProperties(driverResource);
|
|
126
|
+
let multipartFormData = 0 < Object.keys(uploadProperties).length ? ' enctype="multipart/form-data"' : '';
|
|
127
|
+
let idProperty = this.fetchEntityIdPropertyKey(driverResource);
|
|
128
|
+
let editProperties = Object.keys(driverResource.options.properties);
|
|
129
|
+
editProperties.splice(editProperties.indexOf(idProperty), 1);
|
|
130
|
+
let filters = driverResource.options.filterProperties.map((property) => {
|
|
131
|
+
return {
|
|
132
|
+
propertyKey: property,
|
|
133
|
+
name: this.fetchTranslation(property),
|
|
134
|
+
value: '{{&'+property+'}}'
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
let fields = driverResource.options.showProperties.map((property) => {
|
|
138
|
+
return {
|
|
139
|
+
name: this.fetchTranslation(property),
|
|
140
|
+
value: '{{&'+property+'}}'
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
let editFields = editProperties.map((property) => {
|
|
144
|
+
return {
|
|
145
|
+
name: this.fetchTranslation(property),
|
|
146
|
+
value: '{{&'+property+'}}'
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
let sectionsContents = this.adminFilesContents?.sections;
|
|
150
|
+
let extraContentForList = sc.get(sectionsContents?.list, driverResource.entityPath, '');
|
|
151
|
+
let extraContentForView = await this.render(
|
|
152
|
+
sc.get(sectionsContents?.view, driverResource.entityPath, ''),
|
|
153
|
+
{
|
|
154
|
+
id: '{{&id}}',
|
|
155
|
+
entitySerializedData: '{{&entitySerializedData}}'
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
let extraFormContentForView = sc.get(sectionsContents?.viewForm, driverResource.entityPath, '');
|
|
159
|
+
let extraContentForEdit = sc.get(sectionsContents?.edit, driverResource.entityPath, '');
|
|
160
|
+
let extraFormContentForEdit = sc.get(sectionsContents?.editForm, driverResource.entityPath, '');
|
|
161
|
+
entitiesContents[entityName] = {
|
|
162
|
+
list: await this.render(
|
|
163
|
+
this.adminFilesContents.list,
|
|
164
|
+
{
|
|
165
|
+
entityName,
|
|
166
|
+
templateTitle,
|
|
167
|
+
entityListRoute,
|
|
168
|
+
entityEditRoute,
|
|
169
|
+
filters,
|
|
170
|
+
list: '{{&list}}',
|
|
171
|
+
pagination: '{{&pagination}}',
|
|
172
|
+
extraContent: '{{&extraContentForList}}'+extraContentForList,
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
view: await this.render(
|
|
176
|
+
this.adminFilesContents.view,
|
|
177
|
+
{
|
|
178
|
+
entityName,
|
|
179
|
+
templateTitle,
|
|
180
|
+
entityDeleteRoute,
|
|
181
|
+
entityListRoute,
|
|
182
|
+
fields,
|
|
183
|
+
id: '{{&id}}',
|
|
184
|
+
entityEditRoute: '{{&entityEditRoute}}',
|
|
185
|
+
entityNewRoute: '{{&entityNewRoute}}',
|
|
186
|
+
extraContent: '{{&extraContentForView}}'+extraContentForView,
|
|
187
|
+
extraFormContent: '{{&extraFormContentForView}}'+extraFormContentForView
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
edit: await this.render(
|
|
191
|
+
this.adminFilesContents.edit,
|
|
192
|
+
{
|
|
193
|
+
entityName,
|
|
194
|
+
entitySaveRoute,
|
|
195
|
+
multipartFormData,
|
|
196
|
+
editFields,
|
|
197
|
+
idValue: '{{&idValue}}',
|
|
198
|
+
idProperty: '{{&idProperty}}',
|
|
199
|
+
templateTitle: '{{&templateTitle}}',
|
|
200
|
+
entityViewRoute: '{{&entityViewRoute}}',
|
|
201
|
+
extraContent: '{{&extraContentForEdit}}'+extraContentForEdit,
|
|
202
|
+
extraFormContent: '{{&extraFormContentForEdit}}'+extraFormContentForEdit
|
|
203
|
+
}
|
|
204
|
+
)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return entitiesContents;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async render(content, params)
|
|
211
|
+
{
|
|
212
|
+
return await this.renderCallback(content, params);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async renderRoute(pageContent, sideBar)
|
|
216
|
+
{
|
|
217
|
+
return await this.render(
|
|
218
|
+
this.adminContents.layout,
|
|
219
|
+
{
|
|
220
|
+
stylesFilePath: this.stylesFilePath,
|
|
221
|
+
scriptsFilePath: this.scriptsFilePath,
|
|
222
|
+
brandingCompanyName: this.branding.companyName,
|
|
223
|
+
copyRight: this.branding.copyRight,
|
|
224
|
+
pageContent,
|
|
225
|
+
sideBar
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async buildAdminScripts()
|
|
231
|
+
{
|
|
232
|
+
if(!sc.isFunction(this.buildAdminScriptsOnActivation)){
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
return this.buildAdminScriptsOnActivation();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async updateAdminAssets()
|
|
239
|
+
{
|
|
240
|
+
if(!sc.isFunction(this.updateAdminAssetsDistOnActivation)){
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
return this.updateAdminAssetsDistOnActivation();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async buildAdminCss()
|
|
247
|
+
{
|
|
248
|
+
if(!sc.isFunction(this.buildAdminCssOnActivation)){
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return this.buildAdminCssOnActivation();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports.ContentsBuilder = ContentsBuilder;
|