diff --git a/seed/challenges/advanced-bonfires.json b/seed/challenges/advanced-bonfires.json index e14504dba4..978ebe81ce 100644 --- a/seed/challenges/advanced-bonfires.json +++ b/seed/challenges/advanced-bonfires.json @@ -230,7 +230,7 @@ "permAlone('aab');" ], "tests": [ - "expect(permAlone('aab')).to.be.a.number;", + "expect(permAlone('aab')).to.be.a('number');", "expect(permAlone('aab')).to.equal(2);", "expect(permAlone('aaa')).to.equal(0);", "expect(permAlone('aabb')).to.equal(8);", diff --git a/seed/challenges/basic-bonfires.json b/seed/challenges/basic-bonfires.json index 11274ec1a7..ae9b0b571a 100644 --- a/seed/challenges/basic-bonfires.json +++ b/seed/challenges/basic-bonfires.json @@ -423,6 +423,7 @@ ], "tests": [ "expect(truncate('A-tisket a-tasket A green and yellow basket', 11)).to.eqls('A-tisket...');", + "expect(truncate('Peter Piper picked a peck of pickled peppers', 14)).to.eqls('Peter Piper...');", "assert(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length) === 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is = length');", "assert.strictEqual(truncate('A-tisket a-tasket A green and yellow basket', 'A-tisket a-tasket A green and yellow basket'.length + 2), 'A-tisket a-tasket A green and yellow basket', 'should not truncate if string is < length');" ], @@ -657,7 +658,10 @@ ], "tests": [ "assert.deepEqual(destroyer([1, 2, 3, 1, 2, 3], 2, 3), [1, 1], 'should remove correct values from an array');", - "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');" + "assert.deepEqual(destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3), [1, 5, 1], 'should remove correct values from an array');", + "assert.deepEqual(destroyer([3, 5, 1, 2, 2], 2, 3, 5), [1], 'should accept more than two additional arguments');", + "assert.deepEqual(destroyer([2, 3, 2, 3], 2, 3), [], 'should remove correct values from an array');", + "assert.deepEqual(destroyer(['tree', 'hamburger', 53], 'tree', 53), ['hamburger'], 'should handle NaN-elements');" ], "MDNlinks": [ "Arguments object", diff --git a/seed/field-guides.json b/seed/field-guides.json index 2de429b569..9d3e906d16 100644 --- a/seed/field-guides.json +++ b/seed/field-guides.json @@ -863,7 +863,7 @@ "description": [ "
", "

Translation is an all-or-nothing proposal.", - "

We won't be able to add new languages to Free Code Camp until all of our challenges are translated into that langauge.

", + "

We won't be able to add new languages to Free Code Camp until all of our challenges are translated into that language.

", "

In addition to translating these initially, we'll also need to maintain the translation as the challenges are gradually updated.

", "

If you're able to help us, you can join our Trello board by sending @quincylarson your email address in Slack.

", "
" diff --git a/server/boot/challenge.js b/server/boot/challenge.js index bddf9118c4..4b3d23e0e0 100644 --- a/server/boot/challenge.js +++ b/server/boot/challenge.js @@ -32,7 +32,9 @@ var R = require('ramda'), utils = require('../utils'), - userMigration = require('../utils/middleware').userMigration; + saveUser = require('../utils/rx').saveUser, + userMigration = require('../utils/middleware').userMigration, + ifNoUserRedirectTo = require('../utils/middleware').ifNoUserRedirectTo; var challengeMapWithNames = utils.getChallengeMapWithNames(); var challengeMapWithIds = utils.getChallengeMapWithIds(); @@ -51,23 +53,30 @@ module.exports = function(app) { // the follow routes are covered by userMigration router.use(userMigration); - router.get('/challenges/next-challenge', returnNextChallenge); - router.get('/challenges/:challengeName', returnIndividualChallenge); - router.get('/challenges/', returnCurrentChallenge); router.get('/map', challengeMap); + router.get( + '/challenges/next-challenge', + ifNoUserRedirectTo('../challenges/learn-how-free-code-camp-works'), + returnNextChallenge + ); + + router.get('/challenges/:challengeName', returnIndividualChallenge); + + router.get( + '/challenges/', + ifNoUserRedirectTo('../challenges/learn-how-free-code-camp-works'), + returnCurrentChallenge + ); app.use(router); function returnNextChallenge(req, res, next) { - if (!req.user) { - return res.redirect('../challenges/learn-how-free-code-camp-works'); - } var completed = req.user.completedChallenges.map(function (elem) { return elem.id; }); req.user.uncompletedChallenges = utils.allChallengeIds() - .filter(function (elem) { + .filter(function(elem) { if (completed.indexOf(elem) === -1) { return elem; } @@ -100,18 +109,17 @@ module.exports = function(app) { nextChallengeName = R.head(challengeMapWithDashedNames[0].challenges); } - req.user.save(function(err) { - if (err) { - return next(err); - } - return res.redirect('../challenges/' + nextChallengeName); - }); + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + res.redirect('../challenges/' + nextChallengeName); + } + ); } function returnCurrentChallenge(req, res, next) { - if (!req.user) { - return res.redirect('../challenges/learn-how-free-code-camp-works'); - } var completed = req.user.completedChallenges.map(function (elem) { return elem.id; }); @@ -133,12 +141,14 @@ module.exports = function(app) { var nameString = req.user.currentChallenge.dashedName; - req.user.save(function(err) { - if (err) { - return next(err); - } - return res.redirect('../challenges/' + nameString); - }); + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + res.redirect('../challenges/' + nameString); + } + ); } function returnIndividualChallenge(req, res, next) { @@ -152,8 +162,10 @@ module.exports = function(app) { // Handle not found if (!challenge) { req.flash('errors', { - msg: '404: We couldn\'t find a challenge with that name. ' + - 'Please double check the name.' + msg: + '404: We couldn\'t find a challenge with the name `' + + dashedName + + '` Please double check the name.' }); return res.redirect('/challenges'); } @@ -167,8 +179,9 @@ module.exports = function(app) { map(function (key) { return challengeMapWithIds[key] .filter(function (elem) { - return String(elem) === String(challenge.id); - }).map(function () { + return String(elem) === challenge.id; + }) + .map(function () { return key; }); }) @@ -176,120 +189,48 @@ module.exports = function(app) { }; } - var challengeType = { - 0: function() { - res.render('coursewares/showHTML', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - brief: challenge.description[0], - details: challenge.description.slice(1), - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - environment: utils.whichEnvironment(), - challengeType: challenge.challengeType - }); - }, - - 1: function() { - res.render('coursewares/showJS', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - brief: challenge.description[0], - details: challenge.description.slice(1), - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 2: function() { - res.render('coursewares/showVideo', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - tests: challenge.tests, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 3: function() { - res.render('coursewares/showZiplineOrBasejump', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 4: function() { - res.render('coursewares/showZiplineOrBasejump', { - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - details: challenge.description, - video: challenge.challengeSeed[0], - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - challengeId: challenge.id, - challengeType: challenge.challengeType - }); - }, - - 5: function() { - res.render('coursewares/showBonfire', { - completedWith: null, - title: challenge.name, - dashedName: dashedName, - name: challenge.name, - difficulty: Math.floor(+challenge.difficulty), - brief: challenge.description.shift(), - details: challenge.description, - tests: challenge.tests, - challengeSeed: challenge.challengeSeed, - verb: utils.randomVerb(), - phrase: utils.randomPhrase(), - compliment: utils.randomCompliment(), - bonfires: challenge, - challengeId: challenge.id, - MDNkeys: challenge.MDNlinks, - MDNlinks: getMDNLinks(challenge.MDNlinks), - challengeType: challenge.challengeType - }); - } + var commonLocals = { + title: challenge.name, + dashedName: dashedName, + name: challenge.name, + details: challenge.description.slice(1), + tests: challenge.tests, + challengeSeed: challenge.challengeSeed, + verb: utils.randomVerb(), + phrase: utils.randomPhrase(), + compliment: utils.randomCompliment(), + challengeId: challenge.id, + challengeType: challenge.challengeType, + // video challenges + video: challenge.challengeSeed[0], + // bonfires specific + difficulty: Math.floor(+challenge.difficulty), + brief: challenge.description.shift(), + bonfires: challenge, + MDNkeys: challenge.MDNlinks, + MDNlinks: getMDNLinks(challenge.MDNlinks), + // htmls specific + environment: utils.whichEnvironment() }; - if (req.user) { - req.user.save(function (err) { - if (err) { - return next(err); + + var challengeView = { + 0: 'coursewares/showHTML', + 1: 'coursewares/showJS', + 2: 'coursewares/showVideo', + 3: 'coursewares/showZiplineOrBasejump', + 4: 'coursewares/showZiplineOrBasejump', + 5: 'coursewares/showBonfire' + }; + + saveUser(req.user) + .subscribe( + function() {}, + next, + function() { + var view = challengeView[challenge.challengeType]; + res.render(view, commonLocals); } - return challengeType[challenge.challengeType](); - }); - } else { - return challengeType[challenge.challengeType](); - } + ); }); } diff --git a/server/boot/nonprofits.js b/server/boot/nonprofits.js index 988ded5f84..1d16e76b74 100644 --- a/server/boot/nonprofits.js +++ b/server/boot/nonprofits.js @@ -9,7 +9,7 @@ module.exports = function(app) { function nonprofitsDirectory(req, res, next) { Nonprofit.find( - { where: { estimatedHours: { $gt: 0 } } }, + { where: { estimatedHours: { gt: 0 } } }, function(err, nonprofits) { if (err) { return next(err); } diff --git a/server/utils/middleware.js b/server/utils/middleware.js index 5d2d12741c..5af207e513 100644 --- a/server/utils/middleware.js +++ b/server/utils/middleware.js @@ -33,3 +33,13 @@ exports.userMigration = function userMigration(req, res, next) { ); return next(); }; + +exports.ifNoUserRedirectTo = function ifNoUserRedirectTo(url) { + return function(req, res, next) { + if (req.user) { + return next(); + } + return res.redirect(url); + }; +}; +