Persisting completion of bonfire challenges into User model, split routes for bonfires and challenges, refactored class selectors to be challenge type specific
This commit is contained in:
69
app.js
69
app.js
@ -251,7 +251,7 @@ app.all('/account', passportConf.isAuthenticated);
|
|||||||
app.get('/account/api', userController.getAccountAngular);
|
app.get('/account/api', userController.getAccountAngular);
|
||||||
app.get('/bonfire', bonfireController.index);
|
app.get('/bonfire', bonfireController.index);
|
||||||
app.get(
|
app.get(
|
||||||
'/bonfire/:bonfireNumber',
|
'/bonfires/:bonfireNumber',
|
||||||
bonfireController.returnBonfire
|
bonfireController.returnBonfire
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -274,29 +274,68 @@ app.get('/account/unlink/:provider', userController.getOauthUnlink);
|
|||||||
app.post('/completed-challenge', function (req, res) {
|
app.post('/completed-challenge', function (req, res) {
|
||||||
req.user.challengesHash[parseInt(req.body.challengeNumber)] =
|
req.user.challengesHash[parseInt(req.body.challengeNumber)] =
|
||||||
Math.round(+new Date() / 1000);
|
Math.round(+new Date() / 1000);
|
||||||
var ch = req.user.challengesHash;
|
var timestamp = req.user.challengesHash;
|
||||||
var p = 0;
|
var points = 0;
|
||||||
for (var k in ch) {
|
for (var key in timestamp) {
|
||||||
if (ch[k] > 0) {
|
if (timestamp[key] > 0) {
|
||||||
p += 1;
|
points += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.user.points = p;
|
req.user.points = points;
|
||||||
req.user.save();
|
req.user.save();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/completed-bonfire/', function (req, res) {
|
app.post('/completed-bonfire/', function (req, res) {
|
||||||
req.user.challengesHash[parseInt(req.body.challengeNumber)] =
|
debug(req.body, 'In post method'); // TODO: remove debug statement
|
||||||
|
req.user.bonfiresHash[parseInt(req.body.bonfireNumber)] =
|
||||||
Math.round(+new Date() / 1000);
|
Math.round(+new Date() / 1000);
|
||||||
var ch = req.user.challengesHash;
|
var timestamp = req.user.bonfiresHash;
|
||||||
var p = 0;
|
var points = 0;
|
||||||
for (var k in ch) {
|
for (var key in timestamp) {
|
||||||
if (ch[k] > 0) {
|
if (timestamp[key] > 0) {
|
||||||
p += 1;
|
points += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.user.points = p;
|
|
||||||
req.user.save();
|
var isCompletedWith = req.body.bonfireInfo.completedWith || undefined;
|
||||||
|
var isCompletedDate = Math.round(+new Date() / 1000);
|
||||||
|
var bonfireHash = req.body.bonfireInfo.bonfireHash;
|
||||||
|
var isSolution = req.body.bonfireInfo.solution;
|
||||||
|
req.user.bonfiresHash[bonfireHash] = {
|
||||||
|
completedWith: isCompletedWith,
|
||||||
|
completedDate: isCompletedDate,
|
||||||
|
solution: isSolution
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isCompletedWith) {
|
||||||
|
User.find({"profile.username": isCompletedWith}, function(err, pairedWith) {
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
pairedWith.bonfiresHash[bonfireHash] = {
|
||||||
|
completedWith: req.user._id,
|
||||||
|
completedDate: isCompletedDate,
|
||||||
|
solution: isSolution
|
||||||
|
};
|
||||||
|
req.user.bonfiresHash[bonfireHash] = {
|
||||||
|
completedWith: pairedWith._id,
|
||||||
|
completedDate: isCompletedDate,
|
||||||
|
solution: isSolution
|
||||||
|
};
|
||||||
|
|
||||||
|
req.user.save();
|
||||||
|
pairedWith.save();
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
req.user.bonfiresHash[bonfireHash] = {
|
||||||
|
completedWith: null,
|
||||||
|
completedDate: isCompletedDate,
|
||||||
|
solution: isSolution
|
||||||
|
};
|
||||||
|
req.user.save();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +56,9 @@ exports.returnBonfire = function(req, res, next) {
|
|||||||
debug('bonfire err: ', err);
|
debug('bonfire err: ', err);
|
||||||
next(err);
|
next(err);
|
||||||
}
|
}
|
||||||
|
debug(bonfire[bonfireNumber]._id);
|
||||||
res.render('bonfire/show', {
|
res.render('bonfire/show', {
|
||||||
|
completedWith: null,
|
||||||
title: bonfire[bonfireNumber].name,
|
title: bonfire[bonfireNumber].name,
|
||||||
name: bonfire[bonfireNumber].name,
|
name: bonfire[bonfireNumber].name,
|
||||||
number: bonfire[bonfireNumber].bonfireNumber,
|
number: bonfire[bonfireNumber].bonfireNumber,
|
||||||
@ -69,7 +71,8 @@ exports.returnBonfire = function(req, res, next) {
|
|||||||
points: req.user ? req.user.points : undefined,
|
points: req.user ? req.user.points : undefined,
|
||||||
verb: verbs[Math.floor(Math.random() * verbs.length)],
|
verb: verbs[Math.floor(Math.random() * verbs.length)],
|
||||||
phrase: phrases[Math.floor(Math.random() * phrases.length)],
|
phrase: phrases[Math.floor(Math.random() * phrases.length)],
|
||||||
bonfires: bonfire
|
bonfires: bonfire,
|
||||||
|
bonfireHash: bonfire[bonfireNumber]._id
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
255
models/User.js
255
models/User.js
@ -354,247 +354,24 @@ var userSchema = new mongoose.Schema({
|
|||||||
resetPasswordToken: String,
|
resetPasswordToken: String,
|
||||||
resetPasswordExpires: Date,
|
resetPasswordExpires: Date,
|
||||||
bonfiresHash: {
|
bonfiresHash: {
|
||||||
0: {
|
aaa48de84e1ecc7c742e1124: {
|
||||||
type: Boolean,
|
completedWith: String,
|
||||||
default: 0
|
completedDate: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
solution: String
|
||||||
},
|
},
|
||||||
1: {
|
ff0395860f5d3034dc0bfc94: {
|
||||||
type: Boolean,
|
completedWith: String,
|
||||||
default: 0
|
completedDate: {
|
||||||
},
|
type: Number,
|
||||||
2: {
|
default: 0
|
||||||
type: Boolean,
|
},
|
||||||
default: 0
|
solution: String
|
||||||
},
|
|
||||||
3: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
4: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
5: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
6: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
7: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
8: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
9: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
10: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
11: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
12: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
13: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
14: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
15: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
16: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
17: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
18: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
19: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
20: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
21: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
22: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
23: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
24: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
25: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
26: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
27: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
28: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
29: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
30: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
31: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
32: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
33: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
34: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
35: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
36: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
37: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
38: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
39: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
40: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
41: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
42: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
43: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
44: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
45: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
46: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
47: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
48: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
49: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
50: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
51: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
52: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
53: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
54: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
55: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
56: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
57: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
58: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
},
|
|
||||||
59: {
|
|
||||||
type: Boolean,
|
|
||||||
default: 0
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
bonfires: Array
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -231,7 +231,6 @@ var runTests = function(err, data) {
|
|||||||
allTestsPassed = false;
|
allTestsPassed = false;
|
||||||
showCompletion();
|
showCompletion();
|
||||||
}
|
}
|
||||||
console.log(allTestsPassed);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function showCompletion() {
|
function showCompletion() {
|
||||||
|
@ -33,7 +33,7 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.completed-bonfire').on('click', function() {
|
function completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash) {
|
||||||
$('#complete-bonfire-dialog').modal('show');
|
$('#complete-bonfire-dialog').modal('show');
|
||||||
// Only post to server if there is an authenticated user
|
// Only post to server if there is an authenticated user
|
||||||
if ($('.signup-btn-nav').length < 1) {
|
if ($('.signup-btn-nav').length < 1) {
|
||||||
@ -41,11 +41,18 @@ $(document).ready(function() {
|
|||||||
cn = l[l.length - 1];
|
cn = l[l.length - 1];
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: {bonfireHash: cn},
|
data: {
|
||||||
|
bonfireInfo: {
|
||||||
|
completedWith : didCompleteWith,
|
||||||
|
solution: bonfireSolution,
|
||||||
|
bonfireHash: thisBonfireHash
|
||||||
|
}
|
||||||
|
},
|
||||||
url: '/completed-bonfire/'
|
url: '/completed-bonfire/'
|
||||||
});
|
});
|
||||||
|
console.log(didCompleteWith, bonfireSolution, thisBonfireHash); // TODO: remove debug statement
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
$('.all-challenges').on('click', function() {
|
$('.all-challenges').on('click', function() {
|
||||||
$('#all-challenges-dialog').modal('show');
|
$('#all-challenges-dialog').modal('show');
|
||||||
@ -55,10 +62,21 @@ $(document).ready(function() {
|
|||||||
$('#all-bonfires-dialog').modal('show');
|
$('#all-bonfires-dialog').modal('show');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.next-button').on('click', function() {
|
$('.next-challenge-button').on('click', function() {
|
||||||
l = location.pathname.split('/');
|
l = location.pathname.split('/');
|
||||||
window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
|
window.location = '/challenges/' + (parseInt(l[l.length - 1]) + 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: refactor this to create meaningful variable names, what the heck i l?
|
||||||
|
$('.next-bonfire-button').on('click', function() {
|
||||||
|
var bonfireSolution = myCodeMirror.getValue();
|
||||||
|
var thisBonfireHash = passedBonfireHash || null;
|
||||||
|
var didCompleteWith = $('#completed-with').text() || null;
|
||||||
|
console.log(bonfireSolution, thisBonfireHash);
|
||||||
|
completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash);
|
||||||
|
l = location.pathname.split('/');
|
||||||
|
window.location = '/bonfires/' + (parseInt(l[l.length - 1]) + 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var profileValidation = angular.module('profileValidation',['ui.bootstrap']);
|
var profileValidation = angular.module('profileValidation',['ui.bootstrap']);
|
||||||
|
@ -45,8 +45,11 @@ block content
|
|||||||
var tests = !{JSON.stringify(tests)};
|
var tests = !{JSON.stringify(tests)};
|
||||||
var challengeSeed = !{JSON.stringify(challengeSeed)};
|
var challengeSeed = !{JSON.stringify(challengeSeed)};
|
||||||
var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)};
|
var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)};
|
||||||
|
var passedBonfireHash = !{JSON.stringify(bonfireHash)};
|
||||||
|
console.log(passedBonfireHash);
|
||||||
script(src='/js/lib/bonfire/bonfireFramework.js')
|
script(src='/js/lib/bonfire/bonfireFramework.js')
|
||||||
|
|
||||||
|
|
||||||
#complete-bonfire-dialog.modal(tabindex='-1')
|
#complete-bonfire-dialog.modal(tabindex='-1')
|
||||||
.modal-dialog.animated.zoomIn.fast-animation
|
.modal-dialog.animated.zoomIn.fast-animation
|
||||||
.modal-content
|
.modal-content
|
||||||
@ -57,9 +60,12 @@ block content
|
|||||||
.animated.zoomInDown.delay-half
|
.animated.zoomInDown.delay-half
|
||||||
span.landing-icon.ion-checkmark-circled.text-primary
|
span.landing-icon.ion-checkmark-circled.text-primary
|
||||||
- if (cc)
|
- if (cc)
|
||||||
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge
|
|
||||||
|
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-bonfire-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge
|
||||||
|
|
||||||
|
|
||||||
- if (points && points > 2)
|
- if (points && points > 2)
|
||||||
a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20Free%20Code%20Camp%20Challenge%20%23#{number}:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{number}&hashtags=learntocode, javascript" target="_blank")
|
a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20Free%20Code%20Camp%20Challenge%20%23#{number}:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{number}&hashtags=learntocode, javascript" target="_blank")
|
||||||
i.fa.fa-twitter
|
i.fa.fa-twitter
|
||||||
= phrase
|
= phrase
|
||||||
- else
|
- else
|
||||||
@ -67,7 +73,7 @@ block content
|
|||||||
#all-bonfires-dialog.modal(tabindex='-1')
|
#all-bonfires-dialog.modal(tabindex='-1')
|
||||||
.modal-dialog.animated.fadeInUp.fast-animation
|
.modal-dialog.animated.fadeInUp.fast-animation
|
||||||
.modal-content
|
.modal-content
|
||||||
.modal-header.challenge-list-header Challenges
|
.modal-header.challenge-list-header Bonfires
|
||||||
a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') ×
|
a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') ×
|
||||||
.modal-body
|
.modal-body
|
||||||
include ../partials/bonfires
|
include ../partials/bonfires
|
||||||
|
@ -26,7 +26,7 @@ block content
|
|||||||
.animated.zoomInDown.delay-half
|
.animated.zoomInDown.delay-half
|
||||||
span.landing-icon.ion-checkmark-circled.text-primary
|
span.landing-icon.ion-checkmark-circled.text-primary
|
||||||
- if (cc)
|
- if (cc)
|
||||||
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge
|
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-challenge-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge
|
||||||
- if (points && points > 2)
|
- if (points && points > 2)
|
||||||
a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20Free%20Code%20Camp%20Challenge%20%23#{number}:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{number}&hashtags=learntocode, javascript" target="_blank")
|
a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20Free%20Code%20Camp%20Challenge%20%23#{number}:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{number}&hashtags=learntocode, javascript" target="_blank")
|
||||||
i.fa.fa-twitter
|
i.fa.fa-twitter
|
||||||
|
Reference in New Issue
Block a user