зеркало из https://github.com/mozilla/CSOL-site.git
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:
Родитель
a5a92918c2
Коммит
9d7b65d500
3
api.js
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 -->
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends 'layout.html' %}
|
||||||
|
{% set navitem = 'backpack' %}
|
||||||
|
{% set pageTitle = badge.name %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
hooray
|
||||||
|
{% endblock %}
|
Загрузка…
Ссылка в новой задаче