Merge branch 'master' into refactor
Conflicts: app.js controllers/api.js controllers/challenges.js gulpfile.js
This commit is contained in:
38
app.js
38
app.js
@ -1,19 +1,19 @@
|
||||
require('newrelic');
|
||||
require('dotenv').load();
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var express = require('express'),
|
||||
debug = require('debug')('freecc:server'),
|
||||
cookieParser = require('cookie-parser'),
|
||||
compress = require('compression'),
|
||||
session = require('express-session'),
|
||||
bodyParser = require('body-parser'),
|
||||
logger = require('morgan'),
|
||||
errorHandler = require('errorhandler'),
|
||||
methodOverride = require('method-override'),
|
||||
bodyParser = require('body-parser'),
|
||||
helmet = require('helmet'),
|
||||
|
||||
_ = require('lodash'),
|
||||
MongoStore = require('connect-mongo')(session),
|
||||
flash = require('express-flash'),
|
||||
@ -99,15 +99,19 @@ app.use(helmet.xframe());
|
||||
var trusted = [
|
||||
'"self"',
|
||||
'*.freecodecamp.com',
|
||||
'*.google-analytics.com',
|
||||
'*.googleapis.com',
|
||||
'*.gstatic.com',
|
||||
'*.doubleclick.net',
|
||||
'*.twitter.com',
|
||||
"*.google-analytics.com",
|
||||
"*.googleapis.com",
|
||||
"*.google.com",
|
||||
"*.gstatic.com",
|
||||
"*.doubleclick.net",
|
||||
"*.twitter.com",
|
||||
'*.twimg.com',
|
||||
'*.githubusercontent.com',
|
||||
'"unsafe-eval"',
|
||||
'"unsafe-inline"'
|
||||
"*.githubusercontent.com",
|
||||
"'unsafe-eval'",
|
||||
"'unsafe-inline'",
|
||||
"*.rafflecopter.com",
|
||||
"localhost:3001"
|
||||
];
|
||||
//TODO(Berks): conditionally add localhost domains to csp;
|
||||
/*var connectSrc;
|
||||
@ -123,14 +127,12 @@ debug(trusted);
|
||||
app.use(helmet.contentSecurityPolicy({
|
||||
defaultSrc: trusted,
|
||||
scriptSrc: ['*.optimizely.com'].concat(trusted),
|
||||
'connect-src': ['ws://localhost:3001/', 'http://localhost:3001/'],
|
||||
'connect-src': ['ws://*.rafflecopter.com', 'wss://*.rafflecopter.com','https://*.rafflecopter.com', 'ws://www.freecodecamp.com', 'ws://localhost:3001/', 'http://localhost:3001', 'http://www.freecodecamp.com'],
|
||||
styleSrc: trusted,
|
||||
imgSrc: ['*.evernote.com', '*.amazonaws.com', 'data:'].concat(trusted),
|
||||
fontSrc: ['"self"', '*.googleapis.com'].concat(trusted),
|
||||
imgSrc: ['*.evernote.com', '*.amazonaws.com', "data:", '*.licdn.com', '*.gravatar.com', '*.youtube.com'].concat(trusted),
|
||||
fontSrc: ["'self", '*.googleapis.com'].concat(trusted),
|
||||
mediaSrc: ['*.amazonaws.com', '*.twitter.com'],
|
||||
frameSrc: ['*.gitter.im', '*.vimeo.com', '*.twitter.com'],
|
||||
// sandbox: ['allow-forms', 'allow-scripts'],
|
||||
// reportUri: '/report-violation',
|
||||
frameSrc: ['*.gitter.im', '*.vimeo.com', '*.twitter.com', '*.rafflecopter.com'],
|
||||
reportOnly: false, // set to true if you only want to report errors
|
||||
setAllHeaders: false, // set to true if you want to set all headers
|
||||
safari5: false // set to true if you want to force buggy CSP in Safari 5
|
||||
@ -207,11 +209,9 @@ app.post(
|
||||
);
|
||||
|
||||
app.get(
|
||||
'/challenges/:challengeNumber',
|
||||
passportConf.isAuthenticated,
|
||||
challengesController.returnChallenge
|
||||
'/challenges/:challengeNumber',
|
||||
challengesController.returnChallenge
|
||||
);
|
||||
|
||||
app.all('/account', passportConf.isAuthenticated);
|
||||
app.get('/account', userController.getAccount);
|
||||
app.post('/account/profile', userController.postUpdateProfile);
|
||||
|
137
controllers/api.js
Normal file
137
controllers/api.js
Normal file
@ -0,0 +1,137 @@
|
||||
var secrets = require('../config/secrets');
|
||||
var User = require('../models/User');
|
||||
var querystring = require('querystring');
|
||||
var validator = require('validator');
|
||||
var async = require('async');
|
||||
var cheerio = require('cheerio');
|
||||
var request = require('request');
|
||||
var graph = require('fbgraph');
|
||||
var Github = require('github-api');
|
||||
var Twit = require('twit');
|
||||
var Linkedin = require('node-linkedin')(secrets.linkedin.clientID, secrets.linkedin.clientSecret, secrets.linkedin.callbackURL);
|
||||
var Y = require('yui/yql');
|
||||
var _ = require('lodash');
|
||||
|
||||
/**
|
||||
* GET /api
|
||||
* List of API examples.
|
||||
*/
|
||||
|
||||
exports.getApi = function(req, res) {
|
||||
res.render('api/index', {
|
||||
title: 'API Examples'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /api/facebook
|
||||
* Facebook API example.
|
||||
*/
|
||||
|
||||
exports.getFacebook = function(req, res, next) {
|
||||
var token = _.find(req.user.tokens, { kind: 'facebook' });
|
||||
graph.setAccessToken(token.accessToken);
|
||||
async.parallel({
|
||||
getMe: function(done) {
|
||||
graph.get(req.user.facebook, function(err, me) {
|
||||
done(err, me);
|
||||
});
|
||||
},
|
||||
getMyFriends: function(done) {
|
||||
graph.get(req.user.facebook + '/friends', function(err, friends) {
|
||||
done(err, friends.data);
|
||||
});
|
||||
}
|
||||
},
|
||||
function(err, results) {
|
||||
if (err) return next(err);
|
||||
res.render('api/facebook', {
|
||||
title: 'Facebook API',
|
||||
me: results.getMe,
|
||||
friends: results.getMyFriends
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /api/github
|
||||
* GitHub API Example.
|
||||
*/
|
||||
|
||||
exports.getGithub = function(req, res, next) {
|
||||
var token = _.find(req.user.tokens, { kind: 'github' });
|
||||
var github = new Github({ token: token.accessToken });
|
||||
var repo = github.getRepo('sahat', 'requirejs-library');
|
||||
repo.show(function(err, repo) {
|
||||
if (err) return next(err);
|
||||
res.render('api/github', {
|
||||
title: 'GitHub API',
|
||||
repo: repo
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /api/twitter
|
||||
* Twiter API example.
|
||||
*/
|
||||
|
||||
exports.getTwitter = function(req, res, next) {
|
||||
var token = _.find(req.user.tokens, { kind: 'twitter' });
|
||||
var T = new Twit({
|
||||
consumer_key: secrets.twitter.consumerKey,
|
||||
consumer_secret: secrets.twitter.consumerSecret,
|
||||
access_token: token.accessToken,
|
||||
access_token_secret: token.tokenSecret
|
||||
});
|
||||
T.get('search/tweets', { q: 'nodejs since:2013-01-01', geocode: '40.71448,-74.00598,5mi', count: 10 }, function(err, reply) {
|
||||
if (err) return next(err);
|
||||
res.render('api/twitter', {
|
||||
title: 'Twitter API',
|
||||
tweets: reply.statuses
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* POST /api/twitter
|
||||
* Post a tweet.
|
||||
*/
|
||||
|
||||
exports.postTwitter = function(req, res, next) {
|
||||
req.assert('tweet', 'Tweet cannot be empty.').notEmpty();
|
||||
var errors = req.validationErrors();
|
||||
if (errors) {
|
||||
req.flash('errors', errors);
|
||||
return res.redirect('/api/twitter');
|
||||
}
|
||||
var token = _.find(req.user.tokens, { kind: 'twitter' });
|
||||
var T = new Twit({
|
||||
consumer_key: secrets.twitter.consumerKey,
|
||||
consumer_secret: secrets.twitter.consumerSecret,
|
||||
access_token: token.accessToken,
|
||||
access_token_secret: token.tokenSecret
|
||||
});
|
||||
T.post('statuses/update', { status: req.body.tweet }, function(err, data, response) {
|
||||
if (err) return next(err);
|
||||
req.flash('success', { msg: 'Tweet has been posted.'});
|
||||
res.redirect('/api/twitter');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /api/linkedin
|
||||
* LinkedIn API example.
|
||||
*/
|
||||
|
||||
exports.getLinkedin = function(req, res, next) {
|
||||
var token = _.find(req.user.tokens, { kind: 'linkedin' });
|
||||
var linkedin = Linkedin.init(token.accessToken);
|
||||
linkedin.people.me(function(err, $in) {
|
||||
if (err) return next(err);
|
||||
res.render('api/linkedin', {
|
||||
title: 'LinkedIn API',
|
||||
profile: $in
|
||||
});
|
||||
});
|
||||
};
|
@ -7,24 +7,49 @@ var _ = require('lodash'),
|
||||
Challenge = require('./../models/Challenge');
|
||||
|
||||
exports.returnChallenge = function(req, res, next) {
|
||||
var challengeNumber = parseInt(req.params.challengeNumber) || 0;
|
||||
|
||||
if (challengeNumber > 59) {
|
||||
challengeNumber = 0;
|
||||
}
|
||||
|
||||
Challenge.findOne({ challengeNumber: challengeNumber }, function(err, c) {
|
||||
if (err) {
|
||||
debug('Challenge err: ', err);
|
||||
return next(err);
|
||||
}
|
||||
res.render('challenges/show', {
|
||||
title: 'Challenge: ' + c.name,
|
||||
name: c.name,
|
||||
video: c.video,
|
||||
time: c.time,
|
||||
steps: c.steps,
|
||||
cc: req.user.challengesHash
|
||||
var challengeNumber = parseInt(req.params.challengeNumber) || 0;
|
||||
var verbs = [
|
||||
'ACED',
|
||||
'NAILED',
|
||||
'ROCKED',
|
||||
'SCORCHED',
|
||||
'DEVASTATED',
|
||||
'OWNED',
|
||||
'CRUSHED',
|
||||
'CONQUERED',
|
||||
'KILLED',
|
||||
'SHREDDED',
|
||||
'ANNIHILATED',
|
||||
'NUKED'
|
||||
];
|
||||
var phrases = [
|
||||
"Shout it from on top of a mountain",
|
||||
"Tell everyone and their dogs",
|
||||
"Show them. Show them all!",
|
||||
"Inspire your friends",
|
||||
"Tell the world of your greatness",
|
||||
"Look accomplished on social media",
|
||||
"Share news of your grand endeavor",
|
||||
"Establish your alibi for the past two hours",
|
||||
"Prove to mom that computers aren't just for games"
|
||||
];
|
||||
if (challengeNumber > 59) { challengeNumber = 0; }
|
||||
Challenge.find({}, function (err, c) {
|
||||
if (err) {
|
||||
debug('Challenge err: ', err);
|
||||
next(err);
|
||||
}
|
||||
res.render('challenges/show', {
|
||||
title: 'Challenge: ' + c[challengeNumber].name,
|
||||
name: c[challengeNumber].name,
|
||||
video: c[challengeNumber].video,
|
||||
time: c[challengeNumber].time,
|
||||
steps: c[challengeNumber].steps,
|
||||
number: challengeNumber,
|
||||
cc: req.user ? req.user.challengesHash : undefined,
|
||||
verb: verbs[Math.floor(Math.random() * verbs.length)],
|
||||
phrase: phrases[Math.floor(Math.random() * phrases.length)],
|
||||
challenges: c
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ var passport = require('passport');
|
||||
var User = require('../models/User');
|
||||
var secrets = require('../config/secrets');
|
||||
var moment = require('moment');
|
||||
var Challenge = require('./../models/Challenge');
|
||||
|
||||
//TODO(Berks): Refactor to use module.exports = {} pattern.
|
||||
/**
|
||||
@ -133,10 +134,17 @@ exports.postEmailSignup = function(req, res, next) {
|
||||
*/
|
||||
|
||||
exports.getAccount = function(req, res) {
|
||||
res.render('account/profile', {
|
||||
title: 'Manage your Free Code Camp Account',
|
||||
cc: req.user.challengesHash,
|
||||
moment: moment
|
||||
Challenge.find({}, function (err, c) {
|
||||
if (err) {
|
||||
console.error('Challenge err: ', err);
|
||||
next(err);
|
||||
}
|
||||
res.render('account/profile', {
|
||||
title: 'Manage your Free Code Camp Account',
|
||||
cc: c,
|
||||
ch: req.user.challengesHash,
|
||||
moment: moment
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
{
|
||||
"name": "Join our Forum",
|
||||
"time": 5,
|
||||
"video": "114578442",
|
||||
"video": "115275066",
|
||||
"challengeNumber": 2,
|
||||
"steps": [
|
||||
"Go to Free Code Camp's forum: <a href='http://forum.freecodecamp.com' target='_blank'>http://forum.freecodecamp.com</a>.",
|
||||
@ -46,7 +46,7 @@
|
||||
"Click on the \"Introduce yourself here\" discussion.",
|
||||
"Here you can read through other Free Code Camp community members' self introductions.",
|
||||
"Go ahead and type a brief self introduction of your own.",
|
||||
"Click on the \"Categories\" drop-down menu. You should see a category called \"Local Chapters\". Click that. If your city isn't already on the list, you can create a topic for it. Otherwise, you can also introduce yourself to the other Code Campers from your city.",
|
||||
"Click on the \"Categories\" drop-down menu. You should see a category called \"Local Chapters\". Click that. If your city isn't already on the list, create a topic for it. Otherwise, introduce yourself to the other Code Campers from your city.",
|
||||
"Come back here daily to ask questions, engage in discussions, and share links to helpful coding tools."
|
||||
]
|
||||
},
|
||||
@ -192,8 +192,8 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Customize Bootstrap with Bootswatch",
|
||||
"time": 10,
|
||||
"name": "Customize Bootstrap",
|
||||
"time": 15,
|
||||
"video": "110752741",
|
||||
"challengeNumber": 16,
|
||||
"steps": [
|
||||
|
@ -40,246 +40,12 @@ block content
|
||||
tr
|
||||
th Challenge
|
||||
th Date Finished
|
||||
if cc[0] > 0
|
||||
tr
|
||||
td Learn how Free Code Camp Works
|
||||
td=moment(cc[0], 'X').format("MMM DD, YYYY")
|
||||
if cc[1] > 0
|
||||
tr
|
||||
td Join Our Chat Room
|
||||
td=moment(cc[1], 'X').format("MMM DD, YYYY")
|
||||
if cc[2] > 0
|
||||
tr
|
||||
td Subscribe to Our Subreddit
|
||||
td=moment(cc[2], 'X').format("MMM DD, YYYY")
|
||||
if cc[3] > 0
|
||||
tr
|
||||
td Build a Personal Website
|
||||
td=moment(cc[3], 'X').format("MMM DD, YYYY")
|
||||
if cc[4] > 0
|
||||
tr
|
||||
td Build a Responsive Blog Theme
|
||||
td=moment(cc[4], 'X').format("MMM DD, YYYY")
|
||||
if cc[5] > 0
|
||||
tr
|
||||
td Build a Small Business Website
|
||||
td=moment(cc[5], 'X').format("MMM DD, YYYY")
|
||||
if cc[6] > 0
|
||||
tr
|
||||
td Tweak HTML and CSS in CodePen
|
||||
td=moment(cc[6], 'X').format("MMM DD, YYYY")
|
||||
if cc[7] > 0
|
||||
tr
|
||||
td Build a CSS Robot
|
||||
td=moment(cc[7], 'X').format("MMM DD, YYYY")
|
||||
if cc[8] > 0
|
||||
tr
|
||||
td Get Started with jQuery
|
||||
td=moment(cc[8], 'X').format("MMM DD, YYYY")
|
||||
if cc[9] > 0
|
||||
tr
|
||||
td Traverse the DOM
|
||||
td=moment(cc[9], 'X').format("MMM DD, YYYY")
|
||||
if cc[10] > 0
|
||||
tr
|
||||
td Work with the DOM
|
||||
td=moment(cc[10], 'X').format("MMM DD, YYYY")
|
||||
if cc[11] > 0
|
||||
tr
|
||||
td Listen for DOM Events
|
||||
td=moment(cc[11], 'X').format("MMM DD, YYYY")
|
||||
if cc[12] > 0
|
||||
tr
|
||||
td Use jQuery for Styling
|
||||
td=moment(cc[12], 'X').format("MMM DD, YYYY")
|
||||
if cc[13] > 0
|
||||
tr
|
||||
td Build a MadLibs Game
|
||||
td=moment(cc[13], 'X').format("MMM DD, YYYY")
|
||||
if cc[14] > 0
|
||||
tr
|
||||
td Discover Chrome's DevTools
|
||||
td=moment(cc[14], 'X').format("MMM DD, YYYY")
|
||||
if cc[15] > 0
|
||||
tr
|
||||
td Tackle jQuery Exercises
|
||||
td=moment(cc[15], 'X').format("MMM DD, YYYY")
|
||||
if cc[16] > 0
|
||||
tr
|
||||
td Customize Bootstrap
|
||||
td=moment(cc[16], 'X').format("MMM DD, YYYY")
|
||||
if cc[17] > 0
|
||||
tr
|
||||
td Inject Animation into CSS
|
||||
td=moment(cc[17], 'X').format("MMM DD, YYYY")
|
||||
if cc[18] > 0
|
||||
tr
|
||||
td Learn Basic Computer Science
|
||||
td=moment(cc[18], 'X').format("MMM DD, YYYY")
|
||||
if cc[19] > 0
|
||||
tr
|
||||
td Learn Loops
|
||||
td=moment(cc[19], 'X').format("MMM DD, YYYY")
|
||||
if cc[20] > 0
|
||||
tr
|
||||
td Learn Computer Hardware
|
||||
td=moment(cc[20], 'X').format("MMM DD, YYYY")
|
||||
if cc[21] > 0
|
||||
tr
|
||||
td Learn Computer Networking
|
||||
td=moment(cc[21], 'X').format("MMM DD, YYYY")
|
||||
if cc[22] > 0
|
||||
tr
|
||||
td Learn Boolean Logic
|
||||
td=moment(cc[22], 'X').format("MMM DD, YYYY")
|
||||
if cc[23] > 0
|
||||
tr
|
||||
td Learn Computer Security
|
||||
td=moment(cc[23], 'X').format("MMM DD, YYYY")
|
||||
if cc[24] > 0
|
||||
tr
|
||||
td Build an Adventure Game
|
||||
td=moment(cc[24], 'X').format("MMM DD, YYYY")
|
||||
if cc[25] > 0
|
||||
tr
|
||||
td Build Rock Paper Scissors
|
||||
td=moment(cc[25], 'X').format("MMM DD, YYYY")
|
||||
if cc[26] > 0
|
||||
tr
|
||||
td Learn JavaScript For Loops
|
||||
td=moment(cc[26], 'X').format("MMM DD, YYYY")
|
||||
if cc[27] > 0
|
||||
tr
|
||||
td Learn JavaScript While Loops
|
||||
td=moment(cc[27], 'X').format("MMM DD, YYYY")
|
||||
if cc[28] > 0
|
||||
tr
|
||||
td Learn Control Flow
|
||||
td=moment(cc[28], 'X').format("MMM DD, YYYY")
|
||||
if cc[29] > 0
|
||||
tr
|
||||
td Build a Contact List
|
||||
td=moment(cc[29], 'X').format("MMM DD, YYYY")
|
||||
if cc[30] > 0
|
||||
tr
|
||||
td Build an Address Book
|
||||
td=moment(cc[30], 'X').format("MMM DD, YYYY")
|
||||
if cc[31] > 0
|
||||
tr
|
||||
td Build a Cash Register
|
||||
td=moment(cc[31], 'X').format("MMM DD, YYYY")
|
||||
if cc[32] > 0
|
||||
tr
|
||||
td Get Help the Hacker Way
|
||||
td=moment(cc[32], 'X').format("MMM DD, YYYY")
|
||||
if cc[33] > 0
|
||||
tr
|
||||
td Learn Regular Expressions
|
||||
td=moment(cc[33], 'X').format("MMM DD, YYYY")
|
||||
if cc[34] > 0
|
||||
tr
|
||||
td Pair Program on CoderByte
|
||||
td=moment(cc[34], 'X').format("MMM DD, YYYY")
|
||||
if cc[35] > 0
|
||||
tr
|
||||
td Learn Relational Database Theory
|
||||
td=moment(cc[35], 'X').format("MMM DD, YYYY")
|
||||
if cc[36] > 0
|
||||
tr
|
||||
td Pair Program to Query SQL pt 1
|
||||
td=moment(cc[36], 'X').format("MMM DD, YYYY")
|
||||
if cc[37] > 0
|
||||
tr
|
||||
td Pair Program to Query SQL pt 2
|
||||
td=moment(cc[37], 'X').format("MMM DD, YYYY")
|
||||
if cc[38] > 0
|
||||
tr
|
||||
td Pair Program to modify SQL pt 1
|
||||
td=moment(cc[38], 'X').format("MMM DD, YYYY")
|
||||
if cc[39] > 0
|
||||
tr
|
||||
td Pair Program to modify SQL pt 2
|
||||
td=moment(cc[39], 'X').format("MMM DD, YYYY")
|
||||
if cc[40] > 0
|
||||
tr
|
||||
td Learn JSON
|
||||
td=moment(cc[40], 'X').format("MMM DD, YYYY")
|
||||
if cc[41] > 0
|
||||
tr
|
||||
td Manage Source Code with Git
|
||||
td=moment(cc[41], 'X').format("MMM DD, YYYY")
|
||||
if cc[42] > 0
|
||||
tr
|
||||
td Get Started with Node.js
|
||||
td=moment(cc[42], 'X').format("MMM DD, YYYY")
|
||||
if cc[43] > 0
|
||||
tr
|
||||
td Try Node.js Events
|
||||
td=moment(cc[43], 'X').format("MMM DD, YYYY")
|
||||
if cc[44] > 0
|
||||
tr
|
||||
td Try Node.js Streams
|
||||
td=moment(cc[44], 'X').format("MMM DD, YYYY")
|
||||
if cc[45] > 0
|
||||
tr
|
||||
td Learn how Node.js Modules Work
|
||||
td=moment(cc[45], 'X').format("MMM DD, YYYY")
|
||||
if cc[46] > 0
|
||||
tr
|
||||
td Start an Express.js Server
|
||||
td=moment(cc[46], 'X').format("MMM DD, YYYY")
|
||||
if cc[47] > 0
|
||||
tr
|
||||
td Use Socket.io
|
||||
td=moment(cc[47], 'X').format("MMM DD, YYYY")
|
||||
if cc[48] > 0
|
||||
tr
|
||||
td Use Redis to Persist Data
|
||||
td=moment(cc[48], 'X').format("MMM DD, YYYY")
|
||||
if cc[49] > 0
|
||||
tr
|
||||
td Dive Deeper into Express.js
|
||||
td=moment(cc[49], 'X').format("MMM DD, YYYY")
|
||||
if cc[50] > 0
|
||||
tr
|
||||
td Set up Express.js Middleware
|
||||
td=moment(cc[50], 'X').format("MMM DD, YYYY")
|
||||
if cc[51] > 0
|
||||
tr
|
||||
td Take Advantage of Parameters
|
||||
td=moment(cc[51], 'X').format("MMM DD, YYYY")
|
||||
if cc[52] > 0
|
||||
tr
|
||||
td Add the Body Parser
|
||||
td=moment(cc[52], 'X').format("MMM DD, YYYY")
|
||||
if cc[53] > 0
|
||||
tr
|
||||
td Configure Routes in Express.js
|
||||
td=moment(cc[53], 'X').format("MMM DD, YYYY")
|
||||
if cc[54] > 0
|
||||
tr
|
||||
td Try MongoDB
|
||||
td=moment(cc[54], 'X').format("MMM DD, YYYY")
|
||||
if cc[55] > 0
|
||||
tr
|
||||
td Get Started with Angular.js
|
||||
td=moment(cc[55], 'X').format("MMM DD, YYYY")
|
||||
if cc[56] > 0
|
||||
tr
|
||||
td Apply Angular.js Directives
|
||||
td=moment(cc[56], 'X').format("MMM DD, YYYY")
|
||||
if cc[57] > 0
|
||||
tr
|
||||
td Power Forms with Angular.js
|
||||
td=moment(cc[57], 'X').format("MMM DD, YYYY")
|
||||
if cc[58] > 0
|
||||
tr
|
||||
td Customize Angular.js Directives
|
||||
td=moment(cc[58], 'X').format("MMM DD, YYYY")
|
||||
if cc[59] > 0
|
||||
tr
|
||||
td Create Angular.js Services
|
||||
td=moment(cc[59], 'X').format("MMM DD, YYYY")
|
||||
for challenge in cc
|
||||
if ch[challenge.challengeNumber] > 0
|
||||
tr
|
||||
td= cc[challenge.challengeNumber].name
|
||||
td= moment(ch[challenge.challengeNumber], 'X').format("MMM DD, YYYY")
|
||||
|
||||
h3 Danger Zone
|
||||
button.btn.btn-danger.confirm-deletion
|
||||
span.ion-trash-b
|
||||
|
@ -15,7 +15,7 @@ block content
|
||||
.btn.btn-primary.btn-big.btn-block.completed-challenge I've completed this challenge
|
||||
.ten-pixel-break
|
||||
.btn.btn-success.btn-large.btn-block.skip-challenge I want to skip this challenge for now
|
||||
- if (cc[2] > 0)
|
||||
- if (cc && cc[2] > 0)
|
||||
.panel-footer.text-center
|
||||
span Need a break? Check out our:
|
||||
a(href="https://gitter.im/FreeCodeCamp/FreeCodeCamp", target="_blank") Chat Room
|
||||
@ -34,6 +34,11 @@ block content
|
||||
.animated.zoomInUp.delay-1
|
||||
span.landing-icon.ion-checkmark-circled.text-primary
|
||||
a.animated.fadeIn.delay-2.btn.btn-lg.btn-primary.btn-block.next-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge
|
||||
if (cc && cc[2] > 0)
|
||||
a.animated.fadeIn.delay-2.btn-twitter.btn.btn-lg.btn-info.btn-block(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")
|
||||
i.fa.fa-twitter
|
||||
= phrase
|
||||
|
||||
#skip-dialog.modal
|
||||
.modal-dialog.animated.zoomIn.fast-animation
|
||||
.modal-content
|
||||
|
@ -2,185 +2,9 @@
|
||||
.panel-heading Challenges
|
||||
.panel-body
|
||||
ol(start='0')
|
||||
for challenge in challenges
|
||||
li
|
||||
a(href="/challenges/0", class="#{ cc[0] > 0 ? 'strikethrough' : '' }") Learn how Free Code Camp Works
|
||||
| (2 minutes)
|
||||
li
|
||||
a(href="/challenges/1", class="#{ cc[1] > 0 ? 'strikethrough' : '' }") Join Our Chat Room
|
||||
| (5 minutes)
|
||||
li
|
||||
a(href="/challenges/2", class="#{ cc[2] > 0 ? 'strikethrough' : '' }") Subscribe to Our Subreddit
|
||||
| (5 minutes)
|
||||
li
|
||||
a(href="/challenges/3", class="#{ cc[3] > 0 ? 'strikethrough' : '' }") Build a Personal Website
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/4", class="#{ cc[4] > 0 ? 'strikethrough' : '' }") Build a Responsive Blog Theme
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/5", class="#{ cc[5] > 0 ? 'strikethrough' : '' }") Build a Small Business Website
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/6", class="#{ cc[6] > 0 ? 'strikethrough' : '' }") Tweak HTML and CSS in CodePen
|
||||
| (10 minutes)
|
||||
li
|
||||
a(href="/challenges/7", class="#{ cc[7] > 0 ? 'strikethrough' : '' }") Build a CSS Robot
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/8", class="#{ cc[8] > 0 ? 'strikethrough' : '' }") Get Started with jQuery
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/9", class="#{ cc[9] > 0 ? 'strikethrough' : '' }") Traverse the DOM
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/10", class="#{ cc[10] > 0 ? 'strikethrough' : '' }") Work with the DOM
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/11", class="#{ cc[11] > 0 ? 'strikethrough' : '' }") Listen for DOM Events
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/12", class="#{ cc[12] > 0 ? 'strikethrough' : '' }") Use jQuery for Styling
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/13", class="#{ cc[13] > 0 ? 'strikethrough' : '' }") Build a MadLibs Game
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/14", class="#{ cc[14] > 0 ? 'strikethrough' : '' }") Discover Chrome's DevTools
|
||||
| (90 minutes)
|
||||
li
|
||||
a(href="/challenges/15", class="#{ cc[15] > 0 ? 'strikethrough' : '' }") Tackle jQuery Exercises
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/16", class="#{ cc[16] > 0 ? 'strikethrough' : '' }") Customize Bootstrap
|
||||
| (10 minutes)
|
||||
li
|
||||
a(href="/challenges/17", class="#{ cc[17] > 0 ? 'strikethrough' : '' }") Inject Animation into CSS
|
||||
| (15 minutes)
|
||||
li
|
||||
a(href="/challenges/18", class="#{ cc[18] > 0 ? 'strikethrough' : '' }") Learn Basic Computer Science
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/19", class="#{ cc[19] > 0 ? 'strikethrough' : '' }") Learn Loops
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/20", class="#{ cc[20] > 0 ? 'strikethrough' : '' }") Learn Computer Hardware
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/21", class="#{ cc[21] > 0 ? 'strikethrough' : '' }") Learn Computer Networking
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/22", class="#{ cc[22] > 0 ? 'strikethrough' : '' }") Learn Boolean Logic
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/23", class="#{ cc[23] > 0 ? 'strikethrough' : '' }") Learn Computer Security
|
||||
| (120 minutes)
|
||||
li
|
||||
a(href="/challenges/24", class="#{ cc[24] > 0 ? 'strikethrough' : '' }") Build an Adventure Game
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/25", class="#{ cc[25] > 0 ? 'strikethrough' : '' }") Build Rock Paper Scissors
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/26", class="#{ cc[26] > 0 ? 'strikethrough' : '' }") Learn JavaScript For Loops
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/27", class="#{ cc[27] > 0 ? 'strikethrough' : '' }") Learn JavaScript While Loops
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/28", class="#{ cc[28] > 0 ? 'strikethrough' : '' }") Learn Control Flow
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/29", class="#{ cc[29] > 0 ? 'strikethrough' : '' }") Build a Contact List
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/30", class="#{ cc[30] > 0 ? 'strikethrough' : '' }") Build an Address Book
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/31", class="#{ cc[31] > 0 ? 'strikethrough' : '' }") Build a Cash Register
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/32", class="#{ cc[32] > 0 ? 'strikethrough' : '' }") Get Help the Hacker Way
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/33", class="#{ cc[33] > 0 ? 'strikethrough' : '' }") Learn Regular Expressions
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/34", class="#{ cc[34] > 0 ? 'strikethrough' : '' }") Pair Program on CoderByte
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/35", class="#{ cc[35] > 0 ? 'strikethrough' : '' }") Learn Relational Database Theory
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/36", class="#{ cc[36] > 0 ? 'strikethrough' : '' }") Pair Program to Query SQL pt 1
|
||||
| (90 minutes)
|
||||
li
|
||||
a(href="/challenges/37", class="#{ cc[37] > 0 ? 'strikethrough' : '' }") Pair Program to Query SQL pt 2
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/38", class="#{ cc[38] > 0 ? 'strikethrough' : '' }") Pair Program to modify SQL pt 1
|
||||
| (90 minutes)
|
||||
li
|
||||
a(href="/challenges/39", class="#{ cc[39] > 0 ? 'strikethrough' : '' }") Pair Program to modify SQL pt 2
|
||||
| (60 minutes)
|
||||
li
|
||||
a(href="/challenges/40", class="#{ cc[40] > 0 ? 'strikethrough' : '' }") Learn JSON
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/41", class="#{ cc[41] > 0 ? 'strikethrough' : '' }") Manage Source Code with Git
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/42", class="#{ cc[42] > 0 ? 'strikethrough' : '' }") Get Started with Node.js
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/43", class="#{ cc[43] > 0 ? 'strikethrough' : '' }") Try Node.js Events
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/44", class="#{ cc[44] > 0 ? 'strikethrough' : '' }") Try Node.js Streams
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/45", class="#{ cc[45] > 0 ? 'strikethrough' : '' }") Learn how Node.js Modules Work
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/46", class="#{ cc[46] > 0 ? 'strikethrough' : '' }") Start an Express.js Server
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/47", class="#{ cc[47] > 0 ? 'strikethrough' : '' }") Use Socket.io
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/48", class="#{ cc[48] > 0 ? 'strikethrough' : '' }") Use Redis to Persist Data
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/49", class="#{ cc[49] > 0 ? 'strikethrough' : '' }") Dive Deeper into Express.js
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/50", class="#{ cc[50] > 0 ? 'strikethrough' : '' }") Set up Express.js Middleware
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/51", class="#{ cc[51] > 0 ? 'strikethrough' : '' }") Take Advantage of Parameters
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/52", class="#{ cc[52] > 0 ? 'strikethrough' : '' }") Add the Body Parser
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/53", class="#{ cc[53] > 0 ? 'strikethrough' : '' }") Configure Routes in Express.js
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/54", class="#{ cc[54] > 0 ? 'strikethrough' : '' }") Try MongoDB
|
||||
| (30 minutes)
|
||||
li
|
||||
a(href="/challenges/55", class="#{ cc[55] > 0 ? 'strikethrough' : '' }") Get Started with Angular.js
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/56", class="#{ cc[56] > 0 ? 'strikethrough' : '' }") Apply Angular.js Directives
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/57", class="#{ cc[57] > 0 ? 'strikethrough' : '' }") Power Forms with Angular.js
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/58", class="#{ cc[58] > 0 ? 'strikethrough' : '' }") Customize Angular.js Directives
|
||||
| (45 minutes)
|
||||
li
|
||||
a(href="/challenges/59", class="#{ cc[59] > 0 ? 'strikethrough' : '' }") Create Angular.js Services
|
||||
| (45 minutes)
|
||||
a(href="/challenges/#{challenge.challengeNumber}", class="#{ (cc && cc[challenge.challengeNumber] > 0) ? 'strikethrough' : '' }") #{challenge.name}
|
||||
| (#{challenge.time} mins)
|
||||
|
||||
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
|
||||
a.btn.btn-primary(href="/done-with-first-100-hours", class="#{ ((cc && cc[59] === 0) || (!cc)) ? 'disabled' : '' }") I've finished all Free Code Camp challenges and all the Easy and Medium CoderByte Challenges
|
@ -27,26 +27,26 @@
|
||||
a(href='/')
|
||||
span.ion-map
|
||||
| My Challenges
|
||||
- if (cc[1] > 0)
|
||||
li.hamburger
|
||||
a(href='https://gitter.im/FreeCodeCamp/FreeCodeCamp', target='_blank')
|
||||
span.ion-coffee
|
||||
| Chat Room
|
||||
- else
|
||||
- if (cc && cc[1] < 1)
|
||||
li.hamburger.disabled
|
||||
a(href='https://gitter.im/FreeCodeCamp/FreeCodeCamp', target='_blank')
|
||||
span.ion-coffee
|
||||
| Chat Room (do Challenge 1 first)
|
||||
- if (cc[2] > 0)
|
||||
li.hamburger
|
||||
a(href='http://forum.freecodecamp.com/', target='_blank')
|
||||
span.ion-planet
|
||||
| Forum
|
||||
- else
|
||||
li.hamburger
|
||||
a(href='https://gitter.im/FreeCodeCamp/FreeCodeCamp', target='_blank')
|
||||
span.ion-coffee
|
||||
| Chat Room
|
||||
- if (cc && cc[2] < 1)
|
||||
li.hamburger.disabled
|
||||
a(href='http://forum.freecodecamp.com/', target='_blank')
|
||||
span.ion-planet
|
||||
| Forum (do Challenge 2 first)
|
||||
- else
|
||||
li.hamburger
|
||||
a(href='http://forum.freecodecamp.com/', target='_blank')
|
||||
span.ion-planet
|
||||
| Forum
|
||||
li.hamburger
|
||||
a(href='/account')
|
||||
span.ion-person
|
||||
|
Reference in New Issue
Block a user