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 || {},
req.query || {},
req.body || {},
req.params || {}
req.params || {},
{ session: req.session || {} } // TODO: move session to separate arg
);
method(query, function(err, data) {

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

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

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

@ -1,18 +1,14 @@
const openbadger = require('../openbadger');
const db = require('../db');
const claim = db.model('Claim');
const loggedIn = require('../middleware').loggedIn;
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 user = res.locals.user;
if (!user) {
req.session.afterLogin = req.originalUrl;
return res.redirect('/login');
}
if (!claimCode)
return res.render('claim.html');
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 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({
code: claimCode,
LearnerId: user.id
@ -96,25 +63,17 @@ module.exports = function (app) {
else
req.flash('success', "You've claimed a new badge!");
}
return res.redirect('/backpack');
return res.redirect('/mybadges');
});
}
});
});
app.get('/backpack', function (req, res, next) {
var badges = [];
for (var i = 0; i < 7; ++i) {
badges.push({
thumbnail: '/media/images/badge.png',
description: 'Badge blah in voluptate velit...',
url: '/badges/ae784f'
});
}
app.get('/mybadges', [loggedIn], openbadger.middleware('getUserBadges'), function (req, res, next) {
var data = req.remote;
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) {
var email = query.email;
var code = query.code;
@ -170,7 +191,7 @@ var openbadger = new Api(ENDPOINT, {
this.post('/claim', { json: params }, function(err, data) {
return callback(err, data);
});
}
},
});
module.exports = openbadger;

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

@ -28,8 +28,11 @@ function fakeRequest(func, config, callback) {
// TODO: translating config object to req data is sloppy
var req = _.extend(
{ __proto__: express.request,
headers: {} },
{
__proto__: express.request,
headers: {} ,
session: config.session || {}
},
config
);
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) {
var method = sinon.stub();
var api = new Api(ORIGIN, {
@ -216,7 +238,6 @@ test('api.middleware(method)', function(t) {
fakeRequest(
api.middleware('method'),
function(req, res, next) {
console.log(req);
t.same(req.remote, { result: 1 }, 'req.remote');
t.ok(next.calledOnce, 'next');
t.end();
@ -342,7 +363,6 @@ test('api.get', function(t) {
api.get('/foo', { some: 'params' }, function(){});
t.ok(get.calledOnce, 'called');
console.log(get.args);
t.ok(get.calledWith(
sinon.match(ORIGIN + '/foo'),
sinon.match({ some: 'params' })

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

@ -33,16 +33,13 @@
{% if user %}
{% if user.type == 'learner' %}
<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">
<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 role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}>
<a role="menuitem" tabindex="-1" href="/backpack/favorites">My Favorites</a>
</li>
<li role="presentation"{% if subNavItem == 'badges' %} class="active"{% endif %}>
<a role="menuitem" tabindex="-1" href="/backpack/applications">My Applications</a>
<a role="menuitem" tabindex="-1" href="/myapplications">My Applications</a>
</li>
<li class="divider" role="presentation" aria-hidden="true"></li>
<li role="presentation">

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

@ -3,116 +3,26 @@
{% set navItem = 'backpack' %}
{% block list %}
<li class="span3">
<figure class="thumbnail">
<div class="status awarded">
<img src="/media/images/icon_status_awarded.png" alt="Awarded"/>Awarded
</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 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>
{{ super() }}
<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>
</li>
{% 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 %}
<!-- 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 %}