larvitcms 1.0.2 → 3.0.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/.eslintrc +85 -87
- package/.github/workflows/actions.yml +43 -0
- package/README.md +2 -0
- package/cms.js +82 -181
- package/dataWriter.js +60 -312
- package/dbmigration/5.js +11 -21
- package/package.json +14 -19
- package/test/00test.js +135 -221
- package/.travis.yml +0 -36
- package/controllers/adminCmsPageEdit.js +0 -141
- package/controllers/adminCmsPages.js +0 -24
- package/controllers/adminCmsSnippetEdit.js +0 -106
- package/controllers/adminCmsSnippets.js +0 -26
- package/controllers/cms.js +0 -66
- package/models/utils.js +0 -6
- package/public/tmpl/adminCmsPageEdit.tmpl +0 -98
- package/public/tmpl/adminCmsPages.tmpl +0 -21
- package/public/tmpl/adminCmsSnippetEdit.tmpl +0 -38
- package/public/tmpl/adminCmsSnippets.tmpl +0 -17
- package/public/tmpl/inc/adminCmsPageEditControls.tmpl +0 -12
- package/public/tmpl/inc/adminCmsSnippetEditControls.tmpl +0 -10
- package/test/98lint.js +0 -9
- package/test/99close.js +0 -7
@@ -1,106 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const slugify = require('larvitslugify');
|
4
|
-
const async = require('async');
|
5
|
-
|
6
|
-
exports.run = function (req, res, cb) {
|
7
|
-
const tasks = [];
|
8
|
-
const data = {global: res.globalData};
|
9
|
-
const name = res.globalData.urlParsed.query.name || slugify(res.globalData.formFields.name);
|
10
|
-
|
11
|
-
data.global.menuControllerName = 'adminCmsSnippets';
|
12
|
-
data.global.messages = [];
|
13
|
-
data.global.errors = [];
|
14
|
-
|
15
|
-
// Make sure the user have the correct rights
|
16
|
-
// This is set in larvitadmingui controllerGlobal
|
17
|
-
if (!res.adminRights) {
|
18
|
-
utils.deny(res);
|
19
|
-
|
20
|
-
return cb(null, req, res, null);
|
21
|
-
}
|
22
|
-
|
23
|
-
// Save a POSTed form
|
24
|
-
if (res.globalData.formFields.save !== undefined) {
|
25
|
-
tasks.push(function (cb) {
|
26
|
-
const tasks = [];
|
27
|
-
|
28
|
-
let field;
|
29
|
-
|
30
|
-
if (res.globalData.formFields.name === '') {
|
31
|
-
data.global.errors.push('Name must be specified');
|
32
|
-
|
33
|
-
return cb();
|
34
|
-
}
|
35
|
-
|
36
|
-
if (res.globalData.urlParsed.query.name === undefined) {
|
37
|
-
tasks.push(function (cb) {
|
38
|
-
req.cms.getSnippets({names: res.globalData.formFields.name}, function (err, result) {
|
39
|
-
if (err) return cb(err);
|
40
|
-
if (result.length > 0) err = new Error('Snippet already exists');
|
41
|
-
|
42
|
-
return cb(err);
|
43
|
-
});
|
44
|
-
});
|
45
|
-
}
|
46
|
-
|
47
|
-
function addTask(lang, body) {
|
48
|
-
tasks.push(function (cb) {
|
49
|
-
req.cms.saveSnippet({name: res.globalData.formFields.name, lang: lang, body: body}, cb);
|
50
|
-
});
|
51
|
-
}
|
52
|
-
|
53
|
-
for (field in res.globalData.formFields) {
|
54
|
-
if (field.split('.').length === 2) {
|
55
|
-
addTask(field.split('.')[1], res.globalData.formFields[field]);
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
async.series(tasks, function (err) {
|
60
|
-
if (err) {
|
61
|
-
data.global.errors.push('Save error: ' + err.message);
|
62
|
-
|
63
|
-
return cb();
|
64
|
-
}
|
65
|
-
|
66
|
-
res.statusCode = 302;
|
67
|
-
req.session.data.nextCallData = {global: {messages: ['Saved']}};
|
68
|
-
res.setHeader('Location', '/adminCmsSnippetEdit?name=' + res.globalData.formFields.name + '&langs=' + (res.globalData.urlParsed.query.langs || 'en'));
|
69
|
-
cb();
|
70
|
-
});
|
71
|
-
});
|
72
|
-
}
|
73
|
-
|
74
|
-
if (name !== undefined) {
|
75
|
-
if (res.globalData.formFields.delete === 'delete') {
|
76
|
-
tasks.push(function (cb) {
|
77
|
-
req.cms.rmSnippet(name, function (err) {
|
78
|
-
if (err) return cb(err);
|
79
|
-
res.statusCode = 302;
|
80
|
-
req.session.data.nextCallData = {global: {messages: ['Successfully removed snippet']}};
|
81
|
-
res.setHeader('Location', '/adminCmsSnippets');
|
82
|
-
cb();
|
83
|
-
});
|
84
|
-
});
|
85
|
-
} else {
|
86
|
-
// Load data from database
|
87
|
-
tasks.push(function (cb) {
|
88
|
-
req.cms.getSnippets({names: name}, function (err, snippets) {
|
89
|
-
let lang;
|
90
|
-
|
91
|
-
if (snippets[0] !== undefined) {
|
92
|
-
for (lang in snippets[0].langs) {
|
93
|
-
res.globalData.formFields['body.' + lang] = snippets[0].langs[lang];
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
cb();
|
98
|
-
});
|
99
|
-
});
|
100
|
-
}
|
101
|
-
}
|
102
|
-
|
103
|
-
async.series(tasks, function (err) {
|
104
|
-
cb(err, req, res, data);
|
105
|
-
});
|
106
|
-
};
|
@@ -1,26 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const utils = require('../models/utils.js');
|
4
|
-
|
5
|
-
exports.run = function (req, res, cb) {
|
6
|
-
const data = {global: res.globalData};
|
7
|
-
|
8
|
-
data.global.controllerName = 'adminCmsSnippets';
|
9
|
-
|
10
|
-
// Make sure the user have the correct rights
|
11
|
-
// This is set in larvitadmingui controllerGlobal
|
12
|
-
if (!res.adminRights) {
|
13
|
-
utils.deny(res);
|
14
|
-
|
15
|
-
return cb(null, req, res, null);
|
16
|
-
}
|
17
|
-
|
18
|
-
if (res.langs) {
|
19
|
-
data.global.langs = res.langs;
|
20
|
-
}
|
21
|
-
|
22
|
-
req.cms.getSnippets({onlyNames: true}, function (err, snippets) {
|
23
|
-
data.cmsSnippets = snippets;
|
24
|
-
cb(null, req, res, data);
|
25
|
-
});
|
26
|
-
};
|
package/controllers/cms.js
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
const logPrefix = 'larvitcms: controllers/cms.js - ';
|
4
|
-
|
5
|
-
function call404(req, res, cb) {
|
6
|
-
res.templateName = '404';
|
7
|
-
|
8
|
-
if (req.lfs.getPathSync('controllers/404.js')) {
|
9
|
-
require(req.lfs.getPathSync('controllers/404.js')).run(req, res, cb);
|
10
|
-
} else {
|
11
|
-
const err = new Error(logPrefix + 'call404() - 404 controller not found');
|
12
|
-
|
13
|
-
res.statusCode = 500;
|
14
|
-
data = {};
|
15
|
-
cb(err, req, res, {});
|
16
|
-
}
|
17
|
-
}
|
18
|
-
|
19
|
-
exports.run = function (req, res, cb) {
|
20
|
-
const data = {global: res.globalData};
|
21
|
-
|
22
|
-
if (req.lang === undefined) {
|
23
|
-
if (res.langs !== undefined && res.langs[0] !== undefined) {
|
24
|
-
req.lang = res.langs[0];
|
25
|
-
} else {
|
26
|
-
req.lang = 'en';
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
if (!data.global.title) {
|
31
|
-
data.global.title = '';
|
32
|
-
}
|
33
|
-
|
34
|
-
if (req.urlParsed.path.substring(req.urlParsed.path.length - 5) === '.json') {
|
35
|
-
req.urlParsed.path = req.urlParsed.path.substring(0, req.urlParsed.path.length - 5);
|
36
|
-
}
|
37
|
-
|
38
|
-
req.cms.getPages({slugs: req.urlParsed.path}, function (err, pages) {
|
39
|
-
if (err) return cb(err, req, res, data);
|
40
|
-
|
41
|
-
if (pages.length === 0) {
|
42
|
-
req.log.verbose(logPrefix + 'CMS controller called, but no page found for slug: "' + req.urlParsed.path + '"');
|
43
|
-
call404(req, res, cb);
|
44
|
-
|
45
|
-
return;
|
46
|
-
}
|
47
|
-
|
48
|
-
// Take the first page that is found... if there are several, well, tough luck :D
|
49
|
-
if (pages[0] !== undefined && pages[0].langs !== undefined && pages[0].langs[req.lang] !== undefined) {
|
50
|
-
data.cmsData = pages[0].langs[req.lang];
|
51
|
-
data.cmsData.template = pages[0].template;
|
52
|
-
data.global.title += ' | ' + data.cmsData.htmlTitle;
|
53
|
-
data.global.slugs = {};
|
54
|
-
for (const key in pages[0].langs) {
|
55
|
-
data.global.slugs[key] = pages[0].langs[key].slug;
|
56
|
-
}
|
57
|
-
} else {
|
58
|
-
req.log.verbose(logPrefix + 'CMS controller called, but no content found for slug: "' + req.urlParsed.path + '" and lang: "' + req.lang + '"');
|
59
|
-
call404(req, res, cb);
|
60
|
-
|
61
|
-
return;
|
62
|
-
}
|
63
|
-
|
64
|
-
cb(err, req, res, data);
|
65
|
-
});
|
66
|
-
};
|
package/models/utils.js
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
<%= _.render('inc/head', obj) %>
|
2
|
-
<%= _.render('inc/pageTop', obj) %>
|
3
|
-
<form method="post">
|
4
|
-
|
5
|
-
<%= _.render('inc/adminCmsPageEditControls', obj) %>
|
6
|
-
|
7
|
-
<fieldset>
|
8
|
-
<legend>Identity</legend>
|
9
|
-
|
10
|
-
<div class="row">
|
11
|
-
<div class="three columns">
|
12
|
-
<label for="id">Id</label>
|
13
|
-
<input type="text" value="<%= global.urlParsed.query.uuid %>" disabled="disabled" />
|
14
|
-
</div>
|
15
|
-
|
16
|
-
<div class="three columns">
|
17
|
-
<label for="name">Page name</label>
|
18
|
-
<input type="text" name="name" value="<%= global.formFields.name %>" />
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div class="three columns">
|
22
|
-
<label for="template">Template</label>
|
23
|
-
<select name="template">
|
24
|
-
<% for (var templateName in obj.cmsTemplates) { %>
|
25
|
-
<option value="<%= templateName %>"<% if (templateName === obj.global.formFields.template) { print(' selected="selected"'); } %>><%= obj.cmsTemplates[templateName].label %></option>
|
26
|
-
<% } %>
|
27
|
-
</select>
|
28
|
-
</div>
|
29
|
-
|
30
|
-
<div class="three columns">
|
31
|
-
<label for="published">
|
32
|
-
<input type="checkbox" name="published" <% if (global.formFields.published) print(' checked="checked"'); %> />
|
33
|
-
<span class="label-body">Published</span>
|
34
|
-
</label>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
</fieldset>
|
38
|
-
|
39
|
-
<% if ( ! global.urlParsed.query.langs) global.urlParsed.query.langs = 'en'; %>
|
40
|
-
|
41
|
-
<% /* Due to display: inline-block we need it to be no spaces between the elements... */
|
42
|
-
let i = 0;
|
43
|
-
print('<nav class="tabs">');
|
44
|
-
_.each(global.urlParsed.query.langs.split(','), function (lang) {
|
45
|
-
print('<a showcontent="tab_content_' + i + '" class="tab');
|
46
|
-
if (i === 0) print(' active');
|
47
|
-
print('">' + lang + '</a>');
|
48
|
-
i ++;
|
49
|
-
});
|
50
|
-
print('</nav>');
|
51
|
-
%>
|
52
|
-
|
53
|
-
<% i = 0; %>
|
54
|
-
<% _.each(global.urlParsed.query.langs.split(','), function (lang) { %>
|
55
|
-
<fieldset class="tab_content" id="tab_content_<%= i %>">
|
56
|
-
<legend>Entry content, language: <%= lang %></legend>
|
57
|
-
|
58
|
-
<div class="row">
|
59
|
-
<div class="six columns">
|
60
|
-
<label for="htmlTitle.<%= lang %>">Page title</label>
|
61
|
-
<input type="text" name="htmlTitle.<%= lang %>" value="<% if (global.formFields['htmlTitle.' + lang]) print(global.formFields['htmlTitle.' + lang]) %>" />
|
62
|
-
</div>
|
63
|
-
|
64
|
-
<div class="six columns">
|
65
|
-
<label for="slug.<%= lang %>">Slug</label>
|
66
|
-
<input type="text" name="slug.<%= lang %>" value="<% if (global.formFields['slug.' + lang]) print(global.formFields['slug.' + lang]) %>" />
|
67
|
-
</div>
|
68
|
-
</div>
|
69
|
-
|
70
|
-
<%
|
71
|
-
var fields = 1;
|
72
|
-
if (obj.global.formFields.template && obj.cmsTemplates[obj.global.formFields.template].fields) {
|
73
|
-
fields = obj.cmsTemplates[obj.global.formFields.template].fields;
|
74
|
-
}
|
75
|
-
%>
|
76
|
-
|
77
|
-
<% for (let i = 1; i !== (fields + 1); i ++) { %>
|
78
|
-
<div class="row">
|
79
|
-
<label for="body<%= i %>.<%= lang %>">Entry <%= i %> content</label>
|
80
|
-
<textarea class="u-full-width" name="body<%= i %>.<%= lang %>" rows="20"><% if (global.formFields['body' + i + '.' + lang]) print(global.formFields['body' + i + '.' + lang]) %></textarea>
|
81
|
-
</div>
|
82
|
-
<% } %>
|
83
|
-
</fieldset>
|
84
|
-
<% i ++; %>
|
85
|
-
<% }); %>
|
86
|
-
|
87
|
-
<%= _.render('inc/adminCmsPageEditControls', obj) %>
|
88
|
-
|
89
|
-
</form>
|
90
|
-
<script src="//tinymce.cachefly.net/4.2/tinymce.min.js"></script>
|
91
|
-
<script>tinymce.init({
|
92
|
-
'selector': 'textarea',
|
93
|
-
'toolbar': 'undo redo | formatselect bold italic underline strikethrough | subscript superscript | link unlink image | table | bullist numlist | removeformat code',
|
94
|
-
'menubar': false,
|
95
|
-
'plugins': 'link image code table',
|
96
|
-
'valid_elements': 'ul,li,ol,table,tr[colspan|rowspan],td[colspan|rowspan],th,thead,tbody,p,strong,a[href|target],em,span[style],sup,sub,h1,h2,h3,h4,h5,h6,br,img[id|lang|longdesc|src|alt|title|width|height|rel]'
|
97
|
-
});</script>
|
98
|
-
<%= _.render('inc/pageBottom', obj) %>
|
@@ -1,21 +0,0 @@
|
|
1
|
-
<%= _.render('inc/head', obj) %>
|
2
|
-
<%= _.render('inc/pageTop', obj) %>
|
3
|
-
<table>
|
4
|
-
<thead>
|
5
|
-
<tr>
|
6
|
-
<th>Uuid</th>
|
7
|
-
<th>Name</th>
|
8
|
-
<th>Published</th>
|
9
|
-
</tr>
|
10
|
-
</thead>
|
11
|
-
<tbody>
|
12
|
-
<% _.each(cmsPages, function (page) { %>
|
13
|
-
<tr>
|
14
|
-
<td><a href="adminCmsPageEdit?langs=<% if(global.langs){print(global.langs.join(','));}else{print('en');} %>&uuid=<%= page.uuid %>"><%= page.uuid %></a></td>
|
15
|
-
<td><%= page.name %></td>
|
16
|
-
<td><% if (page.published) print('Yes'); else print('No'); %></td>
|
17
|
-
</tr>
|
18
|
-
<% }) %>
|
19
|
-
</tbody>
|
20
|
-
</table>
|
21
|
-
<%= _.render('inc/pageBottom', obj) %>
|
@@ -1,38 +0,0 @@
|
|
1
|
-
<%= _.render('inc/head', obj) %>
|
2
|
-
<%= _.render('inc/pageTop', obj) %>
|
3
|
-
<script src="//tinymce.cachefly.net/4.2/tinymce.min.js"></script>
|
4
|
-
<script>tinymce.init({
|
5
|
-
'selector': 'textarea',
|
6
|
-
'toolbar': 'undo redo | formatselect bold italic underline strikethrough | bullist numlist | subscript superscript | link unlink image | removeformat code',
|
7
|
-
'menubar': false,
|
8
|
-
'plugins': 'link image code',
|
9
|
-
'valid_elements': 'ul,li,ol,br,p,strong,a[href|target],em,span,sup,sub,h1,h2,h3,h4,h5,h6,br,img[id|lang|longdesc|src|alt|title|width|height|rel]'
|
10
|
-
});</script>
|
11
|
-
<form method="post">
|
12
|
-
|
13
|
-
<%= _.render('inc/adminCmsSnippetEditControls', obj) %>
|
14
|
-
|
15
|
-
<fieldset>
|
16
|
-
<legend>Snippet</legend>
|
17
|
-
|
18
|
-
<div class="row">
|
19
|
-
<div class="three columns">
|
20
|
-
<label for="name">Name</label>
|
21
|
-
<input type="text" value="<%= global.urlParsed.query.name %>" name="name" <% if (global.urlParsed.query.name !== undefined) { print('readonly="readonly"'); } %> />
|
22
|
-
</div>
|
23
|
-
</div>
|
24
|
-
|
25
|
-
<% if ( ! global.urlParsed.query.langs) global.urlParsed.query.langs = 'en'; %>
|
26
|
-
|
27
|
-
<% _.each(global.urlParsed.query.langs.split(','), function (lang) { %>
|
28
|
-
<div class="row">
|
29
|
-
<label for="body.<%= lang %>">Snippet content, language: <%= lang %></label>
|
30
|
-
<textarea class="u-full-width" name="body.<%= lang %>" rows="20"><% if (global.formFields['body.' + lang]) print(global.formFields['body.' + lang]) %></textarea>
|
31
|
-
</div>
|
32
|
-
</fieldset>
|
33
|
-
<% }); %>
|
34
|
-
|
35
|
-
<%= _.render('inc/adminCmsSnippetEditControls', obj) %>
|
36
|
-
|
37
|
-
</form>
|
38
|
-
<%= _.render('inc/pageBottom', obj) %>
|
@@ -1,17 +0,0 @@
|
|
1
|
-
<%= _.render('inc/head', obj) %>
|
2
|
-
<%= _.render('inc/pageTop', obj) %>
|
3
|
-
<table>
|
4
|
-
<thead>
|
5
|
-
<tr>
|
6
|
-
<th>Name</th>
|
7
|
-
</tr>
|
8
|
-
</thead>
|
9
|
-
<tbody>
|
10
|
-
<% _.each(cmsSnippets, function (snippet) { %>
|
11
|
-
<tr>
|
12
|
-
<td><a href="adminCmsSnippetEdit?langs=<% if(global.langs){print(global.langs.join(','));}else{print('en');} %>&name=<%= snippet.name %>"><%= snippet.name %></a></td>
|
13
|
-
</tr>
|
14
|
-
<% }) %>
|
15
|
-
</tbody>
|
16
|
-
</table>
|
17
|
-
<%= _.render('inc/pageBottom', obj) %>
|
@@ -1,12 +0,0 @@
|
|
1
|
-
<div class="row">
|
2
|
-
<div class="six columns">
|
3
|
-
<a href="/adminCmsPages" class="button">Cancel</a>
|
4
|
-
<% if (global.urlParsed.query.uuid) { %>
|
5
|
-
<button type="submit" name="delete">Delete entry</button>
|
6
|
-
<% } %>
|
7
|
-
</div>
|
8
|
-
|
9
|
-
<div class="six columns text_right">
|
10
|
-
<button type="submit" name="save" value="save">Save</button>
|
11
|
-
</div>
|
12
|
-
</div>
|
@@ -1,10 +0,0 @@
|
|
1
|
-
<div class="row">
|
2
|
-
<div class="six columns">
|
3
|
-
<a href="/adminCmsSnippets" class="button">Cancel</a>
|
4
|
-
</div>
|
5
|
-
|
6
|
-
<div class="six columns text_right">
|
7
|
-
<button type="submit" name="save" value="save">Save</button>
|
8
|
-
<button type="submit" name="delete" value="delete" class="inv">Delete</button>
|
9
|
-
</div>
|
10
|
-
</div>
|
package/test/98lint.js
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
require('mocha-eslint')([__dirname + '/..'], {
|
4
|
-
// Increase the timeout of the test if linting takes to long
|
5
|
-
timeout: 5000, // Defaults to the global mocha `timeout` option
|
6
|
-
|
7
|
-
// Increase the time until a test is marked as slow
|
8
|
-
slow: 1000 // Defaults to the global mocha `slow` option
|
9
|
-
});
|