diff --git a/config.js b/config.js index c73733de8244..699df2520f51 100644 --- a/config.js +++ b/config.js @@ -11,10 +11,7 @@ config.defaultLang = 'en'; // Force i18n to be on config.forceI18n = true; -// ## Themes & Plugins - -// Current active theme -config.activeTheme = 'casper'; +// ## Plugins // Current active plugins config.activePlugins = [ diff --git a/core/client/models/settings.js b/core/client/models/settings.js index dc1ea5ef84d5..31f1c7000a27 100644 --- a/core/client/models/settings.js +++ b/core/client/models/settings.js @@ -4,7 +4,7 @@ // Set the url manually and id to '0' to force PUT requests Ghost.Models.Settings = Backbone.Model.extend({ - url: '/api/v0.1/settings/', + url: Ghost.settings.apiRoot + '/settings', id: "0", defaults: { title: 'My Blog', diff --git a/core/client/models/themes.js b/core/client/models/themes.js new file mode 100644 index 000000000000..47549b758d4a --- /dev/null +++ b/core/client/models/themes.js @@ -0,0 +1,9 @@ +/*global window, document, Ghost, $, _, Backbone */ +(function () { + "use strict"; + + Ghost.Models.Themes = Backbone.Model.extend({ + url: Ghost.settings.apiRoot + '/themes' + }); + +}()); \ No newline at end of file diff --git a/core/client/tpl/settings/general.hbs b/core/client/tpl/settings/general.hbs index 7846eb09c9f2..ffbb06709af3 100644 --- a/core/client/tpl/settings/general.hbs +++ b/core/client/tpl/settings/general.hbs @@ -50,6 +50,15 @@ +
+ + +
+
diff --git a/core/client/views/settings.js b/core/client/views/settings.js index 92c488672707..640c93a6f201 100644 --- a/core/client/views/settings.js +++ b/core/client/views/settings.js @@ -41,7 +41,8 @@ showContent: function (id) { var self = this, - model; + model, + themes; Ghost.router.navigate('/settings/' + id); Ghost.trigger('urlchange'); @@ -53,9 +54,13 @@ this.pane = new Settings[id]({ el: '.settings-content'}); if (!this.models.hasOwnProperty(this.pane.options.modelType)) { + themes = this.models.Themes = new Ghost.Models.Themes(); model = this.models[this.pane.options.modelType] = new Ghost.Models[this.pane.options.modelType](); - model.fetch().then(function () { - self.renderPane(model); + themes.fetch().then(function () { + model.fetch().then(function () { + model.set({availableThemes: themes.toJSON()}); + self.renderPane(model); + }); }); } else { model = this.models[this.pane.options.modelType]; @@ -134,12 +139,13 @@ }, saveSettings: function () { + this.model.unset('availableThemes'); this.model.save({ title: this.$('#blog-title').val(), email: this.$('#email-address').val(), logo: this.$('#logo').attr("src"), - icon: this.$('#icon').attr("src") - + icon: this.$('#icon').attr("src"), + activeTheme: this.$('#activeTheme').val() }, { success: this.saveSuccess, error: this.saveError diff --git a/core/ghost.js b/core/ghost.js index 0c72de771daf..a90a595195d5 100644 --- a/core/ghost.js +++ b/core/ghost.js @@ -111,7 +111,7 @@ Ghost = function () { 'appRoot': appRoot, 'themePath': themePath, 'pluginPath': pluginPath, - 'activeTheme': path.join(themePath, config.activeTheme), + 'activeTheme': path.join(themePath, !instance.settingsCache ? "" : instance.settingsCache.activeTheme), 'adminViews': path.join(appRoot, '/core/server/views/'), 'helperTemplates': path.join(appRoot, '/core/server/helpers/tpl/'), 'lang': path.join(appRoot, '/core/shared/lang/'), @@ -168,6 +168,17 @@ Ghost.prototype.updateSettingsCache = function (settings) { var settings = {}; _.map(result.models, function (member) { if (!settings.hasOwnProperty(member.attributes.key)) { + if (member.attributes.key === 'activeTheme') { + member.attributes.value = member.attributes.value.substring(member.attributes.value.lastIndexOf('/') + 1); + var settingsThemePath = path.join(themePath, member.attributes.value); + fs.exists(settingsThemePath, function (exists) { + if (!exists) { + member.attributes.value = "casper"; + } + settings[member.attributes.key] = member.attributes.value; + }); + return; + } settings[member.attributes.key] = member.attributes.value; } }); diff --git a/core/server/api.js b/core/server/api.js index 6c9e38a658a8..a88c3946ac0c 100644 --- a/core/server/api.js +++ b/core/server/api.js @@ -14,6 +14,7 @@ var Ghost = require('../ghost'), users, notifications, settings, + themes, requestHandler, cachedSettingsRequestHandler, settingsObject, @@ -247,6 +248,39 @@ settings = { } }; +// ## Themes + +themes = { + // #### Browse + + // **takes:** options object + browse: function browse() { + // **returns:** a promise for a themes json object + return when(ghost.paths().availableThemes).then(function (themes) { + var themeKeys = Object.keys(themes), + res = [], + i, + activeTheme = ghost.paths().activeTheme.substring(ghost.paths().activeTheme.lastIndexOf('/') + 1), + item; + + for (i = 0; i < themeKeys.length; i += 1) { + //do not include hidden files + if (themeKeys[i].indexOf('.') !== 0) { + item = {}; + item.name = themeKeys[i]; + item.details = themes[themeKeys[i]]; + if (themeKeys[i] === activeTheme) { + item.active = true; + } + res.push(item); + } + } + return res; + }); + } +}; + + // ## Request Handlers // ### requestHandler @@ -308,5 +342,6 @@ module.exports.posts = posts; module.exports.users = users; module.exports.notifications = notifications; module.exports.settings = settings; +module.exports.themes = themes; module.exports.requestHandler = requestHandler; module.exports.cachedSettingsRequestHandler = cachedSettingsRequestHandler; diff --git a/core/server/views/default.hbs b/core/server/views/default.hbs index 9100a93db5ea..38d7091ce03a 100644 --- a/core/server/views/default.hbs +++ b/core/server/views/default.hbs @@ -80,6 +80,7 @@ + diff --git a/index.js b/index.js index 6248be0fd806..d234f4287608 100644 --- a/index.js +++ b/index.js @@ -199,6 +199,8 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( ghost.app().get('/api/v0.1/settings', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.browse)); ghost.app().get('/api/v0.1/settings/:key', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.read)); ghost.app().put('/api/v0.1/settings', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.edit)); + // #### Themes + ghost.app().get('/api/v0.1/themes', authAPI, disableCachedResult, api.requestHandler(api.themes.browse)); // #### Users ghost.app().get('/api/v0.1/users', authAPI, disableCachedResult, api.requestHandler(api.users.browse)); ghost.app().get('/api/v0.1/users/:id', authAPI, disableCachedResult, api.requestHandler(api.users.read));