larvitcms 1.0.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
});
|