Merging with upstream master changes; settings provider

This commit is contained in:
Jacob Gable 2013-05-23 23:05:52 -05:00 committed by vagrant
commit a758db1c5f
10 changed files with 185 additions and 21 deletions

View File

@ -22,7 +22,8 @@
// Unit test all the things!
nodeunit: {
all: ['core/test/ghost/**/test-*.js']
all: ['core/test/ghost/**/test-*.js'],
api: ['core/test/ghost/test-api.js']
},
// Compile all the SASS!
@ -45,6 +46,9 @@
// TODO: Git submodule init/update (https://github.com/jaubourg/grunt-update-submodules)?
grunt.registerTask("init", ["compass:admin"]);
// Run API tests only
grunt.registerTask("test-api", ["nodeunit:api"]);
// Run tests and lint code
grunt.registerTask("validate", ["jslint", "nodeunit:all"]);
};

6
app.js
View File

@ -25,7 +25,8 @@
ghost.app().configure('development', function () {
ghost.app().use(express.favicon(__dirname + '/content/images/favicon.ico'));
ghost.app().use(express.errorHandler());
ghost.app().use(express.errorHandler({ dumpExceptions: true, showStack: true }));
ghost.app().use(express.logger('dev'));
ghost.app().use(I18n.load(ghost));
ghost.app().use(express.bodyParser());
ghost.app().use(express.cookieParser('try-ghost'));
@ -66,6 +67,9 @@
ghost.app().post('/api/v0.1/posts/create', auth, api.requestHandler(api.posts.add));
ghost.app().put('/api/v0.1/posts/edit', auth, api.requestHandler(api.posts.edit));
ghost.app()['delete']('/api/v0.1/posts/:id', auth, api.requestHandler(api.posts.destroy));
ghost.app().get('/api/v0.1/settings', auth, api.requestHandler(api.settings.browse));
ghost.app().get('/api/v0.1/settings/:key', auth, api.requestHandler(api.settings.read));
ghost.app().put('/api/v0.1/settings/edit', auth, api.requestHandler(api.settings.edit));
/**
* Admin routes..

View File

@ -56,12 +56,19 @@
config.homepage.posts = 4;
config.database = {
testing: {
client: 'sqlite3',
connection: {
filename: './core/shared/data/tests.db'
}
},
development: {
client: 'sqlite3',
connection: {
filename: './core/shared/data/testdb.db'
},
debug: false
debug: true
},
staging: {},

View File

@ -13,7 +13,19 @@
$('.settings-content').fadeOut().delay(250);
$(newPage).fadeIn();
};
},
defaultSettings = {
title: 'My Blog',
description: ''
},
getSettings = function () {
return $.extend(defaultSettings, {
title : $('#blog-title').val(),
description : $('#blog-description').val()
});
};
$(document).ready(function () {
if (location.hash) {
@ -30,6 +42,19 @@
$('input').iCheck({
checkboxClass: 'icheckbox_square-grey'
});
$('.button-save').click(function (e) {
e.preventDefault();
var data = getSettings();
$.ajax({
method: 'PUT',
url: '/api/v0.1/settings/edit',
data: data,
success: function (res, xhr, c) {
console.log(xhr, c);
}
});
});
});
}(jQuery));

View File

@ -131,10 +131,16 @@
});
},
'settings': function (req, res) {
res.render('settings', {
bodyClass: 'settings',
adminNav: setSelected(adminNavbar, 'settings')
});
api.settings.browse()
.then(function (settings) {
settings = settings.toJSON();
settings = _.object(_.pluck(settings, 'key'), _.pluck(settings, 'value'));
res.render('settings', {
bodyClass: 'settings',
adminNav: setSelected(adminNavbar, 'settings'),
settings: settings
});
});
},
'debug': { /* ugly temporary stuff for managing the app before it's properly finished */
index: function (req, res) {

View File

@ -27,11 +27,12 @@
</section>
</header>
<section class="content">
{{#with settings}}
<form id="settings-general">
<fieldset>
<label>
<b>Blog Title</b>
<input id="blog-title" type="text" value="John O'Nolan" />
<input id="blog-title" type="text" value="{{title}}" />
<p>How your blog name appears on the site</p>
</label>
@ -81,7 +82,7 @@
</fieldset>
{{/with}}
</form>
</section>
</section>
@ -128,13 +129,13 @@
<label>
<b>SEO Title Pattern</b>
<input id="blog-title" type="text" value="[Post Name] - [Site Title]" />
<input id="seo-title" type="text" value="[Post Name] - [Site Title]" />
<p>The pattern used to display your title tags</p>
</label>
<label>
<b>SEO Description Pattern</b>
<input id="blog-title" type="text" value="Auto" />
<input id="seo-description" type="text" value="Auto" />
<p>The pattern used to display your meta descriptions</p>
</label>

View File

@ -16,6 +16,7 @@
ghost = new Ghost(),
posts,
users,
settings,
requestHandler;
// # Posts
@ -56,9 +57,22 @@
return when.call(ghost.dataProvider().users.check, postData);
}
};
// settings: {},
// categories: {},
// post_categories: {}
// # Settings
settings = {
browse: function (options) {
return when.call(ghost.dataProvider().settings.browse, options);
},
read: function (options) {
return when.call(ghost.dataProvider().settings.read, options.key);
},
edit: function (options) {
return when.call(ghost.dataProvider().settings.edit, options);
}
};
// categories: {};
// post_categories: {};
// requestHandler
@ -78,5 +92,6 @@
module.exports.posts = posts;
module.exports.users = users;
module.exports.settings = settings;
module.exports.requestHandler = requestHandler;
}());

View File

@ -9,6 +9,10 @@
var knex = require('./knex_init'),
PostsProvider = require('./dataProvider.bookshelf.posts'),
UsersProvider = require('./dataProvider.bookshelf.users'),
models = require('./models'),
bcrypt = require('bcrypt'),
when = require("when"),
_ = require("underscore"),
DataProvider,
instance;
@ -17,8 +21,12 @@
instance = this;
knex.Schema.hasTable('posts').then(null, function () {
// Simple boostraping of the data model for now.
require('../data/migration/001').up().then(function () {
console.log('all done....');
var migration = require('../data/migration/001');
migration.down().then(function() {
migration.up().then(function () {
console.log('all done....');
});
});
});
}
@ -29,5 +37,30 @@
DataProvider.prototype.posts = new PostsProvider();
DataProvider.prototype.users = new UsersProvider();
// ## Settings
DataProvider.prototype.settings = function () { };
DataProvider.prototype.settings.browse = function (_args, callback) {
models.Settings.forge(_args).fetch().then(function (settings) {
callback(null, settings);
}, callback);
};
DataProvider.prototype.settings.read = function (_key, callback) {
models.Setting.forge({ key: _key }).fetch().then(function (setting) {
callback(null, setting);
}, callback);
};
DataProvider.prototype.settings.edit = function (_data, callback) {
when.all(_.map(_data, function (value, key) {
return models.Setting.forge({ key: key }).fetch().then(function (setting) {
return setting.set('value', value).save();
});
})).then(function (settings) {
callback(null, settings);
}, callback);
};
module.exports = DataProvider;
}());

View File

@ -13,7 +13,8 @@
Posts,
User,
Users,
Setting;
Setting,
Settings;
Post = Bookshelf.Model.extend({
@ -75,9 +76,12 @@
});
Setting = Bookshelf.Model.extend({
tableName: 'settings',
hasTimestamps: true
});
tableName: 'settings'
Settings = Bookshelf.Collection.extend({
model: Setting
});
module.exports = {
@ -85,6 +89,7 @@
Posts: Posts,
User: User,
Users: Users,
Setting: Setting
Setting: Setting,
Settings: Settings
};
}());

View File

@ -0,0 +1,64 @@
/*global require, module */
(function () {
"use strict";
// Use 'testing' Ghost config
process.env.NODE_ENV = 'testing';
var fs = require('fs'),
path = require('path'),
_ = require('underscore'),
assert = require('assert'),
delay = require('when/delay'),
config = require('../../../config'),
fixtures = require('../../shared/data/fixtures/001'),
api;
function fail(err) {
process.nextTick(function () {
assert.ifError(err);
});
}
module.exports = {
setUp: function (done) {
// Clear database
var dbpath = path.resolve(__dirname, '../../../', config.database.testing.connection.filename);
fs.unlink(dbpath, function () {
// There is currently no way to tell when Ghost is loaded. api instantiates it's own `Ghost`
// which will run migrations without making the promise externally accessible
api = require('../../shared/api');
// So we just sit for a while :/
setTimeout(done, 3000);
});
},
'settings:browse': function (test) {
test.expect(1);
api.settings.browse().then(function (settings) {
settings = _.map(settings.toJSON(), function (item) {
return _.omit(item, 'id', 'updated_at', 'created_at');
});
test.deepEqual(settings, fixtures.settings);
test.done();
}).then(null, fail);
},
'settings:read': function (test) {
api.settings.read('title', function (setting) {
test.done();
}).then(null, fail);
},
'settings:edit': function (test) {
test.expect(2);
api.settings.edit('title', "Jenna O'Neil").then(function (title) {
title = title.toJSON();
test.equal(title.key, 'title');
test.equal(title.value, "Jenna O'Neil");
test.done();
}).then(null, fail);
}
};
}());