update to automatically redirect based on highest completed challenge hash value
This commit is contained in:
28
app.js
28
app.js
@ -133,7 +133,9 @@ app.get('/privacy', resourcesController.privacy);
|
|||||||
app.get('/jquery-exercises', resourcesController.jqueryExercises);
|
app.get('/jquery-exercises', resourcesController.jqueryExercises);
|
||||||
app.get('/chromebook', resourcesController.chromebook);
|
app.get('/chromebook', resourcesController.chromebook);
|
||||||
app.get('/pair-program-with-team-viewer', resourcesController.pairProgramWithTeamViewer);
|
app.get('/pair-program-with-team-viewer', resourcesController.pairProgramWithTeamViewer);
|
||||||
|
app.get('/done-with-first-100-hours', resourcesController.doneWithFirst100Hours);
|
||||||
app.get('/programmer-interview-questions-app', resourcesController.programmerInterviewQuestionsApp);
|
app.get('/programmer-interview-questions-app', resourcesController.programmerInterviewQuestionsApp);
|
||||||
|
|
||||||
app.get('/about', resourcesController.about);
|
app.get('/about', resourcesController.about);
|
||||||
app.get('/login', userController.getLogin);
|
app.get('/login', userController.getLogin);
|
||||||
app.post('/login', userController.postLogin);
|
app.post('/login', userController.postLogin);
|
||||||
@ -243,28 +245,4 @@ app.listen(app.get('port'), function() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|
||||||
//app.get('/api', apiController.getApi);
|
|
||||||
//app.get('/api/lastfm', apiController.getLastfm);
|
|
||||||
//app.get('/api/nyt', apiController.getNewYorkTimes);
|
|
||||||
//app.get('/api/aviary', apiController.getAviary);
|
|
||||||
//app.get('/api/steam', apiController.getSteam);
|
|
||||||
//app.get('/api/stripe', apiController.getStripe);
|
|
||||||
//app.post('/api/stripe', apiController.postStripe);
|
|
||||||
//app.get('/api/scraping', apiController.getScraping);
|
|
||||||
//app.get('/api/twilio', apiController.getTwilio);
|
|
||||||
//app.post('/api/twilio', apiController.postTwilio);
|
|
||||||
//app.get('/api/clockwork', apiController.getClockwork);
|
|
||||||
//app.post('/api/clockwork', apiController.postClockwork);
|
|
||||||
//app.get('/api/foursquare', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFoursquare);
|
|
||||||
//app.get('/api/tumblr', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTumblr);
|
|
||||||
//app.get('/api/facebook', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getFacebook);
|
|
||||||
//app.get('/api/github', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getGithub);
|
|
||||||
//app.get('/api/twitter', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getTwitter);
|
|
||||||
//app.post('/api/twitter', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.postTwitter);
|
|
||||||
//app.get('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getVenmo);
|
|
||||||
//app.post('/api/venmo', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.postVenmo);
|
|
||||||
//app.get('/api/linkedin', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getLinkedin);
|
|
||||||
//app.get('/api/instagram', passportConf.isAuthenticated, passportConf.isAuthorized, apiController.getInstagram);
|
|
||||||
//app.get('/api/yahoo', apiController.getYahoo);
|
|
@ -7,7 +7,7 @@ var _ = require('lodash');
|
|||||||
|
|
||||||
exports.returnChallenge = function(req, res, next) {
|
exports.returnChallenge = function(req, res, next) {
|
||||||
var challengeNumber = parseInt(req.params.challengeNumber) || 0;
|
var challengeNumber = parseInt(req.params.challengeNumber) || 0;
|
||||||
if (challengeNumber > 60) { challengeNumber = 0; }
|
if (challengeNumber > 59) { challengeNumber = 0; }
|
||||||
Challenge.findOne({challengeNumber: challengeNumber}, function (err, c) {
|
Challenge.findOne({challengeNumber: challengeNumber}, function (err, c) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Challenge err: ', err);
|
console.error('Challenge err: ', err);
|
||||||
|
@ -5,9 +5,13 @@
|
|||||||
|
|
||||||
exports.index = function(req, res) {
|
exports.index = function(req, res) {
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
if (req.user.challengesCompleted.length > 0) {
|
ch = req.user.challengesHash;
|
||||||
nextChallenge = Math.max.apply(Math, req.user.challengesHash) + 1;
|
if (req.user.challengesHash[0] > 0) {
|
||||||
res.redirect("challenges/" + nextChallenge);
|
var max = Object.keys(ch).reduce(function(max,key){
|
||||||
|
return (max === undefined || ch[key] > ch[max]) ? +key : max;
|
||||||
|
});
|
||||||
|
nextChallenge = max + 1;
|
||||||
|
res.redirect("challenges/" + nextChallenge);
|
||||||
} else {
|
} else {
|
||||||
res.redirect("challenges/0");
|
res.redirect("challenges/0");
|
||||||
}
|
}
|
||||||
|
@ -66,12 +66,17 @@ exports.pairProgramWithTeamViewer = function(req, res) {
|
|||||||
"Be sure to pair program on these challenges, and remember to apply the RSAP methodology.",
|
"Be sure to pair program on these challenges, and remember to apply the RSAP methodology.",
|
||||||
"Click the button below to return to the Pair Programming challenge, then mark it complete."],
|
"Click the button below to return to the Pair Programming challenge, then mark it complete."],
|
||||||
cc: req.user.challengesHash
|
cc: req.user.challengesHash
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.about = function(req, res) {
|
exports.about = function(req, res) {
|
||||||
res.render('about', {
|
res.render('about', {
|
||||||
title: 'Who We Are'
|
title: 'About Free Code Camp and Our Team of Volunteers'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.doneWithFirst100Hours = function(req, res) {
|
||||||
|
res.render('done-with-first-100-hours', {
|
||||||
|
title: 'Congratulations on finishing the first 100 hours of Free Code Camp!'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
extends layout
|
extends layout
|
||||||
block content
|
block content
|
||||||
h1 About Free Code Camp
|
include partials/about-us
|
||||||
h2 this is a placeholder page. Our about us page is coming soon.
|
br
|
||||||
|
include partials/faq
|
6
views/done-with-first-100-hours.jade
Normal file
6
views/done-with-first-100-hours.jade
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
extends layout
|
||||||
|
block content
|
||||||
|
.jumbotron.negative-15.text-center
|
||||||
|
h1.hug-top Congratulations on finishing the first 100 hours of Free Code Camp!
|
||||||
|
h2 Now you're ready to continue your learning by building solutions for nonprofits!
|
||||||
|
h3 Private message Quincy Larson in the Free Code Camp Chatroom and he'll help you get started on your first project.
|
@ -183,4 +183,4 @@
|
|||||||
a(href="/challenges/59", class="#{ cc[59] > 0 ? 'strikethrough' : '' }") Create Angular.js Services
|
a(href="/challenges/59", class="#{ cc[59] > 0 ? 'strikethrough' : '' }") Create Angular.js Services
|
||||||
| (45 minutes)
|
| (45 minutes)
|
||||||
|
|
||||||
a.btn.btn-primary.disabled(href="/done-with-first-100-hours") I've finished all Free Code Camp challenges and all the Easy and Medium CoderByte Challenges
|
a.btn.btn-primary(href="/done-with-first-100-hours", class="#{ cc[59] > 0 ? '' : 'disabled' }") I've finished all Free Code Camp challenges and all the Easy and Medium CoderByte Challenges
|
@ -1,202 +0,0 @@
|
|||||||
extends layout
|
|
||||||
block content
|
|
||||||
script.
|
|
||||||
$(document).ready(function () {
|
|
||||||
var directions = {
|
|
||||||
0: "To get started, open your Chrome DevTools. The #next-exercise button is disabled below. Try using jQuery's .attr() method to turn the disabled attribute to false.",
|
|
||||||
1: "Move the .target element from #location1 to #location2.",
|
|
||||||
2: "Change the background color of .target to red.",
|
|
||||||
3: "Change the background color of the even-numbered targets to red.",
|
|
||||||
4: "Change the background color of the target4 to red.",
|
|
||||||
5: "Clone the target2 in #location1 so that it also exists in #location2.",
|
|
||||||
6: "Remove the target3 from element from #location1.",
|
|
||||||
7: "Check the following checkboxes using jQuery.",
|
|
||||||
8: "Make the text input field read-only.",
|
|
||||||
9: "Select the target2 option in the select box.",
|
|
||||||
10: "Add the following css classes to .target: 'animated' and 'hinge'.",
|
|
||||||
11: "Use jQuery to read the data of .target.",
|
|
||||||
12: "Use 'length' to count the number of child elements in #location1, then display that value in #location2.",
|
|
||||||
13: "There's an element hidden in #location1. Show it using jQuery, and then click on it."
|
|
||||||
};
|
|
||||||
var hint = {
|
|
||||||
0: "$('#next-exercise').attr('disabled', false);",
|
|
||||||
1: "$('.target').appendTo('#location2');",
|
|
||||||
2: "$('.target').css('background', 'red');",
|
|
||||||
3: "$('.target:even').css('background', 'red');",
|
|
||||||
4: "$('.target:nth-child(4)').css('background', 'red');",
|
|
||||||
5: "$('.target:nth-child(2)').clone().appendTo($('#location2'));",
|
|
||||||
6: "$('.target:nth-child(3)').remove();",
|
|
||||||
7: "$('#location1 input').attr('checked', 'true')",
|
|
||||||
8: "$('#location1 input').attr('readonly', 'true')",
|
|
||||||
9: "$('#location1 select').val('target2');",
|
|
||||||
10: "$('.target').addClass('animated hinge');",
|
|
||||||
11: "$('.target').data();",
|
|
||||||
12: "$('#location2').text($('#location1').children().length)",
|
|
||||||
13: "$('#finished-button').show().click();"
|
|
||||||
};
|
|
||||||
var elements = {
|
|
||||||
0: "",
|
|
||||||
1: "<div class='btn btn-default target'>.target</div>",
|
|
||||||
2: "<div class='btn btn-default target'>.target</div>",
|
|
||||||
3: "<div class='btn btn-default target'>target0</div><div class='btn btn-default target'>target1</div><div class='btn btn-default target'>target2</div><div class='btn btn-default target'>target3</div><div class='btn btn-default target'>target4</div>",
|
|
||||||
4: "<div class='btn btn-default target'>target1</div><div class='btn btn-default target'>target2</div><div class='btn btn-default target'>target3</div><div class='btn btn-default target'>target4</div><div class='btn btn-default target'>target5</div>",
|
|
||||||
5: "<div class='btn btn-default target'>target1</div><div class='btn btn-default target'>target2</div><div class='btn btn-default target'>target3</div><div class='btn btn-default target'>target4</div><div class='btn btn-default target'>target5</div>",
|
|
||||||
6: "<div class='btn btn-default target'>target1</div><div class='btn btn-default target'>target2</div><div class='btn btn-default target'>target3</div><div class='btn btn-default target'>target4</div><div class='btn btn-default target'>target5</div>",
|
|
||||||
7: "<input type='checkbox'>checkbox1</input><br><input type='checkbox'>checkbox2</input>",
|
|
||||||
8: "<input type='text' value='target'>",
|
|
||||||
9: "<select><option value='target0'>target0</option><option value='target1'>target1</option><option value='target2'>target2</option><option value='target3'>target3</option></select>",
|
|
||||||
10: "<div class='btn btn-default target'>.target</div>",
|
|
||||||
11: "<div class='btn btn-default target' data-lookAtMe='This is some super secret data hidden in the DOM!'>.target</div>",
|
|
||||||
12: "<div class='btn btn-default target'>target1</div><div class='btn btn-default target'>target2</div><div class='btn btn-default target'>target3</div><div class='btn btn-default target'>target4</div><div class='btn btn-default target'>target5</div>",
|
|
||||||
13: "<div class='btn btn-default target' id='finished-button'>Finish!</div>"
|
|
||||||
};
|
|
||||||
|
|
||||||
function refreshEverything() {
|
|
||||||
$('#directions').text("Exercise " + currentExercise + ": " + directions[currentExercise]);
|
|
||||||
$('#location1').html(elements[currentExercise]);
|
|
||||||
$('#hint').text(hint[currentExercise]);
|
|
||||||
handleExerciseTransition();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#exercise-directory').on('click', 'li', event, function () {
|
|
||||||
currentExercise = $(this).index();
|
|
||||||
event.preventDefault();
|
|
||||||
refreshEverything(event);
|
|
||||||
});
|
|
||||||
$('#next-exercise').on('click', event, function () {
|
|
||||||
++currentExercise;
|
|
||||||
event.preventDefault();
|
|
||||||
refreshEverything(event);
|
|
||||||
});
|
|
||||||
$('#solution-button').on('click', function () {
|
|
||||||
$('#hint-modal').modal({backdrop: "static"});
|
|
||||||
});
|
|
||||||
$('#location1').on('click', '#finished-button', function () {
|
|
||||||
$('#finished-modal').modal({backdrop: "static"});
|
|
||||||
});
|
|
||||||
function handleExerciseTransition() {
|
|
||||||
if (currentExercise === 0) {
|
|
||||||
$('#next-exercise').attr('disabled', true);
|
|
||||||
} else {
|
|
||||||
$('#next-exercise').attr('disabled', false);
|
|
||||||
}
|
|
||||||
if (currentExercise === 2 || currentExercise === 6) {
|
|
||||||
$('#location2 .target').remove();
|
|
||||||
}
|
|
||||||
if (currentExercise === 13) {
|
|
||||||
$('#location2').text('');
|
|
||||||
$('#finished-button').hide();
|
|
||||||
$('#next-exercise').attr('disabled', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentExercise = 0;
|
|
||||||
refreshEverything(currentExercise);
|
|
||||||
});
|
|
||||||
style.
|
|
||||||
#directions {
|
|
||||||
text-align: left;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.well {
|
|
||||||
text-align: left;
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#exercise-directory {
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#current-exercise {
|
|
||||||
text-size: 250px;
|
|
||||||
}
|
|
||||||
html.
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class=" col-xs-12 col-sm-8">
|
|
||||||
<div class="jumbotron">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12 text-center">
|
|
||||||
<img src="http://3.bp.blogspot.com/-vgd3mMqeBzk/VGzEmodGqmI/AAAAAAAAAZY/OCcbFvYKzF0/s780/logo4.0LG.png" alt="free code learning at freecodecamp.com" class="img-responsive">
|
|
||||||
<h1>jQuery Exercises</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="text-primary" id="directions">
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-6">#location1</div>
|
|
||||||
<div class="col-xs-6">#location2</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-6 well" id="location1"></div>
|
|
||||||
<div class="col-xs-6 well" id="location2"></div>
|
|
||||||
</div>
|
|
||||||
<div class="btn btn-primary btn-lg btn-block" id="next-exercise">
|
|
||||||
#next-exercise
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<button class="btn btn-block btn-lg btn-info" id="solution-button">
|
|
||||||
#solution-button
|
|
||||||
</button>
|
|
||||||
</br>
|
|
||||||
<div class="text-center">
|
|
||||||
Created for <a href="http://www.FreeCodeCamp.com">Free Code Camp</a><br/>by <a href="https://twitter.com/ossia">Quincy Larson</a>,
|
|
||||||
<a href="https://www.twitter.com/terakilobyte">Nathan Leniz</a>, <a href="https://twitter.com/iheartkode"> Mark Howard</a> and <a href="https://twitter.com/ryanmalm">Ryan Malm</a>. Please <a href="http://codepen.io/ossia/pen/raVEgN">fork this.</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-12 col-sm-4" id="exercise-directory">
|
|
||||||
<div class="panel panel-primary">
|
|
||||||
<div class="panel panel-heading">List of Exercises</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<ol start="0">
|
|
||||||
<li> <a href='#'>Re-enable an element</a></li>
|
|
||||||
<li> <a href='#'>Change an element's parent</a></li>
|
|
||||||
<li> <a href='#'>Change an element's CSS</a></li>
|
|
||||||
<li> <a href='#'>Use jQuery filters to modify even elements</a></li>
|
|
||||||
<li> <a href='#'>Change nth child</a></li>
|
|
||||||
<li> <a href='#'>Clone an element</a></li>
|
|
||||||
<li> <a href='#'>Remove an element</a></li>
|
|
||||||
<li> <a href='#'>Check checkboxes</a></li>
|
|
||||||
<li> <a href='#'>Make text read-only</a></li>
|
|
||||||
<li> <a href='#'>Select an option in a select box</a></li>
|
|
||||||
<li> <a href='#'>Add a CSS class to an element</a></li>
|
|
||||||
<li> <a href='#'>Lookup an element's data attribute</a></li>
|
|
||||||
<li> <a href='#'>Count child elements</a></li>
|
|
||||||
<li> <a href='#'>Show an element and click on it</a></li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal fade" id="hint-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
|
||||||
<h4 class="modal-title" id="myModalLabel">Your hint</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div id="hint">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal fade" id="finished-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
|
||||||
<h4 class="modal-title" id="myModalLabel">Congratulations! You've finished our jQuery exercises! <a href="http://www.freecodecamp.com/">Go back to Free Code Camp </a> and mark this challenge complete.</h4>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div id="hint"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
Reference in New Issue
Block a user