зеркало из https://github.com/mozilla/CSOL-site.git
badges now show correct "playlisted" info on /earn and badge detail pages if they are playlisted. fixes #718
This commit is contained in:
Родитель
495ee328dc
Коммит
fc58d26c03
|
@ -176,7 +176,7 @@ module.exports = function (app) {
|
||||||
var data = req.remote;
|
var data = req.remote;
|
||||||
var user = req.session.user;
|
var user = req.session.user;
|
||||||
|
|
||||||
async.each(data.badges,
|
async.each(data.badges,
|
||||||
function prepForSharing(badge, callback){
|
function prepForSharing(badge, callback){
|
||||||
shareToken.findOrCreate({
|
shareToken.findOrCreate({
|
||||||
shortName: badge.id,
|
shortName: badge.id,
|
||||||
|
@ -346,10 +346,25 @@ module.exports = function (app) {
|
||||||
return [c.value, {label: c.label, badges: shuffle(grouped[c.value]).slice(0, maxPerCat)}];
|
return [c.value, {label: c.label, badges: shuffle(grouped[c.value]).slice(0, maxPerCat)}];
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Construct the user's playlist
|
||||||
|
// Expects that `req.remote.badges` exists and that it is the *full* list
|
||||||
|
// of all badges -- this list is then filtered down by what's in the
|
||||||
|
// playlist table to produce the user's playlist (nb: once/if the openbadger
|
||||||
|
// API supports taking a list of badge shortnames to return badge details
|
||||||
|
// about, retrieving the full list from the API is no longer necessary).
|
||||||
|
var playlist = new Array(req.paylist_ids);
|
||||||
|
_.each(req.remote.badges, function(badge) {
|
||||||
|
if (badge.id in req.playlist_shortnames) {
|
||||||
|
var index = req.playlist_shortnames[badge.id];
|
||||||
|
playlist[index] = badge;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
res.render('user/myplaylist.html', {
|
res.render('user/myplaylist.html', {
|
||||||
user: res.locals.user,
|
user: res.locals.user,
|
||||||
recommended: recommended,
|
recommended: recommended,
|
||||||
playlist: req.playlist
|
playlist: req.playlist,
|
||||||
|
paylist_ids: req.paylist_ids
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ var _ = require('underscore');
|
||||||
var applications = db.model('Application');
|
var applications = db.model('Application');
|
||||||
var evidence = db.model('Evidence');
|
var evidence = db.model('Evidence');
|
||||||
|
|
||||||
|
const playlist = db.model('Playlist');
|
||||||
|
const playlistMiddleware = _.bind(playlist.middleware, playlist);
|
||||||
|
|
||||||
module.exports = function (app) {
|
module.exports = function (app) {
|
||||||
|
|
||||||
function getFilters(query, subset) {
|
function getFilters(query, subset) {
|
||||||
|
@ -221,22 +224,24 @@ module.exports = function (app) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/earn', badger.middleware('getBadges'), function (req, res, next) {
|
app.get('/earn', [badger.middleware('getBadges'),playlistMiddleware], function (req, res, next) {
|
||||||
var data = req.remote;
|
var data = req.remote;
|
||||||
|
|
||||||
res.render('badges/list.html', {
|
res.render('badges/list.html', {
|
||||||
filters: getFilters(req.query, ['categories', 'ageRanges', 'badgeTypes', 'activityTypes', 'search']),
|
filters: getFilters(req.query, ['categories', 'ageRanges', 'badgeTypes', 'activityTypes', 'search']),
|
||||||
items: data.badges,
|
items: data.badges,
|
||||||
page: data.page,
|
page: data.page,
|
||||||
pages: data.pages
|
pages: data.pages,
|
||||||
|
playlist_ids:req.playlist_ids,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/earn/:badgeName', badger.middleware('getBadgeRecommendations', {limit:4}), function (req, res, next) {
|
app.get('/earn/:badgeName', [badger.middleware('getBadgeRecommendations', {limit:4}),playlistMiddleware], function (req, res, next) {
|
||||||
var data = req.remote;
|
var data = req.remote;
|
||||||
res.render('badges/single.html', {
|
res.render('badges/single.html', {
|
||||||
badge: req.params.badge,
|
badge: req.params.badge,
|
||||||
relatedBadges: data.badges
|
relatedBadges: data.badges,
|
||||||
|
playlist_ids:req.playlist_ids,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -30,72 +30,64 @@ module.exports = {
|
||||||
// `add` adds a badge to the user's playlist
|
// `add` adds a badge to the user's playlist
|
||||||
add: function (user, shortName, callback) {
|
add: function (user, shortName, callback) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
this.max('rank', {where: {LearnerId: user.id}})
|
if (user) {
|
||||||
.success(function(rank) {
|
this.max('rank', {where: {LearnerId: user.id}})
|
||||||
_this.create({shortName: shortName, LearnerId: user.id, rank: (rank || 0)+1}).
|
.success(function(rank) {
|
||||||
success(function(item) {
|
_this.create({shortName: shortName, LearnerId: user.id, rank: (rank || 0)+1}).
|
||||||
callback(null, item);
|
success(function(item) {
|
||||||
|
callback(null, item);
|
||||||
|
}).
|
||||||
|
error(function(err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
}).
|
}).
|
||||||
error(function(err) {
|
error(function(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
}).
|
}
|
||||||
error(function(err) {
|
|
||||||
callback(err);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
// `remove` removes a badge from the user's playlist
|
// `remove` removes a badge from the user's playlist
|
||||||
remove: function (user, shortName, callback) {
|
remove: function (user, shortName, callback) {
|
||||||
this.find({where: {LearnerId: user.id, shortName: shortName}}).
|
if (user) {
|
||||||
success(function(item) {
|
this.find({where: {LearnerId: user.id, shortName: shortName}}).
|
||||||
if (item === null) {
|
success(function(item) {
|
||||||
// not treating this as an error condition as the result is what the user wanted to happen anyway: The badge in question is no longer in their playlist.
|
if (item === null) {
|
||||||
logger.log('info', 'playlist.classMethods.remove was unable to find item with learnerid %s and shortname %s', user.id, shortName);
|
// not treating this as an error condition as the result is what the user wanted to happen anyway: The badge in question is no longer in their playlist.
|
||||||
callback(null);
|
logger.log('info', 'playlist.classMethods.remove was unable to find item with learnerid %s and shortname %s', user.id, shortName);
|
||||||
}
|
callback(null);
|
||||||
else {
|
}
|
||||||
item.destroy().success(function() {
|
else {
|
||||||
callback(null);
|
item.destroy().success(function() {
|
||||||
}).error(function(err) {
|
callback(null);
|
||||||
callback(err);
|
}).error(function(err) {
|
||||||
});
|
callback(err);
|
||||||
}
|
});
|
||||||
}).
|
}
|
||||||
error(function(err) {
|
}).
|
||||||
callback(err);
|
error(function(err) {
|
||||||
});
|
callback(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// middleware gets the user's playlist of badges and makes it available via
|
// middleware gets the user's playlist of badges and makes it available via
|
||||||
// `req.playlist`, which is a sorted array of badges.
|
// `req.playlist`, which is a sorted array of badges.
|
||||||
// It expects that `req.remote.badges` exists and that it is the *full* list
|
|
||||||
// of all badges -- this list is then filtered down by what's in the
|
|
||||||
// playlist table to produce the user's playlist (nb: once/if the openbadger
|
|
||||||
// API supports taking a list of badge shortnames to return badge details
|
|
||||||
// about, retrieving the full list from the API is no longer necessary).
|
|
||||||
middleware: function (req, res, next) {
|
middleware: function (req, res, next) {
|
||||||
var badges = req.remote.badges;
|
//var badges = req.remote.badges;
|
||||||
var user = res.locals.user;
|
var user = res.locals.user;
|
||||||
|
var userid = (user) ? user.id : 0;
|
||||||
this.findAll({where: {LearnerId: user.id}, order: 'rank DESC'}).
|
this.findAll({where: {LearnerId: userid}, order: 'rank DESC'}).
|
||||||
success(function(rawList) {
|
success(function(rawList) {
|
||||||
// Make a badge short name -> rank lookup.
|
// Make a badge short name -> rank lookup.
|
||||||
// This serves both as a way to filter down the full badge list into
|
// This serves both as a way to filter down the full badge list into
|
||||||
// the ones in the playlist, as well as to sort the results by rank.
|
// the ones in the playlist, as well as to sort the results by rank.
|
||||||
var shortNames = {}
|
var shortNames = {}
|
||||||
|
var playlist_ids = new Array(rawList.length);
|
||||||
_.each(rawList, function(item, index) {
|
_.each(rawList, function(item, index) {
|
||||||
shortNames[item.shortName] = index;
|
shortNames[item.shortName] = index;
|
||||||
|
playlist_ids.push(item.shortName);
|
||||||
});
|
});
|
||||||
|
req.playlist_shortnames = shortNames;
|
||||||
// Construct the user's playlist
|
req.playlist_ids = playlist_ids;
|
||||||
var playlist = new Array(rawList.length);
|
|
||||||
_.each(badges, function(badge) {
|
|
||||||
if (badge.id in shortNames) {
|
|
||||||
var index = shortNames[badge.id];
|
|
||||||
playlist[index] = badge;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
req.playlist = playlist;
|
|
||||||
|
|
||||||
next();
|
next();
|
||||||
}).
|
}).
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="span4">
|
<div class="span4">
|
||||||
<div class="featured-badge">
|
<div class="featured-badge">
|
||||||
{% set hide_badge_actions = 1 %}
|
|
||||||
{% include "includes/badge-thumbnail.html" %}
|
{% include "includes/badge-thumbnail.html" %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,12 +34,14 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
<br>
|
<br>
|
||||||
|
{% if (not playlist_ids or playlist_ids.indexOf(item.id) < 0) %}
|
||||||
<p>
|
<p>
|
||||||
<form action="/myplaylist" method="POST">
|
<form action="/myplaylist" method="POST">
|
||||||
<input type="hidden" name="shortname" value="{{ item.id }}">
|
<input type="hidden" name="shortname" value="{{ item.id }}">
|
||||||
<button type="submit" class="btn" title="Add to playlist">Add to your playlist</button>
|
<button type="submit" class="btn" title="Add to playlist">Add to your playlist</button>
|
||||||
</form>
|
</form>
|
||||||
</p>
|
</p>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<hr>
|
<hr>
|
||||||
<ul class="tags">
|
<ul class="tags">
|
||||||
|
|
|
@ -4,7 +4,6 @@ Context variables from including template:
|
||||||
|
|
||||||
- item (required)
|
- item (required)
|
||||||
- url (optional)
|
- url (optional)
|
||||||
- playlisted (optional)
|
|
||||||
#}
|
#}
|
||||||
|
|
||||||
{# itemUrl simplifies getting the URL for the badge: it can be set in the
|
{# itemUrl simplifies getting the URL for the badge: it can be set in the
|
||||||
|
@ -17,11 +16,10 @@ doesn't have a URL #}
|
||||||
{{ item.url }}
|
{{ item.url }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
<figure class="thumbnail{% if application %} state-{{ item.state }}{% endif %}">
|
<figure class="thumbnail{% if application %} state-{{ item.state }}{% endif %}">
|
||||||
{% if not application %}
|
{% if not application %}
|
||||||
<div class="playlist-bar text-center{% if playlisted %} in{% endif %}">
|
<div class="playlist-bar text-center{% if playlist_ids and playlist_ids.indexOf(item.id) >= 0 %} in{% endif %}">
|
||||||
{% if not playlisted %}
|
{% if not playlist_ids or playlist_ids.indexOf(item.id) < 0 %}
|
||||||
{% include "includes/add-to-playlist-btn.html" %}
|
{% include "includes/add-to-playlist-btn.html" %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>In Playlist</p>
|
<p>In Playlist</p>
|
||||||
|
@ -55,7 +53,7 @@ doesn't have a URL #}
|
||||||
{% if not hide_badge_actions %}
|
{% if not hide_badge_actions %}
|
||||||
<div class="item-actions row-fluid">
|
<div class="item-actions row-fluid">
|
||||||
<div class="span6">
|
<div class="span6">
|
||||||
{% if playlisted %}
|
{% if playlist_ids and playlist_ids.indexOf(item.id) >= 0 %}
|
||||||
<form action="/myplaylist" method="POST" class="playlist-remove">
|
<form action="/myplaylist" method="POST" class="playlist-remove">
|
||||||
<input type="hidden" name="_method" value="DELETE">
|
<input type="hidden" name="_method" value="DELETE">
|
||||||
<input type="hidden" name="shortname" value="{{ item.id }}">
|
<input type="hidden" name="shortname" value="{{ item.id }}">
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
{% if playlist.length %}
|
{% if playlist.length %}
|
||||||
<ul class="thumbnails">
|
<ul class="thumbnails">
|
||||||
{% for item in playlist %}
|
{% for item in playlist %}
|
||||||
{% set playlisted = true %}
|
|
||||||
<li span="3">
|
<li span="3">
|
||||||
{% include "includes/badge-thumbnail.html" %}
|
{% include "includes/badge-thumbnail.html" %}
|
||||||
</li>
|
</li>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче