mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-07 14:35:47 +01:00
introduction of theme engine parsing (themes go in /public/themes!)
This commit is contained in:
@@ -7,7 +7,7 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
themes.render = function(bootswatch) {
|
themes.render = function(bootswatch) {
|
||||||
var themeFrag = document.createDocumentFragment(),
|
var themeFrag = document.createDocumentFragment(),
|
||||||
themeEl = document.createElement('li'),
|
themeEl = document.createElement('li'),
|
||||||
themeContainer = document.querySelector('#content .themes'),
|
themeContainer = document.querySelector('#bootstrap_themes'),
|
||||||
numThemes = bootswatch.themes.length;
|
numThemes = bootswatch.themes.length;
|
||||||
|
|
||||||
for(var x=0;x<numThemes;x++) {
|
for(var x=0;x<numThemes;x++) {
|
||||||
@@ -42,30 +42,33 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
scriptEl.src = 'http://api.bootswatch.com?callback=nodebb_admin.themes.render';
|
scriptEl.src = 'http://api.bootswatch.com?callback=nodebb_admin.themes.render';
|
||||||
document.body.appendChild(scriptEl);
|
document.body.appendChild(scriptEl);
|
||||||
|
|
||||||
var themeContainer = document.querySelector('#content .themes');
|
var bootstrapThemeContainer = document.querySelector('#bootstrap_themes'),
|
||||||
themeContainer.addEventListener('click', function(e) {
|
installedThemeContainer = document.querySelector('#installed_themes'),
|
||||||
if (e.target.hasAttribute('data-action')) {
|
themeEvent = function(e) {
|
||||||
switch(e.target.getAttribute('data-action')) {
|
if (e.target.hasAttribute('data-action')) {
|
||||||
case 'preview':
|
switch(e.target.getAttribute('data-action')) {
|
||||||
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
case 'preview':
|
||||||
cssEl = document.getElementById('base-theme');
|
var cssSrc = $(e.target).parents('li').attr('data-css'),
|
||||||
|
cssEl = document.getElementById('base-theme');
|
||||||
|
|
||||||
cssEl.href = cssSrc;
|
cssEl.href = cssSrc;
|
||||||
break;
|
break;
|
||||||
case 'use':
|
case 'use':
|
||||||
var parentEl = $(e.target).parents('li'),
|
var parentEl = $(e.target).parents('li'),
|
||||||
cssSrc = parentEl.attr('data-css'),
|
cssSrc = parentEl.attr('data-css'),
|
||||||
cssName = parentEl.attr('data-theme');
|
cssName = parentEl.attr('data-theme');
|
||||||
socket.emit('api:config.set', {
|
socket.emit('api:config.set', {
|
||||||
key: 'theme:id', value: 'bootswatch:' + cssName
|
key: 'theme:id', value: 'bootswatch:' + cssName
|
||||||
});
|
});
|
||||||
socket.emit('api:config.set', {
|
socket.emit('api:config.set', {
|
||||||
key: 'theme:src', value: cssSrc
|
key: 'theme:src', value: cssSrc
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, false);
|
bootstrapThemeContainer.addEventListener('click', themeEvent);
|
||||||
|
installedThemeContainer.addEventListener('click', themeEvent);
|
||||||
|
|
||||||
var revertEl = document.getElementById('revert_theme');
|
var revertEl = document.getElementById('revert_theme');
|
||||||
revertEl.addEventListener('click', function() {
|
revertEl.addEventListener('click', function() {
|
||||||
@@ -76,4 +79,31 @@ var nodebb_admin = (function(nodebb_admin) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
// Installed Themes
|
||||||
|
socket.once('api:admin:themes.getInstalled', function(themes) {
|
||||||
|
var instListEl = document.getElementById('installed_themes'),
|
||||||
|
themeFrag = document.createDocumentFragment(),
|
||||||
|
liEl = document.createElement('li');
|
||||||
|
|
||||||
|
for(var x=0,numThemes=themes.length;x<numThemes;x++) {
|
||||||
|
liEl.setAttribute('data-theme', themes[x].id);
|
||||||
|
liEl.setAttribute('data-css', themes[x].src);
|
||||||
|
liEl.innerHTML = '<img src="' + themes[x].thumbnail + '" />' +
|
||||||
|
'<div>' +
|
||||||
|
'<div class="pull-right">' +
|
||||||
|
'<button class="btn btn-primary" data-action="use">Use</button> ' +
|
||||||
|
'<button class="btn" data-action="preview">Preview</button>' +
|
||||||
|
'</div>' +
|
||||||
|
'<h4>' + themes[x].name + '</h4>' +
|
||||||
|
'<p>' + themes[x].description + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div class="clear">';
|
||||||
|
themeFrag.appendChild(liEl.cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
instListEl.innerHTML = '';
|
||||||
|
instListEl.appendChild(themeFrag);
|
||||||
|
});
|
||||||
|
socket.emit('api:admin:themes.getInstalled');
|
||||||
})();
|
})();
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
<h1>Themes</h1>
|
<h1>Themes</h1>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<h3>Custom Themes</h3>
|
||||||
|
<p>
|
||||||
|
The following themes are currently installed in this NodeBB instance.
|
||||||
|
</p>
|
||||||
|
<ul class="themes" id="installed_themes">
|
||||||
|
<li><i class="icon-refresh icon-spin"></i> Checking for installed themes...</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
<h3>Bootswatch Themes</h3>
|
<h3>Bootswatch Themes</h3>
|
||||||
<p>
|
<p>
|
||||||
NodeBB Themes are powered by Bootswatch, a repository containing themes built
|
NodeBB Themes are powered by Bootswatch, a repository containing themes built
|
||||||
with Bootstrap as a base theme.
|
with Bootstrap as a base theme.
|
||||||
</p>
|
</p>
|
||||||
<ul class="themes">
|
<ul class="themes" id="bootstrap_themes">
|
||||||
<li><i class="icon-refresh icon-spin"></i> Loading Themes</li>
|
<li><i class="icon-refresh icon-spin"></i> Loading Themes</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
0
public/themes/.gitignore
vendored
Normal file
0
public/themes/.gitignore
vendored
Normal file
37
src/meta.js
37
src/meta.js
@@ -1,6 +1,8 @@
|
|||||||
var utils = require('./../public/src/utils.js'),
|
var utils = require('./../public/src/utils.js'),
|
||||||
RDB = require('./redis.js'),
|
RDB = require('./redis.js'),
|
||||||
async = require('async');
|
async = require('async'),
|
||||||
|
path = require('path'),
|
||||||
|
fs = require('fs');
|
||||||
|
|
||||||
(function(Meta) {
|
(function(Meta) {
|
||||||
Meta.config = {
|
Meta.config = {
|
||||||
@@ -42,4 +44,37 @@ var utils = require('./../public/src/utils.js'),
|
|||||||
RDB.hdel('config', field);
|
RDB.hdel('config', field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Meta.themes = {
|
||||||
|
get: function(callback) {
|
||||||
|
var themePath = path.join(__dirname, '../', 'public/themes');
|
||||||
|
fs.readdir(themePath, function(err, files) {
|
||||||
|
var themeArr = [];
|
||||||
|
async.each(files, function(file, next) {
|
||||||
|
fs.lstat(path.join(themePath, file), function(err, stats) {
|
||||||
|
if(stats.isDirectory()) {
|
||||||
|
var themeDir = file,
|
||||||
|
themeConfPath = path.join(themePath, themeDir, 'theme.json');
|
||||||
|
|
||||||
|
fs.exists(themeConfPath, function(exists) {
|
||||||
|
if (exists) {
|
||||||
|
fs.readFile(themeConfPath, function(err, conf) {
|
||||||
|
conf = JSON.parse(conf);
|
||||||
|
conf.src = global.nconf.get('url') + 'themes/' + themeDir + '/' + conf.src;
|
||||||
|
themeArr.push(conf);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else next();
|
||||||
|
});
|
||||||
|
}, function(err) {
|
||||||
|
callback(err, themeArr);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
saveViaGithub: function(repo_url, callback) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
}(exports));
|
}(exports));
|
||||||
@@ -614,6 +614,12 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
else
|
else
|
||||||
socket.emit('api:admin.user.search', null);
|
socket.emit('api:admin.user.search', null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('api:admin:themes.getInstalled', function() {
|
||||||
|
meta.themes.get(function(err, themeArr) {
|
||||||
|
socket.emit('api:admin:themes.getInstalled', themeArr);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
}(SocketIO));
|
}(SocketIO));
|
||||||
|
|||||||
Reference in New Issue
Block a user