start adding Courseware controllers, routes etc.

This commit is contained in:
Michael Q Larson
2015-02-01 14:22:34 -08:00
parent d7d4727c0f
commit afab456ad9
10 changed files with 411 additions and 68 deletions

View File

@ -8,13 +8,14 @@ var _ = require('lodash'),
* Bonfire controller
*/
exports.courseware = function(req, res) {
res.render('courseware/show.jade', {
var highestBonfireNumber = resources.numberOfBonfires();
exports.bonfireNames = function(req, res) {
res.render('bonfires/showList', {
bonfireList: resources.allBonfireNames()
});
};
var highestBonfireNumber = resources.numberOfBonfires();
exports.index = function(req, res) {
res.render('bonfire/show.jade', {
completedWith: null,

207
controllers/courseware.js Normal file
View File

@ -0,0 +1,207 @@
var _ = require('lodash'),
debug = require('debug')('freecc:cntr:coursewares'),
Courseware = require('./../models/Courseware'),
User = require('./../models/User'),
resources = require('./resources');
/**
* Courseware controller
*/
exports.courseware = function(req, res) {
res.render('courseware/show.jade', {
});
};
var highestCourswareNumber = resources.numberOfCoursewares();
exports.returnNextCourseware = function(req, res, next) {
if (!req.user) {
return res.redirect('coursewares/welcome-to-courseware');
}
var completed = req.user.completedBonfires.map(function (elem) {
return elem._id;
});
req.user.uncompletedBonfires = resources.allBonfireIds().filter(function (elem) {
if (completed.indexOf(elem) === -1) {
return elem;
}
});
req.user.save();
var uncompletedCoursewares = req.user.uncompletedCoursewares;
var displayedCoursewares = Courseware.find({'_id': uncompletedCoursewares[0]});
displayedCoursewares.exec(function(err, bonfire) {
if (err) {
next(err);
}
courseware = courseware.pop();
nameString = courseware[0].name.toLowerCase().replace(/\s/g, '-');
return res.redirect('/bonfires/' + nameString);
//res.render('bonfire/show', {
// completedWith: null,
// title: bonfire[bonfireNumber].name,
// name: bonfire[bonfireNumber].name,
// difficulty: +bonfire[bonfireNumber].difficulty,
// brief: bonfire[bonfireNumber].description[0],
// details: bonfire[bonfireNumber].description.slice(1),
// tests: bonfire[bonfireNumber].tests,
// challengeSeed: bonfire[bonfireNumber].challengeSeed,
// challengeEntryPoint: bonfire[bonfireNumber].challengeEntryPoint,
// cc: req.user ? req.user.bonfiresHash : undefined,
// points: req.user ? req.user.points : undefined,
// verb: resources.randomVerb(),
// phrase: resources.randomPhrase(),
// compliments: resources.randomCompliment(),
// bonfires: bonfire,
// bonfireHash: bonfire[bonfireNumber]._id
//});
});
};
exports.returnIndividualBonfire = function(req, res, next) {
var dashedName = req.params.bonfireName;
bonfireName = dashedName.replace(/\-/g, ' ');
var bonfireNumber = 0;
Bonfire.find({"name" : new RegExp(bonfireName, 'i')}, function(err, bonfire) {
if (err) {
next(err);
}
if (bonfire.length < 1) {
req.flash('errors', {
msg: "404: We couldn't find a bonfire with that name. Please double check the name."
});
return res.redirect('/bonfires/meet-bonfire')
} else {
res.render('bonfire/show', {
completedWith: null,
title: bonfire[bonfireNumber].name,
dashedName: dashedName,
name: bonfire[bonfireNumber].name,
difficulty: Math.floor(+bonfire[bonfireNumber].difficulty),
brief: bonfire[bonfireNumber].description[0],
details: bonfire[bonfireNumber].description.slice(1),
tests: bonfire[bonfireNumber].tests,
challengeSeed: bonfire[bonfireNumber].challengeSeed,
challengeEntryPoint: bonfire[bonfireNumber].challengeEntryPoint,
cc: !!req.user,
points: req.user ? req.user.points : undefined,
verb: resources.randomVerb(),
phrase: resources.randomPhrase(),
compliment: resources.randomCompliment(),
bonfires: bonfire,
bonfireHash: bonfire[bonfireNumber]._id
});
}
});
};
/**
* Bonfire generator
*/
exports.returnGenerator = function(req, res) {
res.render('bonfire/generator', {
title: null,
name: null,
difficulty: null,
brief: null,
details: null,
tests: null,
challengeSeed: null,
challengeEntryPoint: null,
bonfireHash: randomString()
});
};
/**
* Post for bonfire generation
*/
function randomString() {
var chars = "0123456789abcdef";
var string_length = 23;
var randomstring = 'a';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
return randomstring;
}
/**
*
*/
exports.testBonfire = function(req, res) {
var bonfireName = req.body.name,
bonfireTests = req.body.tests,
bonfireDifficulty = req.body.difficulty,
bonfireDescription = req.body.description,
bonfireEntryPoint = req.body.challengeEntryPoint,
bonfireChallengeSeed = req.body.challengeSeed;
bonfireTests = bonfireTests.split('\r\n');
bonfireDescription = bonfireDescription.split('\r\n');
bonfireTests.filter(getRidOfEmpties);
bonfireDescription.filter(getRidOfEmpties);
bonfireChallengeSeed = bonfireChallengeSeed.replace('\r', '');
res.render('bonfire/show', {
completedWith: null,
title: bonfireName,
name: bonfireName,
difficulty: +bonfireDifficulty,
brief: bonfireDescription[0],
details: bonfireDescription.slice(1),
tests: bonfireTests,
challengeSeed: bonfireChallengeSeed,
challengeEntryPoint: bonfireEntryPoint,
cc: req.user ? req.user.bonfiresHash : undefined,
points: req.user ? req.user.points : undefined,
verb: resources.randomVerb(),
phrase: resources.randomPhrase(),
compliment: resources.randomCompliment(),
bonfires: [],
bonfireHash: "test"
});
};
function getRidOfEmpties(elem) {
if (elem.length > 0) {
return elem;
}
}
exports.publicGenerator = function(req, res) {
res.render('bonfire/public-generator');
}
exports.generateChallenge = function(req, res) {
var bonfireName = req.body.name,
bonfireTests = req.body.tests,
bonfireDifficulty = req.body.difficulty,
bonfireDescription = req.body.description,
bonfireEntryPoint = req.body.challengeEntryPoint,
bonfireChallengeSeed = req.body.challengeSeed;
bonfireTests = bonfireTests.split('\r\n');
bonfireDescription = bonfireDescription.split('\r\n');
bonfireTests.filter(getRidOfEmpties);
bonfireDescription.filter(getRidOfEmpties);
bonfireChallengeSeed = bonfireChallengeSeed.replace('\r', '');
var response = {
_id: randomString(),
name: bonfireName,
difficulty: bonfireDifficulty,
description: bonfireDescription,
challengeEntryPoint: bonfireEntryPoint,
challengeSeed: bonfireChallengeSeed,
tests: bonfireTests
};
res.send(response);
}

View File

@ -202,7 +202,21 @@ module.exports = {
})
.map(function(elem) {
return elem._id;
});
},
allBonfireNames: function() {
return bonfires.map(function(elem) {
return {
name: elem.name,
difficulty: elem.difficulty
}
})
.sort(function(a, b) {
return a.difficulty - b.difficulty;
})
.map(function(elem) {
return elem.name;
});
}
};

View File

@ -17,7 +17,6 @@ var bonfireSchema = new mongoose.Schema({
tests: Array,
challengeSeed: String,
challengeEntryPoint: String,
challengeEntryPointNegate: String
});
module.exports = mongoose.model('Bonfire', bonfireSchema);

21
models/Courseware.js Normal file
View File

@ -0,0 +1,21 @@
var mongoose = require('mongoose');
var secrets = require('../config/secrets');
/**
*
* @type {exports.Schema}
*/
var coursewareSchema = new mongoose.Schema({
name: {
type: String,
unique: true
},
difficulty: String,
description: Array,
tests: Array,
challengeSeed: String,
challengeEntryPoint: String
});
module.exports = mongoose.model('Courseware', coursewareSchema);

View File

@ -643,6 +643,10 @@ div.CodeMirror-scroll {
margin-top: -30px;
}
iframe.iphone {
width: 401px;
position: absolute;
}
//uncomment this to see the dimensions of all elements outlined in red

View File

@ -0,0 +1,19 @@
[
{
"_id" : "bd7123c8c441eddfaeb5bdef",
"name": "Meet Bonfire",
"difficulty": "0",
"description": [
"Click the button below for further instructions.",
"Your goal is to fix the failing test.",
"First, run all the tests by clickin \"Run code\" or by pressing Control + Enter",
"The failing test is in red. Fix the code so that all tests pass. Then you can move on to the next Bonfire."
],
"tests": [
"expect(meetBonfire(\"test\")).to.be.a(\"boolean\");",
"expect(meetBonfire(\"test\")).to.be.true;"
],
"challengeSeed": "function meetBonfire(argument) {\n // Good luck!\n console.log(\"you can read this function's argument in the developer tools\", argument);\n\nreturn false;\n}\n\n",
"challengeEntryPoint": "meetBonfire(\"You can do this!\");"
}
]

View File

@ -1,20 +1,23 @@
require('dotenv').load();
var Challenge = require('../models/Challenge.js'),
Bonfire = require('../models/Bonfire.js'),
Courseware = require('../models/Courseware.js'),
mongoose = require('mongoose'),
secrets = require('../config/secrets'),
challenges = require('./challenges.json'),
coursewares = require('./coursewares.json'),
bonfires = require('./bonfires.json');
mongoose.connect(secrets.db);
var counter = 0;
var offerings = 3;
var CompletionMonitor = function() {
counter++;
console.log('call ' + counter);
if (counter < 2) {
if (counter < offerings) {
return;
} else {
process.exit(0);
@ -53,7 +56,21 @@ Bonfire.remove({}, function(err, data) {
CompletionMonitor();
});
console.log('bonfires');
});
Courseware.remove({}, function(err, data) {
if (err) {
console.error(err);
} else {
console.log('Deleted ', data);
}
Courseware.create(coursewares, function(err, data) {
if (err) {
console.log(err);
} else {
console.log('Saved ', data);
}
CompletionMonitor();
});
console.log('coursewares');
});

View File

@ -1,60 +0,0 @@
extends ../layout-wide
block content
script(src='/js/lib/codemirror/lib/codemirror.js')
script(src='/js/lib/codemirror/addon/edit/closebrackets.js')
script(src='/js/lib/codemirror/addon/edit/matchbrackets.js')
script(src='/js/lib/codemirror/addon/lint/lint.js')
script(src='/js/lib/codemirror/addon/lint/javascript-lint.js')
script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js')
script(src='/js/lib/chai/chai.js')
link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css')
link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css')
link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css')
link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono")
script(src='/js/lib/codemirror/mode/javascript/javascript.js')
script(src='/js/lib/jailed/jailed.js')
script(src='/js/lib/bonfire/bonfireInit.js')
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')
style(type='text/css').
style.
.CodeMirror {
float: left;
width: 50%;
border: 1px solid black;
}
iframe {
width: 49%;
float: left;
height: 300px;
border: 1px solid black;
border-left: 0px;
}
textarea#code(name='code')
iframe#preview
script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js")
script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js")
style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css")
script.
var delay;
// Initialize CodeMirror editor with a nice html5 canvas demo.
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
mode: 'text/html'
});
editor.on("change", function () {
clearTimeout(delay);
delay = setTimeout(updatePreview, 300);
});
function updatePreview() {
var previewFrame = document.getElementById('preview');
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
preview.open();
preview.write(editor.getValue());
preview.close();
}
setTimeout(updatePreview, 300);

121
views/coursewares/show.jade Normal file
View File

@ -0,0 +1,121 @@
extends ../layout-wide
block content
script(src='/js/lib/codemirror/lib/codemirror.js')
script(src='/js/lib/codemirror/addon/edit/closebrackets.js')
script(src='/js/lib/codemirror/addon/edit/matchbrackets.js')
script(src='/js/lib/codemirror/addon/lint/lint.js')
script(src='/js/lib/codemirror/addon/lint/javascript-lint.js')
script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js')
script(src='/js/lib/chai/chai.js')
link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css')
link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css')
link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css')
link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono")
script(src='/js/lib/codemirror/mode/javascript/javascript.js')
script(src='/js/lib/jailed/jailed.js')
script(src='/js/lib/bonfire/bonfireInit.js')
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')
.row
.col-xs-12.col-sm-12.col-md-3.bonfire-top
h2.text-center= name
.well
.row
.col-xs-12
.bonfire-instructions
p= brief
#brief-instructions
.text-center
button#more-info.btn.btn-info
span.ion-help-circled
| More information
#long-instructions.row.hide
.col-xs-12
for sentence in details
p!= sentence
.text-center
button#less-info.btn.btn-info
span.ion-help-circled
| Less information
#submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter)
br
form.code
.form-group.codeMirrorView
textarea#codeOutput
br
#testSuite
br
script(type="text/javascript").
var tests = !{JSON.stringify(tests)};
var challengeSeed = !{JSON.stringify(challengeSeed)};
var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)};
var passedBonfireHash = !{JSON.stringify(bonfireHash)};
.col-xs-12.col-sm-12.col-md-5
#mainEditorPanel
form.code
.form-group.codeMirrorView
textarea#codeEditor(autofocus=true)
script(src='/js/lib/bonfire/bonfireFramework.js')
#complete-bonfire-dialog.modal(tabindex='-1')
.col-xs-12.col-sm-12.col-md-4
iframe.iphone#preview
//.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(ng-controller="pairedWithController")
// .text-center
// .animated.zoomInDown.delay-half
// span.landing-icon.ion-checkmark-circled.text-primary
// - if (cc)
// form.form-horizontal(novalidate='novalidate', name='completedWithForm')
// .form-group.text-center
// .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2.animated.fadeIn
// // extra field to distract password tools like lastpass from injecting css into our username field
// input.form-control(ng-show="false")
// input.form-control#completed-with(name="existingUser", placeholder="If you paired, enter your pair's username here", existing-username='', ng-model="existingUser", autofocus)
// .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0")
// alert(type='danger')
// span.ion-close-circled
// | Username not found
// a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-bonfire-button(name='_csrf', value=_csrf, aria-hidden='true', ng-disabled='completedWithForm.$invalid && existingUser.length > 0') Take me to my next challenge
// - 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 &nbsp;
// = phrase
// - else
// a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress
// #all-bonfires-dialog.modal(tabindex='-1')
//.modal-dialog.animated.fadeInUp.fast-animation
// .modal-content
// .modal-header.challenge-list-header Bonfires
// a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') ×
// .modal-body
// include ../partials/bonfires
//img(src="https://s3.amazonaws.com/freecodecamp/iphone6-frame.png")
//script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js")
//script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js")
//style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css")
script.
var delay;
// Initialize CodeMirror editor with a nice html5 canvas demo.
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
mode: 'text/html'
});
editor.on("change", function () {
clearTimeout(delay);
delay = setTimeout(updatePreview, 300);
});
function updatePreview() {
var previewFrame = document.getElementById('preview');
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
preview.open();
preview.write(editor.getValue());
preview.close();
}
setTimeout(updatePreview, 300);