Change /backpack/badges to /mybadges

Remove /backpack
Require login for /mybadges
Add openbadger method to fetch user badges
Add session to query object passed to api methods
Basic /mybadges display (doesn't really work until openbadger changes are made)
This commit is contained in:
Mike Larsson 2013-05-30 14:00:19 -04:00
Родитель a5a92918c2
Коммит 9d7b65d500
9 изменённых файлов: 93 добавлений и 169 удалений

3
api.js
Просмотреть файл

@ -27,7 +27,8 @@ function middleware (method, default_query) {
default_query || {}, default_query || {},
req.query || {}, req.query || {},
req.body || {}, req.body || {},
req.params || {} req.params || {},
{ session: req.session || {} } // TODO: move session to separate arg
); );
method(query, function(err, data) { method(query, function(err, data) {

Просмотреть файл

@ -67,7 +67,7 @@ function extractUserData (user) {
if ('home' in user) return user; if ('home' in user) return user;
var userType = user.daoFactoryName.toLowerCase(); var userType = user.daoFactoryName.toLowerCase();
var userHome = (userType === 'learner') ? '/backpack' : '/dashboard'; var userHome = (userType === 'learner') ? '/mybadges' : '/dashboard';
return { return {
id: user.id, id: user.id,

Просмотреть файл

@ -1,18 +1,14 @@
const openbadger = require('../openbadger'); const openbadger = require('../openbadger');
const db = require('../db'); const db = require('../db');
const claim = db.model('Claim'); const claim = db.model('Claim');
const loggedIn = require('../middleware').loggedIn;
module.exports = function (app) { module.exports = function (app) {
app.get('/claim', function (req, res, next) { app.get('/claim', [loggedIn], function (req, res, next) {
var claimCode = req.query.code; var claimCode = req.query.code;
var user = res.locals.user; var user = res.locals.user;
if (!user) {
req.session.afterLogin = req.originalUrl;
return res.redirect('/login');
}
if (!claimCode) if (!claimCode)
return res.render('claim.html'); return res.render('claim.html');
claimCode = claimCode.trim(); claimCode = claimCode.trim();
@ -42,39 +38,10 @@ module.exports = function (app) {
}); });
app.post('/claim', function (req, res, next) { app.post('/claim', [loggedIn], function (req, res, next) {
var claimCode = req.query.code; var claimCode = req.query.code;
var user = res.locals.user; var user = res.locals.user;
if (!user) {
return res.redirect('/login');
}
openbadger.claim({
code: claimCode,
email: user.email
}, function(err, data) {
console.log(err, data);
if (err)
if (err.code === 409)
req.flash('warn', "You already have that badge.");
else
req.flash('error', "There has been an error claiming your badge.");
else
req.flash('success', "You've claimed a new badge!");
return res.redirect('/backpack');
});
});
app.post('/claim', function (req, res, next) {
var claimCode = req.query.code;
var user = res.locals.user;
if (!user) {
return res.redirect('/login');
}
claim.findOrCreate({ claim.findOrCreate({
code: claimCode, code: claimCode,
LearnerId: user.id LearnerId: user.id
@ -96,25 +63,17 @@ module.exports = function (app) {
else else
req.flash('success', "You've claimed a new badge!"); req.flash('success', "You've claimed a new badge!");
} }
return res.redirect('/backpack'); return res.redirect('/mybadges');
}); });
} }
}); });
}); });
app.get('/backpack', function (req, res, next) { app.get('/mybadges', [loggedIn], openbadger.middleware('getUserBadges'), function (req, res, next) {
var badges = []; var data = req.remote;
for (var i = 0; i < 7; ++i) {
badges.push({
thumbnail: '/media/images/badge.png',
description: 'Badge blah in voluptate velit...',
url: '/badges/ae784f'
});
}
res.render('user/backpack.html', { res.render('user/backpack.html', {
items: badges items: data.badges
}); });
}); });

Просмотреть файл

@ -25,3 +25,12 @@ exports.session = function session (config) {
}) })
}); });
}; };
exports.loggedIn = function loggedIn(req, res, next) {
var user = req.session.user;
if (!user) {
req.session.afterLogin = req.originalUrl;
return res.redirect('/login');
}
return next();
}

Просмотреть файл

@ -146,6 +146,27 @@ var openbadger = new Api(ENDPOINT, {
}); });
}, },
getUserBadges: {
func: function getUserBadges (query, callback) {
var email = query.session.user.email;
var code = query.code;
var params = {
auth: getJWTToken(email),
email: email
};
this.get('/user', { qs: params }, function(err, data) {
if (err)
return callback(err, data);
return callback(null, {
badges: _.map(data.badges, normalizeBadge)
});
});
},
paginate: true,
key: 'badges'
},
getBadgeFromCode: function getBadgeFromCode (query, callback) { getBadgeFromCode: function getBadgeFromCode (query, callback) {
var email = query.email; var email = query.email;
var code = query.code; var code = query.code;
@ -170,7 +191,7 @@ var openbadger = new Api(ENDPOINT, {
this.post('/claim', { json: params }, function(err, data) { this.post('/claim', { json: params }, function(err, data) {
return callback(err, data); return callback(err, data);
}); });
} },
}); });
module.exports = openbadger; module.exports = openbadger;

Просмотреть файл

@ -28,8 +28,11 @@ function fakeRequest(func, config, callback) {
// TODO: translating config object to req data is sloppy // TODO: translating config object to req data is sloppy
var req = _.extend( var req = _.extend(
{ __proto__: express.request, {
headers: {} }, __proto__: express.request,
headers: {} ,
session: config.session || {}
},
config config
); );
req.headers = {'x-requested-with': config.xhr ? 'XmlHttpRequest' : 'Whatever'}; req.headers = {'x-requested-with': config.xhr ? 'XmlHttpRequest' : 'Whatever'};
@ -194,6 +197,25 @@ test('api.middleware(method)', function(t) {
); );
}); });
t.test('query object contains session', function(t) {
var method = sinon.stub();
var api = new Api(ORIGIN, {
method: method
});
fakeRequest(
api.middleware('method'),
{
session: { some: 'sessionstuff' }
},
function(req, res, next) {
t.ok(method.calledWith(
sinon.match({ session: { some: 'sessionstuff' }})
), 'session in query obj');
t.end();
}
);
});
t.test('query object contains default params', function(t) { t.test('query object contains default params', function(t) {
var method = sinon.stub(); var method = sinon.stub();
var api = new Api(ORIGIN, { var api = new Api(ORIGIN, {
@ -216,7 +238,6 @@ test('api.middleware(method)', function(t) {
fakeRequest( fakeRequest(
api.middleware('method'), api.middleware('method'),
function(req, res, next) { function(req, res, next) {
console.log(req);
t.same(req.remote, { result: 1 }, 'req.remote'); t.same(req.remote, { result: 1 }, 'req.remote');
t.ok(next.calledOnce, 'next'); t.ok(next.calledOnce, 'next');
t.end(); t.end();
@ -342,7 +363,6 @@ test('api.get', function(t) {
api.get('/foo', { some: 'params' }, function(){}); api.get('/foo', { some: 'params' }, function(){});
t.ok(get.calledOnce, 'called'); t.ok(get.calledOnce, 'called');
console.log(get.args);
t.ok(get.calledWith( t.ok(get.calledWith(
sinon.match(ORIGIN + '/foo'), sinon.match(ORIGIN + '/foo'),
sinon.match({ some: 'params' }) sinon.match({ some: 'params' })

Просмотреть файл

@ -33,16 +33,13 @@
{% if user %} {% if user %}
{% if user.type == 'learner' %} {% if user.type == 'learner' %}
<li class="dropdown backpack{% if navItem == 'backpack' %} active{% endif %}"> <li class="dropdown backpack{% if navItem == 'backpack' %} active{% endif %}">
<a href="/backpack" class="dropdown-toggle" role="button" data-toggle="dropdown" id="backpack-menu-toggle">My Backpack <i class="caret"></i></a> <a class="dropdown-toggle" role="button" data-toggle="dropdown" id="backpack-menu-toggle">My Backpack <i class="caret"></i></a>
<ul class="dropdown-menu" role="menu" id="backpack-menu" aria-labelledby="backpack-menu-toggle"> <ul class="dropdown-menu" role="menu" id="backpack-menu" aria-labelledby="backpack-menu-toggle">
<li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}> <li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}>
<a role="menuitem" tabindex="-1" href="/backpack/badges">My Badges</a> <a role="menuitem" tabindex="-1" href="/mybadges">My Badges</a>
</li> </li>
<li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}> <li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}>
<a role="menuitem" tabindex="-1" href="/backpack/favorites">My Favorites</a> <a role="menuitem" tabindex="-1" href="/myapplications">My Applications</a>
</li>
<li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}>
<a role="menuitem" tabindex="-1" href="/backpack/applications">My Applications</a>
</li> </li>
<li class="divider" role="presentation" aria-hidden="true"></li> <li class="divider" role="presentation" aria-hidden="true"></li>
<li role="presentation"> <li role="presentation">

Просмотреть файл

@ -3,116 +3,26 @@
{% set navItem = 'backpack' %} {% set navItem = 'backpack' %}
{% block list %} {% block list %}
<li class="span3"> {{ super() }}
<figure class="thumbnail"> <li class="span3">
<div class="status awarded"> <figure class="thumbnail">
<img src="/media/images/icon_status_awarded.png" alt="Awarded"/>Awarded <a href="/claim"><img src="/media/images/add-badge.png"></a>
</div><!-- .status --> <figcaption class="caption">
<p>Claim another badge!</p>
<a href="/badges/ae784f"> <p class="text-right"><a href="/claim" class="btn">+1</a></p>
<img src="http://placehold.it/180x180"> </figcaption>
<span class="new">New</span> </figure>
</a> </li>
<figcaption class="caption clearfix">
<p>Pulvinar? Phasellus eu sagittis adipiscing tristique massa.</p>
<p class="pull-left">
<a href="#trashModal" data-toggle="modal" class="btn show-tooltip" title="Trash"><i class="icon-trash"></i></a>
</p>
<p class="pull-right">
<a href="#shareModal" data-toggle="modal" class="btn show-tooltip" title="Share"><i class="icon-share-alt"></i></a>
<a href="/badges/ae784f" class="btn">Details</a>
</p>
</figcaption>
</figure>
</li>
<li class="span3">
<figure class="thumbnail">
<div class="status queued">
<img src="/media/images/icon_status_queue.png" alt="In Queue"/>In Queue
</div><!-- .status -->
<a href="/badges/ae784f">
<img src="http://placehold.it/180x180">
<span class="new">New</span>
</a>
<figcaption class="caption clearfix">
<p>Pulvinar? Phasellus eu sagittis adipiscing tristique massa.</p>
<p class="pull-left">
<a href="#trashModal" data-toggle="modal" class="btn show-tooltip" title="Trash"><i class="icon-trash"></i></a>
</p>
<p class="pull-right">
<a href="#shareModal" data-toggle="modal" class="btn show-tooltip" title="Share"><i class="icon-share-alt"></i></a>
<a href="/badges/ae784f" class="btn">Details</a>
</p>
</figcaption>
</figure>
</li>
<li class="span3">
<figure class="thumbnail">
<div class="status reviewed">
<img src="/media/images/icon_status_reviewed.png" alt="Reviewed"/>Reviewed
<div class="favorite"></div>
</div><!-- .status -->
<a href="/badges/ae784f">
<img src="http://placehold.it/180x180">
<span class="new">New</span>
</a>
<figcaption class="caption clearfix">
<p>Pulvinar? Phasellus eu sagittis adipiscing tristique massa.</p>
<p class="pull-left">
<a href="#trashModal" data-toggle="modal" class="btn show-tooltip" title="Trash"><i class="icon-trash"></i></a>
</p>
<p class="pull-right">
<a href="#shareModal" data-toggle="modal" class="btn show-tooltip" title="Share"><i class="icon-share-alt"></i></a>
<a href="/badges/ae784f" class="btn">Details</a>
</p>
</figcaption>
</figure>
</li>
<li class="span3">
<figure class="thumbnail">
<div class="status favorite">
<img src="/media/images/icon_status_favorite.png" alt="Favorite"/>Favorite
</div><!-- .status -->
<a href="/badges/ae784f">
<img src="http://placehold.it/180x180">
<span class="new">New</span>
</a>
<figcaption class="caption clearfix">
<p>Pulvinar? Phasellus eu sagittis adipiscing tristique massa.</p>
<p class="pull-left">
<a href="#trashModal" data-toggle="modal" class="btn show-tooltip" title="Trash"><i class="icon-trash"></i></a>
</p>
<p class="pull-right">
<a href="#shareModal" data-toggle="modal" class="btn show-tooltip" title="Share"><i class="icon-share-alt"></i></a>
<a href="/badges/ae784f" class="btn">Details</a>
</p>
</figcaption>
</figure>
</li>
<li class="span3">
<figure class="thumbnail">
<a href="/claim"><img src="/media/images/add-badge.png"></a>
<figcaption class="caption">
<p>Claim another badge!</p>
<p class="text-right"><a href="/claim" class="btn">+1</a></p>
</figcaption>
</figure>
</a>
</li>
{% endblock %} {% endblock %}
{% block item_actions %}
{#
{{ super() }}
<a class="btn show-tooltip" title="Add to your favorites" href="{{ item.url }}/favorite"><i class="icon-heart"></i></a>
#}
{% endblock %}
{% block modal %} {% block modal %}
<!-- Modal --> <!-- Modal -->

7
views/user/badge.html Normal file
Просмотреть файл

@ -0,0 +1,7 @@
{% extends 'layout.html' %}
{% set navitem = 'backpack' %}
{% set pageTitle = badge.name %}
{% block content %}
hooray
{% endblock %}