2013-05-29 19:06:27 +04:00
|
|
|
const Api = require('./api');
|
|
|
|
const async = require('async');
|
|
|
|
const openbadger = require('./openbadger');
|
|
|
|
const errors = require('./lib/errors');
|
|
|
|
const _ = require('underscore');
|
|
|
|
|
|
|
|
const ENDPOINT = process.env['CSOL_AESTIMIA_URL'];
|
2013-05-30 19:39:40 +04:00
|
|
|
const SECRET = process.env['CSOL_AESTIMIA_SECRET'];
|
2013-05-31 12:36:23 +04:00
|
|
|
const CSOL_HOST = process.env['CSOL_HOST'];
|
2013-05-30 19:39:40 +04:00
|
|
|
|
2013-05-29 19:06:27 +04:00
|
|
|
if (!ENDPOINT)
|
|
|
|
throw new Error('Must specify CSOL_AESTIMIA_URL in the environment');
|
|
|
|
|
2013-05-30 19:39:40 +04:00
|
|
|
if (!SECRET)
|
|
|
|
throw new Error('Must specify CSOL_AESTIMIA_SECRET in the environment');
|
|
|
|
|
2013-05-31 12:36:23 +04:00
|
|
|
if (!CSOL_HOST)
|
|
|
|
throw new Error('Must specify CSOL_HOST in the environment');
|
|
|
|
|
2013-05-29 19:06:27 +04:00
|
|
|
var aestimia = new Api(ENDPOINT, {
|
|
|
|
|
|
|
|
submit: function (application, callback) {
|
2013-05-30 19:39:40 +04:00
|
|
|
var api = this;
|
|
|
|
|
2013-05-29 19:06:27 +04:00
|
|
|
application.getLearner()
|
|
|
|
.complete(function (err, learner) {
|
|
|
|
if (err)
|
|
|
|
return callback(err);
|
|
|
|
|
|
|
|
application.getEvidence()
|
|
|
|
.complete(function (err, evidence) {
|
|
|
|
if (err)
|
|
|
|
return callback(err);
|
|
|
|
|
|
|
|
openbadger.getBadge(application.badgeId, function (err, data) {
|
|
|
|
var badge = data.badge;
|
|
|
|
|
|
|
|
// console.log('Application:', application);
|
|
|
|
// console.log('Learner:', learner);
|
|
|
|
// console.log('Evidence:', evidence);
|
|
|
|
// console.log('Badge:', badge);
|
|
|
|
|
|
|
|
var submission = {
|
2013-05-31 18:25:04 +04:00
|
|
|
criteriaUrl: api.getFullUrl(CSOL_HOST, badge.url),
|
|
|
|
onChangeUrl: api.getFullUrl(CSOL_HOST, '/applications'),
|
2013-05-29 19:06:27 +04:00
|
|
|
achievement: {
|
|
|
|
name: badge.name,
|
|
|
|
description: badge.description,
|
|
|
|
imageUrl: badge.image
|
|
|
|
},
|
2013-05-31 18:25:04 +04:00
|
|
|
classifications: badge.categories || [],
|
2013-05-29 19:06:27 +04:00
|
|
|
evidence: [],
|
2013-05-31 18:25:04 +04:00
|
|
|
rubric: badge.rubric || {items: [{text: 'Has done some work', required: true}]}
|
2013-05-29 19:06:27 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (learner.email)
|
|
|
|
submission.learner = learner.email;
|
|
|
|
|
2013-05-31 18:25:04 +04:00
|
|
|
if (learner.underage)
|
|
|
|
submission.cannedResponses = [
|
|
|
|
'You did a great job!',
|
|
|
|
'You went above and beyond.',
|
|
|
|
'Keep up the good work!',
|
|
|
|
'Good job.',
|
|
|
|
'You met all the criteria needed to earn this badge.',
|
|
|
|
'Creative and thoughtful work.',
|
|
|
|
'Nice reflection of your work.',
|
|
|
|
'You didn\'t submit relevant evidence.',
|
|
|
|
'Your evidence did not properly reflect the criteria.',
|
|
|
|
'Good work! But you still have a few criteria to meet to earn this badge. Make sure you take a look at all the criteria before reapplying.'
|
|
|
|
];
|
|
|
|
|
2013-05-30 19:39:40 +04:00
|
|
|
evidence.forEach(function(item, index) {
|
|
|
|
var obj = {
|
2013-05-31 18:25:04 +04:00
|
|
|
url: api.getFullUrl(CSOL_HOST, item.getLocationUrl()),
|
2013-05-31 12:36:23 +04:00
|
|
|
mediaType: item.mediaType.split('/')[0]
|
2013-05-30 19:39:40 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (!index && application.description)
|
|
|
|
obj.reflection = application.description;
|
|
|
|
|
|
|
|
submission.evidence.push(obj);
|
2013-05-29 19:06:27 +04:00
|
|
|
});
|
|
|
|
|
2013-05-31 12:36:23 +04:00
|
|
|
api.post('/submission', {json:submission}, function (err, rsp) {
|
|
|
|
if (err)
|
|
|
|
return callback(err);
|
2013-05-29 19:06:27 +04:00
|
|
|
|
2013-05-31 12:36:23 +04:00
|
|
|
callback(null, (rsp||{}).id);
|
2013-05-30 19:39:40 +04:00
|
|
|
});
|
2013-05-29 19:06:27 +04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2013-05-31 18:25:04 +04:00
|
|
|
},
|
|
|
|
|
|
|
|
update: function (application, callback) {
|
|
|
|
var api = this;
|
|
|
|
|
|
|
|
var submissionId = application.submissionId;
|
2013-05-31 20:00:32 +04:00
|
|
|
var latestReview = application.getReview();
|
2013-05-31 18:25:04 +04:00
|
|
|
|
|
|
|
if (!submissionId)
|
|
|
|
return callback('Application has not yet been submitted');
|
|
|
|
|
|
|
|
this.get('/submissions/' + submissionId, function (err, submission) {
|
|
|
|
var rubrics = submission.rubric.items;
|
|
|
|
var reviews = submission.reviews;
|
|
|
|
|
2013-05-31 20:00:32 +04:00
|
|
|
// Bail early, if there are no reviews
|
2013-05-31 18:25:04 +04:00
|
|
|
if (!reviews.length)
|
|
|
|
return callback(null, application);
|
|
|
|
|
2013-05-31 20:00:32 +04:00
|
|
|
// Sort the reviews by (ascending) date, if required
|
2013-05-31 18:25:04 +04:00
|
|
|
if (reviews.length > 1) {
|
|
|
|
reviews.sort(function(a, b) {
|
|
|
|
if (a.date === b.date)
|
|
|
|
return 0;
|
|
|
|
return a.date < b.date;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-05-31 20:00:32 +04:00
|
|
|
// Take the most recent review
|
2013-05-31 18:25:04 +04:00
|
|
|
var review = reviews.pop();
|
|
|
|
|
2013-05-31 20:00:32 +04:00
|
|
|
// If we've already seen it, bail
|
|
|
|
if (review._id === latestReview._id)
|
2013-05-31 18:25:04 +04:00
|
|
|
return callback(null, application);
|
|
|
|
|
|
|
|
var satisfiedRubrics = review.satisfiedRubrics;
|
|
|
|
var satisfied = false;
|
|
|
|
|
2013-05-31 20:00:32 +04:00
|
|
|
// If something is satisfied, see if it's enough to award the badge
|
2013-05-31 18:25:04 +04:00
|
|
|
if (satisfiedRubrics.length) {
|
|
|
|
satisfied = true;
|
|
|
|
|
|
|
|
rubrics.forEach(function (rubric, index) {
|
2013-05-31 20:00:32 +04:00
|
|
|
var rubricSatisfied = !rubric.required || (satisfiedRubrics.indexOf(index) >= 0);
|
|
|
|
satisfied &= rubricSatisfied;
|
2013-05-31 18:25:04 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
var state = satisfied ? 'accepted' : 'rejected';
|
|
|
|
|
|
|
|
if (state !== application.state) {
|
|
|
|
// TO DO - email applicant about change of application state
|
|
|
|
}
|
|
|
|
|
|
|
|
application.updateAttributes({
|
|
|
|
state: state,
|
2013-05-31 20:00:32 +04:00
|
|
|
latestReview: JSON.stringify(review)
|
2013-05-31 18:25:04 +04:00
|
|
|
})
|
|
|
|
.complete(function(err) {
|
|
|
|
if (err)
|
|
|
|
return callback(err, application);
|
|
|
|
|
|
|
|
callback(null, application);
|
|
|
|
});
|
|
|
|
});
|
2013-05-29 19:06:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
2013-05-30 19:39:40 +04:00
|
|
|
aestimia.defaultOptions = {
|
|
|
|
auth: {
|
|
|
|
username: 'api',
|
|
|
|
password: SECRET,
|
2013-05-31 12:36:23 +04:00
|
|
|
sendImmediately: false
|
2013-05-30 19:39:40 +04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-06-04 00:30:31 +04:00
|
|
|
module.exports = aestimia;
|
|
|
|
module.exports.healthCheck = function(cb) {
|
|
|
|
// A random email should guarantee we bust through any caches.
|
|
|
|
var email = 'healthCheck_test_' +
|
|
|
|
Math.floor(Math.random() * 100000) + '@mozilla.org';
|
|
|
|
|
|
|
|
aestimia.get('/submissions?learner=' + encodeURIComponent(email), cb);
|
|
|
|
};
|