diff --git a/app.js b/app.js index 0c2546d754..7f15966228 100644 --- a/app.js +++ b/app.js @@ -372,18 +372,6 @@ app.post( storyController.upvote ); -/** - * Challenge related routes - */ -app.get( - '/challenges/', - challengesController.returnNextChallenge -); -app.get( - '/challenges/:challengeNumber', - challengesController.returnChallenge -); - app.all('/account', passportConf.isAuthenticated); app.get('/account/api', userController.getAccountAngular); @@ -422,10 +410,10 @@ app.post('/completed-bonfire/', bonfireController.completedBonfire); * Courseware related routes */ -app.get('/coursewares/', coursewareController.returnNextCourseware); -app.get('/coursewares/getCoursewareList', coursewareController.showAllCoursewares); +app.get('/challenges/', coursewareController.returnNextCourseware); +app.get('/challenges/getCoursewareList', coursewareController.showAllCoursewares); app.get( - '/coursewares/:coursewareName', + '/challenges/:coursewareName', coursewareController.returnIndividualCourseware ); app.post('/completed-courseware/', coursewareController.completedCourseware); @@ -441,25 +429,7 @@ app.post('/account/delete', userController.postDeleteAccount); app.get('/account/unlink/:provider', userController.getOauthUnlink); app.get('/sitemap.xml', resourcesController.sitemap); -/** - * API examples routes. - * accepts a post request. the challenge id req.body.challengeNumber - * and updates user.challengesHash & user.challengesCompleted - * - */ -app.post('/completed-challenge', function (req, res) { - req.user.challengesHash[parseInt(req.body.challengeNumber)] = - Math.round(+new Date() / 1000); - var timestamp = req.user.challengesHash; - var points = 0; - for (var key in timestamp) { - if (timestamp[key] > 0 && req.body.challengeNumber < 54) { - points += 1; - } - } - req.user.points = points; - req.user.save(); -}); + /** * OAuth sign-in routes. diff --git a/controllers/courseware.js b/controllers/courseware.js index 2cf3390d46..4d992d310e 100644 --- a/controllers/courseware.js +++ b/controllers/courseware.js @@ -23,7 +23,7 @@ exports.showAllCoursewares = function(req, res) { exports.returnNextCourseware = function(req, res) { if (!req.user) { - return res.redirect('../coursewares/start-our-challenges'); + return res.redirect('../challenges/learn-how-free-code-camp-works'); } var completed = req.user.completedCoursewares.map(function (elem) { return elem._id; @@ -50,10 +50,10 @@ exports.returnNextCourseware = function(req, res) { req.flash('errors', { msg: "It looks like you've completed all the courses we have available. Good job!" }); - return res.redirect('../coursewares/start-our-challenges'); + return res.redirect('../challenges/learn-how-free-code-camp-works'); } nameString = courseware.name.toLowerCase().replace(/\s/g, '-'); - return res.redirect('../coursewares/' + nameString); + return res.redirect('../challenges/' + nameString); }); }; @@ -71,14 +71,14 @@ exports.returnIndividualCourseware = function(req, res, next) { req.flash('errors', { msg: "404: We couldn't find a challenge with that name. Please double check the name." }); - return res.redirect('/coursewares') + return res.redirect('/challenges'); } courseware = courseware.pop(); // Redirect to full name if the user only entered a partial var dashedNameFull = courseware.name.toLowerCase().replace(/\s/g, '-'); if (dashedNameFull != dashedName) { - return res.redirect('../coursewares/' + dashedNameFull); + return res.redirect('../challenges/' + dashedNameFull); } var challengeType = { @@ -217,15 +217,19 @@ exports.completedCourseware = function (req, res) { var isCompletedDate = Math.round(+new Date() / 1000); var coursewareHash = req.body.coursewareInfo.coursewareHash; + debug('this is the coursewarehash we got', coursewareHash); + req.user.completedCoursewares.push({ _id: coursewareHash, - completedDate: isCompletedDate + completedDate: isCompletedDate, + name: req.body.coursewareInfo.coursewareName }); - var index = req.user.uncompletedCoursewares.indexOf(coursewareHash); - if (index > -1) { + var index = req.user.completedCoursewares.indexOf(coursewareHash); + debug('this is the index of the found courseware', index); + if (index === -1) { req.user.progressTimestamps.push(Date.now() / 1000 | 0); - req.user.uncompletedCoursewares.splice(index, 1) + req.user.uncompletedCoursewares.splice(index, 1); } req.user.save(function (err, user) { @@ -233,7 +237,7 @@ exports.completedCourseware = function (req, res) { throw err; } if (user) { - res.send(true) + res.send(true); } }); -}; \ No newline at end of file +}; diff --git a/controllers/resources.js b/controllers/resources.js index d2f2075ce9..51a2a6201b 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -21,6 +21,17 @@ var async = require('async'), * Resources. */ +Array.zip = function(left, right, combinerFunction) { + var counter, + results = []; + + for (counter = 0; counter < Math.min(left.length, right.length); counter++) { + results.push(combinerFunction(left[counter],right[counter])); + } + + return results; +}; + module.exports = { privacy: function privacy(req, res) { res.render('resources/privacy', { @@ -185,17 +196,36 @@ module.exports = { req.user.save(); } } - var date1 = new Date("10/15/2014"); + var date1 = new Date('10/15/2014'); var date2 = new Date(); var progressTimestamps = req.user.progressTimestamps; var now = Date.now() / 1000 | 0; if (req.user.pointsNeedMigration) { var challengesHash = req.user.challengesHash; - for(var key in challengesHash) { + for (var key in challengesHash) { if (challengesHash[key] > 0) { req.user.progressTimestamps.push(challengesHash[key]); } } + + var timeStamps = []; + R.keys(req.user.challengesHash).forEach(function(key) { + "use strict"; + timeStamps.push({timeStamp: challengesHash[key]}); + }); + + req.user.completedCoursewares = Array.zip(timeStamps, coursewares, + function(left, right) { + "use strict"; + return ({ + completedDate: left.timeStamp, + _id: right._id, + name: right.name + }); + }).filter(function(elem) { + "use strict"; + return elem.completedDate !== 0; + }); req.user.pointsNeedMigration = false; req.user.save(); } @@ -278,6 +308,11 @@ module.exports = { }); }, + getAllCourses: function() { + "use strict"; + return coursewares; + }, + allCoursewareIds: function() { return coursewares.map(function(elem) { return { @@ -298,16 +333,16 @@ module.exports = { name: elem.name, difficulty: elem.difficulty, _id: elem._id - } + }; }) - .sort(function(a, b) { - return a.difficulty - b.difficulty; - }) - .map (function(elem) { + .sort(function(a, b) { + return a.difficulty - b.difficulty; + }) + .map (function(elem) { return { - name : elem.name, + name: elem.name, _id: elem._id - } + }; }); }, whichEnvironment: function() { diff --git a/controllers/user.js b/controllers/user.js index 80c2fd2311..50ccf2ba47 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1,14 +1,14 @@ var _ = require('lodash'), - async = require('async'), - crypto = require('crypto'), - nodemailer = require('nodemailer'), - passport = require('passport'), - User = require('../models/User'), - secrets = require('../config/secrets'), - moment = require('moment'), - Challenge = require('./../models/Challenge'), - debug = require('debug')('freecc:cntr:challenges'), - resources = require('./resources'); + async = require('async'), + crypto = require('crypto'), + nodemailer = require('nodemailer'), + passport = require('passport'), + User = require('../models/User'), + secrets = require('../config/secrets'), + moment = require('moment'), + Challenge = require('./../models/Challenge'), + debug = require('debug')('freecc:cntr:challenges'), + resources = require('./resources'); @@ -18,10 +18,10 @@ var _ = require('lodash'), */ exports.getSignin = function(req, res) { - if (req.user) return res.redirect('/'); - res.render('account/signin', { - title: 'Free Code Camp Login' - }); + if (req.user) return res.redirect('/'); + res.render('account/signin', { + title: 'Free Code Camp Login' + }); }; /** @@ -30,28 +30,28 @@ exports.getSignin = function(req, res) { */ exports.postSignin = function(req, res, next) { - req.assert('email', 'Email is not valid').isEmail(); - req.assert('password', 'Password cannot be blank').notEmpty(); + req.assert('email', 'Email is not valid').isEmail(); + req.assert('password', 'Password cannot be blank').notEmpty(); - var errors = req.validationErrors(); + var errors = req.validationErrors(); - if (errors) { - req.flash('errors', errors); - return res.redirect('/signin'); + if (errors) { + req.flash('errors', errors); + return res.redirect('/signin'); + } + + passport.authenticate('local', function(err, user, info) { + if (err) return next(err); + if (!user) { + req.flash('errors', { msg: info.message }); + return res.redirect('/signin'); } - - passport.authenticate('local', function(err, user, info) { - if (err) return next(err); - if (!user) { - req.flash('errors', { msg: info.message }); - return res.redirect('/signin'); - } - req.logIn(user, function(err) { - if (err) return next(err); - req.flash('success', { msg: 'Success! You are logged in.' }); - res.redirect(req.session.returnTo || '/'); - }); - })(req, res, next); + req.logIn(user, function(err) { + if (err) return next(err); + req.flash('success', { msg: 'Success! You are logged in.' }); + res.redirect(req.session.returnTo || '/'); + }); + })(req, res, next); }; /** @@ -60,8 +60,8 @@ exports.postSignin = function(req, res, next) { */ exports.signout = function(req, res) { - req.logout(); - res.redirect('/'); + req.logout(); + res.redirect('/'); }; /** @@ -70,10 +70,10 @@ exports.signout = function(req, res) { */ exports.getEmailSignin = function(req, res) { - if (req.user) return res.redirect('/'); - res.render('account/email-signin', { - title: 'Sign in to your Free Code Camp Account' - }); + if (req.user) return res.redirect('/'); + res.render('account/email-signin', { + title: 'Sign in to your Free Code Camp Account' + }); }; /** @@ -82,10 +82,10 @@ exports.getEmailSignin = function(req, res) { */ exports.getEmailSignup = function(req, res) { - if (req.user) return res.redirect('/'); - res.render('account/email-signup', { - title: 'Create Your Free Code Camp Account' - }); + if (req.user) return res.redirect('/'); + res.render('account/email-signup', { + title: 'Create Your Free Code Camp Account' + }); }; /** @@ -95,6 +95,7 @@ exports.getEmailSignup = function(req, res) { exports.postEmailSignup = function(req, res, next) { + req.assert('email', 'valid email required').isEmail(); var errors = req.validationErrors(); @@ -103,86 +104,86 @@ exports.postEmailSignup = function(req, res, next) { return res.redirect('/email-signup'); } - var possibleUserData = req.body; + var possibleUserData = req.body; - if (possibleUserData.password.length < 8) { - req.flash('errors', { - msg: 'Your password is too short' - }); - return res.redirect('email-signup'); + if (possibleUserData.password.length < 8) { + req.flash('errors', { + msg: 'Your password is too short' + }); + return res.redirect('email-signup'); + } + + if (possibleUserData.username.length < 5 || possibleUserData.length > 20) { + req.flash('errors', { + msg: 'Your username must be between 5 and 20 characters' + }); + return res.redirect('email-signup'); + } + + + var user = new User({ + email: req.body.email.trim(), + password: req.body.password, + profile : { + username: req.body.username.trim(), + picture: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png' + } + }); + + User.findOne({ email: req.body.email }, function(err, existingEmail) { + if (err) { + return next(err); } - if (possibleUserData.username.length < 5 || possibleUserData.length > 20) { - req.flash('errors', { - msg: 'Your username must be between 5 and 20 characters' - }); - return res.redirect('email-signup'); + if (existingEmail) { + req.flash('errors', { + msg: 'Account with that email address already exists.' + }); + return res.redirect('/email-signup'); } - - - var user = new User({ - email: req.body.email.trim(), - password: req.body.password, - profile : { - username: req.body.username.trim(), - picture: 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png' - } - }); - - User.findOne({ email: req.body.email }, function(err, existingEmail) { - if (err) { - return next(err); - } - - if (existingEmail) { - req.flash('errors', { - msg: 'Account with that email address already exists.' - }); - return res.redirect('/email-signup'); - } - User.findOne({'profile.username': req.body.username }, function(err, existingUsername) { - if (err) { - return next(err); - } - if (existingUsername) { - req.flash('errors', { - msg: 'Account with that username already exists.' - }); - return res.redirect('/email-signup'); - } - - user.save(function(err) { - if (err) { return next(err); } - req.logIn(user, function(err) { - if (err) { return next(err); } - res.redirect('/email-signup'); - }); - }); - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Welcome to Free Code Camp!', - text: [ - 'Greetings from San Francisco!\n\n', - 'Thank you for joining our community.\n', - 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', - "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", - 'Good luck with the challenges!\n\n', - '- the Volunteer Camp Counselor Team' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return err; } - }); + User.findOne({'profile.username': req.body.username }, function(err, existingUsername) { + if (err) { + return next(err); + } + if (existingUsername) { + req.flash('errors', { + msg: 'Account with that username already exists.' }); + return res.redirect('/email-signup'); + } + + user.save(function(err) { + if (err) { return next(err); } + req.logIn(user, function(err) { + if (err) { return next(err); } + res.redirect('/email-signup'); + }); + }); + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return err; } + }); }); + }); }; /** @@ -200,9 +201,9 @@ exports.getStreak = function(req, res) { */ exports.getAccount = function(req, res) { - res.render('account/account', { - title: 'Manage your Free Code Camp Account' - }); + res.render('account/account', { + title: 'Manage your Free Code Camp Account' + }); }; /** @@ -210,9 +211,9 @@ exports.getAccount = function(req, res) { */ exports.getAccountAngular = function(req, res) { - res.json({ - user: req.user - }); + res.json({ + user: req.user + }); }; /** @@ -220,26 +221,26 @@ exports.getAccountAngular = function(req, res) { */ exports.checkUniqueUsername = function(req, res) { - User.count({'profile.username': req.params.username.toLowerCase()}, function (err, data) { - if (data == 1) { - return res.send(true); - } else { - return res.send(false); - } - }); + User.count({'profile.username': req.params.username.toLowerCase()}, function (err, data) { + if (data == 1) { + return res.send(true); + } else { + return res.send(false); + } + }); }; /** * Existing username check */ exports.checkExistingUsername = function(req, res) { - User.count({'profile.username': req.params.username.toLowerCase()}, function (err, data) { - if (data === 1) { - return res.send(true); - } else { - return res.send(false); - } - }); + User.count({'profile.username': req.params.username.toLowerCase()}, function (err, data) { + if (data === 1) { + return res.send(true); + } else { + return res.send(false); + } + }); }; /** @@ -247,13 +248,13 @@ exports.checkExistingUsername = function(req, res) { */ exports.checkUniqueEmail = function(req, res) { - User.count({'email': decodeURIComponent(req.params.email).toLowerCase()}, function (err, data) { - if (data == 1) { - return res.send(true); - } else { - return res.send(false); - } - }); + User.count({'email': decodeURIComponent(req.params.email).toLowerCase()}, function (err, data) { + if (data === 1) { + return res.send(true); + } else { + return res.send(false); + } + }); }; @@ -267,43 +268,40 @@ exports.returnUser = function(req, res, next) { if (err) { debug('Username err: ', err); next(err); } if (user[0]) { var user = user[0]; - Challenge.find({}, null, {sort: {challengeNumber: 1}}, function (err, c) { - data = {}; - progressTimestamps = user.progressTimestamps; - // dummy data to experiment with visualizations - progressTimestamps = [1417117319, 1384091493, 1367893914, 1411547157, 1366875140, 1382614404, 1374973026, 1363495510, 1372229313, 1389795294, 1393820136, 1395425437, 1383366211, 1402063449, 1368384561, 1413460738, 1390013511, 1408510076, 1395530419, 1391588683, 1410480320, 1360219531, 1367248635, 1408531181, 1374214772, 1424038529, 1387468139, 1381934158, 1409278748, 1390696161, 1415933043, 1389573689, 1395703336, 1401223291, 1375539279, 1371229698, 1371990948, 1422236826, 1363017438, 1359619855, 1364850739, 1401982108, 1381270295, 1420063854, 1406540493, 1409122251, 1360775035, 1367712723, 1395305605, 1382037418, 1378402477, 1377563090, 1398930836, 1417371909, 1377417393, 1423763002, 1357511908, 1377375961, 1388374304, 1406416407, 1399463258, 1422593990, 1383434425, 1420200570, 1379435518, 1414512582, 1416263148, 1398635260, 1381815565, 1369178539, 1378414973, 1394409827, 1398463526, 1379564971, 1385849279, 1392899666, 1367053659, 1417730793, 1400112915, 1379923357, 1417768487, 1415779985, 1416150640, 1399820237, 1370498715, 1374800622, 1363924512, 1402497668, 1400146327, 1362456746, 1394935898, 1414980963, 1413942775, 1367606840, 1387144705, 1407906392, 1417213587, 1422640891, 1414033139, 1365323522, 1424661148]; - for (i = 0; i < progressTimestamps.length; i++) { - data[progressTimestamps[i].toString()] = 1; - } + var data = {}; + var progressTimestamps = user.progressTimestamps; + for (var i = 0; i < progressTimestamps.length; i++) { + data[progressTimestamps[i].toString()] = 1; + } - res.render('account/show', { - title: 'Camper: ', - username: user.profile.username, - name: user.profile.name, - location: user.profile.location, - githubProfile: user.profile.githubProfile, - linkedinProfile: user.profile.linkedinProfile, - codepenProfile: user.profile.codepenProfile, - twitterHandle: user.profile.twitterHandle, - bio: user.profile.bio, - picture: user.profile.picture, - progressTimestamps: req.user.progressTimestamps, - points: user.progressTimestamps, - website1Link: user.portfolio.website1Link, - website1Title: user.portfolio.website1Title, - website1Image: user.portfolio.website1Image, - website2Link: user.portfolio.website2Link, - website2Title: user.portfolio.website2Title, - website2Image: user.portfolio.website2Image, - website3Link: user.portfolio.website3Link, - website3Title: user.portfolio.website3Title, - website3Image: user.portfolio.website3Image, - challenges: c, - calender: data, - moment: moment - }); + res.render('account/show', { + title: 'Camper ' + user.profile.username + '\'s portfolio', + username: user.profile.username, + name: user.profile.name, + location: user.profile.location, + githubProfile: user.profile.githubProfile, + linkedinProfile: user.profile.linkedinProfile, + codepenProfile: user.profile.codepenProfile, + twitterHandle: user.profile.twitterHandle, + bio: user.profile.bio, + picture: user.profile.picture, + progressTimestamps: user.progressTimestamps, + points: user.progressTimestamps.length, + website1Link: user.portfolio.website1Link, + website1Title: user.portfolio.website1Title, + website1Image: user.portfolio.website1Image, + website2Link: user.portfolio.website2Link, + website2Title: user.portfolio.website2Title, + website2Image: user.portfolio.website2Image, + website3Link: user.portfolio.website3Link, + website3Title: user.portfolio.website3Title, + website3Image: user.portfolio.website3Image, + ch: user.challengesHash, + calender: data, + moment: moment }); + } else { req.flash('errors', { msg: "404: We couldn't find a page with that url. Please double check the link." @@ -320,20 +318,20 @@ exports.returnUser = function(req, res, next) { */ exports.updateProgress = function(req, res) { - User.findById(req.user.id, function(err, user) { - if (err) return next(err); - user.email = req.body.email || ''; - user.profile.name = req.body.name || ''; - user.profile.gender = req.body.gender || ''; - user.profile.location = req.body.location || ''; - user.profile.website = req.body.website || ''; + User.findById(req.user.id, function(err, user) { + if (err) return next(err); + user.email = req.body.email || ''; + user.profile.name = req.body.name || ''; + user.profile.gender = req.body.gender || ''; + user.profile.location = req.body.location || ''; + user.profile.website = req.body.website || ''; - user.save(function(err) { - if (err) return next(err); - req.flash('success', { msg: 'Profile information updated.' }); - res.redirect('/account'); - }); + user.save(function(err) { + if (err) return next(err); + req.flash('success', { msg: 'Profile information updated.' }); + res.redirect('/account'); }); + }); }; /** @@ -343,77 +341,77 @@ exports.updateProgress = function(req, res) { exports.postUpdateProfile = function(req, res, next) { - User.findById(req.user.id, function(err, user) { - if (err) return next(err); - var errors = req.validationErrors(); - if (errors) { - req.flash('errors', errors); - return res.redirect('/account'); - } + User.findById(req.user.id, function(err, user) { + if (err) return next(err); + var errors = req.validationErrors(); + if (errors) { + req.flash('errors', errors); + return res.redirect('/account'); + } - User.findOne({ email: req.body.email }, function(err, existingEmail) { - if (err) { - return next(err); - } - var user = req.user; - if (existingEmail && existingEmail.email != user.email) { - req.flash('errors', { - msg: "An account with that email address already exists." - }); - return res.redirect('/account'); - } - User.findOne({ 'profile.username': req.body.username }, function(err, existingUsername) { - if (err) { - return next(err); - } - var user = req.user; - if (existingUsername && existingUsername.profile.username !== user.profile.username) { - req.flash('errors', { - msg: 'An account with that username already exists.' - }); - return res.redirect('/account'); - } - user.email = req.body.email.trim() || ''; - user.profile.name = req.body.name.trim() || ''; - user.profile.username = req.body.username.trim() || ''; - user.profile.location = req.body.location.trim() || ''; - user.profile.githubProfile = req.body.githubProfile.trim() || ''; - user.profile.linkedinProfile = req.body.linkedinProfile.trim() || ''; - user.profile.codepenProfile = req.body.codepenProfile.trim() || ''; - user.profile.twitterHandle = req.body.twitterHandle.trim() || ''; - user.profile.bio = req.body.bio.trim() || ''; - user.profile.picture = req.body.picture.trim() || 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png'; - user.portfolio.website1Title = req.body.website1Title.trim() || ''; - user.portfolio.website1Link = req.body.website1Link.trim() || ''; - user.portfolio.website1Image = req.body.website1Image.trim() || ''; - user.portfolio.website2Title = req.body.website2Title.trim() || ''; - user.portfolio.website2Link = req.body.website2Link.trim() || ''; - user.portfolio.website2Image = req.body.website2Image.trim() || ''; - user.portfolio.website3Title = req.body.website3Title.trim() || ''; - user.portfolio.website3Link = req.body.website3Link.trim() || ''; - user.portfolio.website3Image = req.body.website3Image.trim() || ''; - - - user.save(function (err) { - if (err) { - return next(err); - } - resources.updateUserStoryPictures( - user._id.toString(), - user.profile.picture, - user.profile.username, - function(err) { - if (err) { return next(err); } - req.flash('success', { - msg: 'Profile information updated.' - }); - res.redirect('/account'); - } - ); - }); - }); + User.findOne({ email: req.body.email }, function(err, existingEmail) { + if (err) { + return next(err); + } + var user = req.user; + if (existingEmail && existingEmail.email != user.email) { + req.flash('errors', { + msg: "An account with that email address already exists." }); + return res.redirect('/account'); + } + User.findOne({ 'profile.username': req.body.username }, function(err, existingUsername) { + if (err) { + return next(err); + } + var user = req.user; + if (existingUsername && existingUsername.profile.username !== user.profile.username) { + req.flash('errors', { + msg: 'An account with that username already exists.' + }); + return res.redirect('/account'); + } + user.email = req.body.email.trim() || ''; + user.profile.name = req.body.name.trim() || ''; + user.profile.username = req.body.username.trim() || ''; + user.profile.location = req.body.location.trim() || ''; + user.profile.githubProfile = req.body.githubProfile.trim() || ''; + user.profile.linkedinProfile = req.body.linkedinProfile.trim() || ''; + user.profile.codepenProfile = req.body.codepenProfile.trim() || ''; + user.profile.twitterHandle = req.body.twitterHandle.trim() || ''; + user.profile.bio = req.body.bio.trim() || ''; + user.profile.picture = req.body.picture.trim() || 'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png'; + user.portfolio.website1Title = req.body.website1Title.trim() || ''; + user.portfolio.website1Link = req.body.website1Link.trim() || ''; + user.portfolio.website1Image = req.body.website1Image.trim() || ''; + user.portfolio.website2Title = req.body.website2Title.trim() || ''; + user.portfolio.website2Link = req.body.website2Link.trim() || ''; + user.portfolio.website2Image = req.body.website2Image.trim() || ''; + user.portfolio.website3Title = req.body.website3Title.trim() || ''; + user.portfolio.website3Link = req.body.website3Link.trim() || ''; + user.portfolio.website3Image = req.body.website3Image.trim() || ''; + + + user.save(function (err) { + if (err) { + return next(err); + } + resources.updateUserStoryPictures( + user._id.toString(), + user.profile.picture, + user.profile.username, + function(err) { + if (err) { return next(err); } + req.flash('success', { + msg: 'Profile information updated.' + }); + res.redirect('/account'); + } + ); + }); + }); }); + }); }; /** @@ -422,29 +420,29 @@ exports.postUpdateProfile = function(req, res, next) { */ exports.postUpdatePassword = function(req, res, next) { - req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match') - .equals(req.body.password); + req.assert('password', 'Password must be at least 4 characters long').len(4); + req.assert('confirmPassword', 'Passwords do not match') + .equals(req.body.password); - var errors = req.validationErrors(); + var errors = req.validationErrors(); - if (errors) { - req.flash('errors', errors); - return res.redirect('/account'); - } + if (errors) { + req.flash('errors', errors); + return res.redirect('/account'); + } - User.findById(req.user.id, function(err, user) { - if (err) { return next(err); } + User.findById(req.user.id, function(err, user) { + if (err) { return next(err); } - user.password = req.body.password; + user.password = req.body.password; - user.save(function(err) { - if (err) { return next(err); } + user.save(function(err) { + if (err) { return next(err); } - req.flash('success', { msg: 'Password has been changed.' }); - res.redirect('/account'); - }); + req.flash('success', { msg: 'Password has been changed.' }); + res.redirect('/account'); }); + }); }; /** @@ -453,12 +451,12 @@ exports.postUpdatePassword = function(req, res, next) { */ exports.postDeleteAccount = function(req, res, next) { - User.remove({ _id: req.user.id }, function(err) { - if (err) { return next(err); } - req.logout(); - req.flash('info', { msg: 'Your account has been deleted.' }); - res.redirect('/'); - }); + User.remove({ _id: req.user.id }, function(err) { + if (err) { return next(err); } + req.logout(); + req.flash('info', { msg: 'Your account has been deleted.' }); + res.redirect('/'); + }); }; /** @@ -467,22 +465,22 @@ exports.postDeleteAccount = function(req, res, next) { */ exports.getOauthUnlink = function(req, res, next) { - var provider = req.params.provider; - User.findById(req.user.id, function(err, user) { - if (err) { return next(err); } + var provider = req.params.provider; + User.findById(req.user.id, function(err, user) { + if (err) { return next(err); } - user[provider] = undefined; - user.tokens = - _.reject(user.tokens, function(token) { - return token.kind === provider; - }); + user[provider] = undefined; + user.tokens = + _.reject(user.tokens, function(token) { + return token.kind === provider; + }); - user.save(function(err) { - if (err) { return next(err); } - req.flash('info', { msg: provider + ' account has been unlinked.' }); - res.redirect('/account'); - }); + user.save(function(err) { + if (err) { return next(err); } + req.flash('info', { msg: provider + ' account has been unlinked.' }); + res.redirect('/account'); }); + }); }; /** @@ -491,25 +489,25 @@ exports.getOauthUnlink = function(req, res, next) { */ exports.getReset = function(req, res) { - if (req.isAuthenticated()) { - return res.redirect('/'); - } - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (err) { return next(err); } - if (!user) { - req.flash('errors', { - msg: 'Password reset token is invalid or has expired.' - }); - return res.redirect('/forgot'); - } - res.render('account/reset', { - title: 'Password Reset', - token: req.params.token - }); + if (req.isAuthenticated()) { + return res.redirect('/'); + } + User + .findOne({ resetPasswordToken: req.params.token }) + .where('resetPasswordExpires').gt(Date.now()) + .exec(function(err, user) { + if (err) { return next(err); } + if (!user) { + req.flash('errors', { + msg: 'Password reset token is invalid or has expired.' }); + return res.redirect('/forgot'); + } + res.render('account/reset', { + title: 'Password Reset', + token: req.params.token + }); + }); }; /** @@ -518,72 +516,72 @@ exports.getReset = function(req, res) { */ exports.postReset = function(req, res, next) { - var errors = req.validationErrors(); + var errors = req.validationErrors(); - if (errors) { - req.flash('errors', errors); - return res.redirect('back'); - } + if (errors) { + req.flash('errors', errors); + return res.redirect('back'); + } - async.waterfall([ - function(done) { - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (err) { return next(err); } - if (!user) { - req.flash('errors', { - msg: 'Password reset token is invalid or has expired.' - }); - return res.redirect('back'); - } - - user.password = req.body.password; - user.resetPasswordToken = undefined; - user.resetPasswordExpires = undefined; - - user.save(function(err) { - if (err) { return done(err); } - req.logIn(user, function(err) { - done(err, user); - }); - }); - }); - }, - function(user, done) { - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } + async.waterfall([ + function(done) { + User + .findOne({ resetPasswordToken: req.params.token }) + .where('resetPasswordExpires').gt(Date.now()) + .exec(function(err, user) { + if (err) { return next(err); } + if (!user) { + req.flash('errors', { + msg: 'Password reset token is invalid or has expired.' }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Your Free Code Camp password has been changed', - text: [ - 'Hello,\n\n', - 'This email is confirming that you requested to', - 'reset your password for your Free Code Camp account.', - 'This is your email:', - user.email, - '\n' - ].join(' ') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return done(err); } - req.flash('success', { - msg: 'Success! Your password has been changed.' - }); - done(); + return res.redirect('back'); + } + + user.password = req.body.password; + user.resetPasswordToken = undefined; + user.resetPasswordExpires = undefined; + + user.save(function(err) { + if (err) { return done(err); } + req.logIn(user, function(err) { + done(err, user); }); + }); + }); + }, + function(user, done) { + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password } - ], function(err) { - if (err) { return next(err); } - res.redirect('/'); - }); + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Your Free Code Camp password has been changed', + text: [ + 'Hello,\n\n', + 'This email is confirming that you requested to', + 'reset your password for your Free Code Camp account.', + 'This is your email:', + user.email, + '\n' + ].join(' ') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return done(err); } + req.flash('success', { + msg: 'Success! Your password has been changed.' + }); + done(); + }); + } + ], function(err) { + if (err) { return next(err); } + res.redirect('/'); + }); }; /** @@ -592,12 +590,12 @@ exports.postReset = function(req, res, next) { */ exports.getForgot = function(req, res) { - if (req.isAuthenticated()) { - return res.redirect('/'); - } - res.render('account/forgot', { - title: 'Forgot Password' - }); + if (req.isAuthenticated()) { + return res.redirect('/'); + } + res.render('account/forgot', { + title: 'Forgot Password' + }); }; /** @@ -606,80 +604,80 @@ exports.getForgot = function(req, res) { */ exports.postForgot = function(req, res, next) { - var errors = req.validationErrors(); + var errors = req.validationErrors(); - if (errors) { - req.flash('errors', errors); - return res.redirect('/forgot'); - } + if (errors) { + req.flash('errors', errors); + return res.redirect('/forgot'); + } - async.waterfall([ - function(done) { - crypto.randomBytes(16, function(err, buf) { - if (err) { return done(err); } - var token = buf.toString('hex'); - done(null, token); - }); - }, - function(token, done) { - User.findOne({ - email: req.body.email.toLowerCase() - }, function(err, user) { - if (err) { return done(err); } - if (!user) { - req.flash('errors', { - msg: 'No account with that email address exists.' - }); - return res.redirect('/forgot'); - } - - user.resetPasswordToken = token; - user.resetPasswordExpires = Date.now() + 3600000; // 1 hour - - user.save(function(err) { - if (err) { return done(err); } - done(null, token, user); - }); - }); - }, - function(token, user, done) { - var transporter = nodemailer.createTransport({ - service: 'Mandrill', - auth: { - user: secrets.mandrill.user, - pass: secrets.mandrill.password - } - }); - var mailOptions = { - to: user.email, - from: 'Team@freecodecamp.com', - subject: 'Reset your Free Code Camp password', - text: [ - 'You are receiving this email because you (or someone else)\n', - 'requested we reset your Free Code Camp account\'s password.\n\n', - 'Please click on the following link, or paste this into your\n', - 'browser to complete the process:\n\n', - 'http://', - req.headers.host, - '/reset/', - token, - '\n\n', - 'If you did not request this, please ignore this email and\n', - 'your password will remain unchanged.\n' - ].join('') - }; - transporter.sendMail(mailOptions, function(err) { - if (err) { return done(err); } - req.flash('info', { - msg: 'An e-mail has been sent to ' + - user.email + - ' with further instructions.' - }); - done(null, 'done'); - }); + async.waterfall([ + function(done) { + crypto.randomBytes(16, function(err, buf) { + if (err) { return done(err); } + var token = buf.toString('hex'); + done(null, token); + }); + }, + function(token, done) { + User.findOne({ + email: req.body.email.toLowerCase() + }, function(err, user) { + if (err) { return done(err); } + if (!user) { + req.flash('errors', { + msg: 'No account with that email address exists.' + }); + return res.redirect('/forgot'); } - ], function(err) { - if (err) { return next(err); } - res.redirect('/forgot'); - }); + + user.resetPasswordToken = token; + user.resetPasswordExpires = Date.now() + 3600000; // 1 hour + + user.save(function(err) { + if (err) { return done(err); } + done(null, token, user); + }); + }); + }, + function(token, user, done) { + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Reset your Free Code Camp password', + text: [ + 'You are receiving this email because you (or someone else)\n', + 'requested we reset your Free Code Camp account\'s password.\n\n', + 'Please click on the following link, or paste this into your\n', + 'browser to complete the process:\n\n', + 'http://', + req.headers.host, + '/reset/', + token, + '\n\n', + 'If you did not request this, please ignore this email and\n', + 'your password will remain unchanged.\n' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return done(err); } + req.flash('info', { + msg: 'An e-mail has been sent to ' + + user.email + + ' with further instructions.' + }); + done(null, 'done'); + }); + } + ], function(err) { + if (err) { return next(err); } + res.redirect('/forgot'); + }); }; diff --git a/models/User.js b/models/User.js index 09f6a069a3..33d19618cc 100644 --- a/models/User.js +++ b/models/User.js @@ -240,30 +240,6 @@ var userSchema = new mongoose.Schema({ 53: { type: Number, default: 0 - }, - 54: { - type: Number, - default: 0 - }, - 55: { - type: Number, - default: 0 - }, - 56: { - type: Number, - default: 0 - }, - 57: { - type: Number, - default: 0 - }, - 58: { - type: Number, - default: 0 - }, - 59: { - type: Number, - default: 0 } }, profile: { diff --git a/public/css/main.less b/public/css/main.less index f022a1ac43..5b136853e5 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -864,8 +864,11 @@ iframe.iphone { } #cal-heatmap { - margin: 0 auto; - background-color: #fefefe; + width: 361px; +} + +.cal-heatmap-container { + background-color: #EEEEEE; } //uncomment this to see the dimensions of all elements outlined in red diff --git a/public/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js b/public/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js index d7928afc20..d572181512 100644 --- a/public/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js +++ b/public/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js @@ -3,12 +3,11 @@ */ var widgets = []; -var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { +var editor = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { lineNumbers: true, mode: "text/html", theme: 'monokai', runnable: true, - //lint: true, matchBrackets: true, autoCloseBrackets: true, scrollbarStyle: 'null', @@ -16,7 +15,6 @@ var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor") gutters: ["CodeMirror-lint-markers"], onKeyEvent: doLinting }); -var editor = myCodeMirror; // Hijack tab key to insert two spaces instead @@ -36,10 +34,6 @@ editor.setOption("extraKeys", { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); cm.replaceSelection(spaces); } - }, - "Ctrl-Enter": function() { - bonfireExecute(); - return false; } }); @@ -117,7 +111,7 @@ var allSeeds = ''; }); })(); -myCodeMirror.setValue(allSeeds); +editor.setValue(allSeeds); function doLinting () { editor.operation(function () { diff --git a/public/js/main.js b/public/js/main.js index 9c874abfd8..e108d8c9ac 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -30,19 +30,19 @@ $(document).ready(function() { .addClass('animated fadeInDown'); }); - $('.completed-challenge').on('click', function() { - $('#complete-challenge-dialog').modal('show'); - // Only post to server if there is an authenticated user - if ($('.signup-btn-nav').length < 1) { - l = location.pathname.split('/'); - cn = l[l.length - 1]; - $.ajax({ - type: 'POST', - data: {challengeNumber: cn}, - url: '/completed-challenge/' - }); - } - }); + //$('.completed-challenge').on('click', function() { + // $('#complete-challenge-dialog').modal('show'); + // // Only post to server if there is an authenticated user + // if ($('.signup-btn-nav').length < 1) { + // l = location.pathname.split('/'); + // cn = l[l.length - 1]; + // $.ajax({ + // type: 'POST', + // data: {challengeNumber: cn}, + // url: '/completed-challenge/' + // }); + // } + //}); function completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash) { @@ -74,7 +74,8 @@ $(document).ready(function() { completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash); }); - $('#complete-courseware').on('click', function() { + $('#completed-courseware').on('click', function() { + console.log('trying to show modal'); $('#complete-courseware-dialog').modal('show'); }); @@ -105,18 +106,22 @@ $(document).ready(function() { editor.focus(); }); $('#next-courseware-button').on('click', function() { + console.log(passedCoursewareHash); if ($('.signup-btn-nav').length < 1) { $.post( - '/completed-courseware', + '/completed-courseware/', { coursewareInfo: { - coursewareHash: passedCoursewareHash + coursewareHash: passedCoursewareHash, + coursewareName: passedCoursewareName } }).success( - function() { - window.location.href = '/coursewares'; + function(res) { + if (res) { + window.location.href = '/challenges'; + } } - ) + ); } }); diff --git a/views/account/show.jade b/views/account/show.jade index e737c2f64a..c11fe9e4c8 100644 --- a/views/account/show.jade +++ b/views/account/show.jade @@ -41,7 +41,7 @@ block content .col-xs-12.col-sm-12.col-md-3.text-center .background-svg.img-center .points-on-top - = "[ " + progressTimestamps.length + " ]" + = "[ " + user.progressTimestamps.length + " ]" .row @@ -96,13 +96,11 @@ block content i.fa.icon-beaker | Try it out - html. - - - - - .col-xs-12 - #cal-heatmap + .hidden-xs.col-sm-12 + #cal-heatmap.img-center + script(src="//d3js.org/d3.v3.min.js") + script(src="//cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js") + link(rel="stylesheet", href="//cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css") script. var cal = new CalHeatMap(); var calendar = !{JSON.stringify(calender)}; @@ -112,6 +110,7 @@ block content subDomain: "day", data: calendar, cellSize: 15, + align: 'center', cellRadius: 3, cellPadding: 2, tooltip: true, @@ -119,4 +118,4 @@ block content start: new Date().setDate(new Date().getDate() - 90), legendColors: ["#cccccc", "#215f1e"], legend: [1, 2, 3] - }); + }); \ No newline at end of file diff --git a/views/coursewares/showHTML.jade b/views/coursewares/showHTML.jade index d954b939ff..8f2a457ca6 100644 --- a/views/coursewares/showHTML.jade +++ b/views/coursewares/showHTML.jade @@ -18,8 +18,6 @@ block content script(src='/js/lib/codemirror/mode/xml/xml.js') script(src='/js/lib/codemirror/mode/css/css.js') script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') - script(src="https://cdn.jsdelivr.net/ramda/0.10.0/ramda.min.js") - .row.courseware-height .col-xs-12.col-sm-12.col-md-3.col-lg-3 .well @@ -40,23 +38,19 @@ block content span.ion-arrow-up-b | Less information br - .btn.btn-info#showAllCoursewares - - if (cc) - a.btn.btn-primary.btn-lg.btn-block#complete-courseware + a.btn.btn-primary.btn-lg.btn-block#next-courseware-button | Go to my next challenge br | (ctrl + enter) script. var userLoggedIn = true; - - else a.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress - script. - var userLoggedIn = false; + script. + var userLoggedIn = false; br ul#testSuite.list-group - br script(type="text/javascript"). $('#next-courseware-button').attr('disabled', 'disabled'); @@ -64,58 +58,28 @@ block content var challengeSeed = !{JSON.stringify(challengeSeed)}; var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; var challengeName = !{JSON.stringify(name)}; + var passedCoursewareName = challengeName; var prodOrDev = !{JSON.stringify(environment)}; var started = Math.floor(Date.now() / 1000); - var url = ''; - var dashed = !{JSON.stringify(dashedName)}; - console.log(dashed); - .col-xs-12.col-sm-12.col-md-5.col-lg-6 #mainEditorPanel form.code .form-group.codeMirrorView - textarea#codeEditor(autofocus=true) - script(src='/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js') + textarea#codeEditor(autofocus=true, style='display: none;') + script(src='/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js') .col-md-4.col-lg-3 .hidden-xs.hidden-sm img.iphone-position(src="https://s3.amazonaws.com/freecodecamp/iphone6-frame.png") iframe.iphone#preview - - #complete-courseware-dialog.modal(tabindex='-1') - .modal-dialog.animated.zoomIn.fast-animation - .modal-content - .modal-header.challenge-list-header= compliment - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body - .text-center - .animated.zoomInDown.delay-half - span.completion-icon.ion-checkmark-circled.text-primary - - if (cc) - - a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next challenge (ctrl + enter) - - if (points && points > 2) - a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(target="_blank") - i.fa.fa-twitter   - = phrase - - - else - a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress - - #all-coursewares-dialog.modal(tabindex='-1') - .modal-dialog.animated.fadeInUp.fast-animation - .modal-content - .modal-header.all-list-header Challenges - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body - include ../partials/coursewares - script. - $.ajax({ - url: 'https://api-ssl.bitly.com/v3/shorten?access_token=75e7931a19befaafcf108021b6d597e554b2c5c3&longUrl=http%3A%2F%2Ffreecodecamp.com%2Fchallenges%2F' + dashed + '&format=txt' - }) - .success( - function(data) { - console.log(data); - url = "https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Challenge:%20#{name}&url=" + data + "&hashtags=LearnToCode, JavaScript"; - $('.btn-twitter').attr('href', url); - } - ); + #complete-courseware-dialog.modal(tabindex='-1') + .modal-dialog.animated.zoomIn.fast-animation + .modal-content + .modal-header.challenge-list-header + = compliment + a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × + .modal-body + .text-center + .animated.zoomInDown.delay-half + span.completion-icon.ion-checkmark-circled.text-primary + a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress + script(src="/js/lib/coursewares/coursewaresHCJQFramework_v0.1.1.js") \ No newline at end of file diff --git a/views/coursewares/showJS.jade b/views/coursewares/showJS.jade index ca4a1c9670..f06876ab4e 100644 --- a/views/coursewares/showJS.jade +++ b/views/coursewares/showJS.jade @@ -66,8 +66,8 @@ block content - if (cc) a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next challenge (ctrl + enter) - 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}%20%40FreeCodeCamp%20Challenge:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") - i.fa.fa-twitter   + a.animated.fadeIn.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") + i.fa.fa-twitter   = phrase - else - a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress + a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress \ No newline at end of file diff --git a/views/coursewares/showVideo.jade b/views/coursewares/showVideo.jade index 129f2e4581..278a19609f 100644 --- a/views/coursewares/showVideo.jade +++ b/views/coursewares/showVideo.jade @@ -25,18 +25,19 @@ block content var tests = !{JSON.stringify(tests)}; var passedCoursewareHash = !{JSON.stringify(coursewareHash)}; var challengeName = !{JSON.stringify(name)}; + var passedCoursewareName = challengeName; var started = Math.floor(Date.now() / 1000); #complete-courseware-dialog.modal(tabindex='-1') .modal-dialog.animated.zoomIn.fast-animation .modal-content .modal-header.challenge-list-header= compliment - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × + a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × .modal-body(ng-controller="pairedWithController") .text-center .animated.zoomInDown.delay-half span.completion-icon.ion-checkmark-circled.text-primary - if (cc) - a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf, ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Go to my next challenge (ctrl + enter) + a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) Go to my next challenge (ctrl + enter) - 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}%20%40FreeCodeCamp%20Bonfire:%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/bonfires/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank") i.fa.fa-twitter   diff --git a/views/partials/navbar.jade b/views/partials/navbar.jade index 408fab38cb..f74d5dc487 100644 --- a/views/partials/navbar.jade +++ b/views/partials/navbar.jade @@ -12,7 +12,7 @@ .collapse.navbar-collapse ul.nav.navbar-nav.navbar-right.hamburger-dropdown li - a(href='/courseware') Challenges + a(href='/challenges') Challenges li a(href='/chat') Chat li @@ -26,7 +26,9 @@ else li if (user.profile.username) - a(href='/' + user.profile.username) [ #{user.points} ] + + a(href='/' + user.profile.username) [ #{user.progressTimestamps.length} ] + else a(href='/account') [ #{user.points} ] .hidden-xs