Merge branch 'staging' of github.com:FreeCodeCamp/freecodecamp into staging
This commit is contained in:
@ -47,7 +47,6 @@
|
||||
"express-session": "~1.9.2",
|
||||
"express-validator": "~2.8.0",
|
||||
"font-awesome": "~4.3.0",
|
||||
"forcedomain": "~0.4.0",
|
||||
"forever": "~0.14.1",
|
||||
"frameguard": "^0.2.2",
|
||||
"github-api": "~0.7.0",
|
||||
|
12
pm2Start.js
Normal file
12
pm2Start.js
Normal file
@ -0,0 +1,12 @@
|
||||
var pm2 = require('pm2');
|
||||
pm2.connect(function() {
|
||||
pm2.start({
|
||||
name: 'server',
|
||||
script: 'server/server.js',
|
||||
exec_mode: 'cluster',
|
||||
instances: '2',
|
||||
max_memory_restart: '900M'
|
||||
}, function(err, apps) {
|
||||
pm2.disconnect();
|
||||
});
|
||||
});
|
@ -18,7 +18,7 @@ editor.setSize("100%", "auto");
|
||||
// Hijack tab key to enter two spaces intead
|
||||
editor.setOption("extraKeys", {
|
||||
Tab: function(cm) {
|
||||
if (cm.somethingSelected()){
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection("add");
|
||||
} else {
|
||||
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
||||
@ -26,7 +26,7 @@ editor.setOption("extraKeys", {
|
||||
}
|
||||
},
|
||||
"Shift-Tab": function(cm) {
|
||||
if (cm.somethingSelected()){
|
||||
if (cm.somethingSelected()) {
|
||||
cm.indentSelection("subtract");
|
||||
} else {
|
||||
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
||||
@ -121,7 +121,10 @@ codeOutput.setValue('/**\n' +
|
||||
' */');
|
||||
codeOutput.setSize("100%", "100%");
|
||||
var info = editor.getScrollInfo();
|
||||
var after = editor.charCoords({line: editor.getCursor().line + 1, ch: 0}, "local").top;
|
||||
var after = editor.charCoords({
|
||||
line: editor.getCursor().line + 1,
|
||||
ch: 0
|
||||
}, "local").top;
|
||||
if (info.top + info.clientHeight < after)
|
||||
editor.scrollTo(null, after - info.clientHeight + 3);
|
||||
|
||||
@ -143,8 +146,8 @@ editorValue = (localBonfire.isAlive())? localBonfire.getEditorValue() : allSeeds
|
||||
|
||||
myCodeMirror.setValue(editorValue);
|
||||
|
||||
function doLinting () {
|
||||
editor.operation(function () {
|
||||
function doLinting() {
|
||||
editor.operation(function() {
|
||||
for (var i = 0; i < widgets.length; ++i)
|
||||
editor.removeLineWidget(widgets[i]);
|
||||
widgets.length = 0;
|
||||
@ -166,14 +169,14 @@ function doLinting () {
|
||||
});
|
||||
};
|
||||
|
||||
$('#submitButton').on('click', function () {
|
||||
$('#submitButton').on('click', function() {
|
||||
bonfireExecute();
|
||||
});
|
||||
|
||||
function bonfireExecute() {
|
||||
attempts++;
|
||||
ga('send', 'event', 'Challenge', 'ran-code', challenge_Name);
|
||||
userTests= null;
|
||||
ga('send', 'event', 'Challenge', 'ran-code', challenge_Name);
|
||||
userTests = null;
|
||||
$('#codeOutput').empty();
|
||||
var userJavaScript = myCodeMirror.getValue();
|
||||
userJavaScript = removeComments(userJavaScript);
|
||||
@ -205,16 +208,23 @@ var scrapeTests = function(userJavaScript) {
|
||||
}
|
||||
|
||||
var counter = 0;
|
||||
var regex = new RegExp(/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/);
|
||||
var regex = new RegExp(
|
||||
/(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/
|
||||
);
|
||||
var match = regex.exec(userJavaScript);
|
||||
while (match != null) {
|
||||
var replacement = '//' + counter + testSalt;
|
||||
userJavaScript = userJavaScript.substring(0, match.index) + replacement + userJavaScript.substring(match.index + match[0].length);
|
||||
userJavaScript = userJavaScript.substring(0, match.index) + replacement +
|
||||
userJavaScript.substring(match.index + match[0].length);
|
||||
|
||||
if (!userTests) {
|
||||
userTests= [];
|
||||
userTests = [];
|
||||
}
|
||||
userTests.push({"text": match[0], "line": counter, "err": null});
|
||||
userTests.push({
|
||||
"text": match[0],
|
||||
"line": counter,
|
||||
"err": null
|
||||
});
|
||||
counter++;
|
||||
match = regex.exec(userJavaScript);
|
||||
}
|
||||
@ -236,17 +246,22 @@ var createTestDisplay = function() {
|
||||
if (pushed) {
|
||||
userTests.pop();
|
||||
}
|
||||
for (var i = 0; i < userTests.length;i++) {
|
||||
for (var i = 0; i < userTests.length; i++) {
|
||||
var test = userTests[i];
|
||||
var testDoc = document.createElement("div");
|
||||
if (test.err != null) {
|
||||
console.log('Should be displaying bad tests');
|
||||
$(testDoc)
|
||||
.html("<div class='row'><div class='col-xs-2 text-center'><i class='ion-close-circled big-error-icon'></i></div><div class='col-xs-10 test-output wrappable test-vertical-center grayed-out-test-output'>" + test.text + "</div><div class='col-xs-10 test-output wrappable'>" + test.err + "</div></div><div class='ten-pixel-break'/>")
|
||||
.html(
|
||||
"<div class='row'><div class='col-xs-2 text-center'><i class='ion-close-circled big-error-icon'></i></div><div class='col-xs-10 test-output wrappable test-vertical-center grayed-out-test-output'>" +
|
||||
test.text + "</div><div class='col-xs-10 test-output wrappable'>" +
|
||||
test.err + "</div></div><div class='ten-pixel-break'/>")
|
||||
.appendTo($('#testSuite'));
|
||||
} else {
|
||||
$(testDoc)
|
||||
.html("<div class='row'><div class='col-xs-2 text-center'><i class='ion-checkmark-circled big-success-icon'></i></div><div class='col-xs-10 test-output test-vertical-center wrappable grayed-out-test-output'>" + test.text + "</div></div><div class='ten-pixel-break'/>")
|
||||
.html(
|
||||
"<div class='row'><div class='col-xs-2 text-center'><i class='ion-checkmark-circled big-success-icon'></i></div><div class='col-xs-10 test-output test-vertical-center wrappable grayed-out-test-output'>" +
|
||||
test.text + "</div></div><div class='ten-pixel-break'/>")
|
||||
.appendTo($('#testSuite'));
|
||||
}
|
||||
};
|
||||
@ -268,18 +283,21 @@ var runTests = function(err, data) {
|
||||
pushed = false;
|
||||
$('#testSuite').children().remove();
|
||||
if (err && userTests.length > 0) {
|
||||
userTests= [{text:"Program Execution Failure", err: "No user tests were run."}];
|
||||
userTests = [{
|
||||
text: "Program Execution Failure",
|
||||
err: "No user tests were run."
|
||||
}];
|
||||
createTestDisplay();
|
||||
} else if (userTests) {
|
||||
userTests.push(false);
|
||||
pushed = true;
|
||||
userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, __testArray){
|
||||
userTests.forEach(function(chaiTestFromJSON, indexOfTestArray,
|
||||
__testArray) {
|
||||
try {
|
||||
if (chaiTestFromJSON) {
|
||||
var output = eval(reassembleTest(chaiTestFromJSON, data));
|
||||
debugger;
|
||||
}
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
allTestsPassed = false;
|
||||
__testArray[indexOfTestArray].err = error.message;
|
||||
} finally {
|
||||
@ -299,12 +317,12 @@ var runTests = function(err, data) {
|
||||
|
||||
function showCompletion() {
|
||||
var time = Math.floor(Date.now()) - started;
|
||||
ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time +', Attempts: ' + attempts);
|
||||
ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time +
|
||||
', Attempts: ' + attempts);
|
||||
var bonfireSolution = myCodeMirror.getValue();
|
||||
var didCompleteWith = $('#completed-with').val() || null;
|
||||
$.post(
|
||||
'/completed-bonfire/',
|
||||
{
|
||||
'/completed-bonfire/', {
|
||||
challengeInfo: {
|
||||
challengeId: challenge_Id,
|
||||
challengeName: challenge_Name,
|
||||
@ -312,10 +330,11 @@ function showCompletion() {
|
||||
challengeType: challengeType,
|
||||
solution: bonfireSolution
|
||||
}
|
||||
}, function(res) {
|
||||
},
|
||||
function(res) {
|
||||
if (res) {
|
||||
$('#complete-courseware-dialog').modal('show');
|
||||
$('#complete-courseware-dialog').keydown(function (e) {
|
||||
$('#complete-courseware-dialog').keydown(function(e) {
|
||||
if (e.ctrlKey && e.keyCode == 13) {
|
||||
$('#next-courseware-button').click();
|
||||
}
|
||||
|
@ -180,7 +180,8 @@
|
||||
"assert.deepEqual(palindrome(\"not a palindrome\"), false);",
|
||||
"assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);",
|
||||
"assert.deepEqual(palindrome(\"never odd or even\"), true);",
|
||||
"assert.deepEqual(palindrome(\"nope\"), false);"
|
||||
"assert.deepEqual(palindrome(\"nope\"), false);",
|
||||
"assert.deepEqual(palindrome(\"almostomla\"), false);"
|
||||
],
|
||||
"challengeSeed": [
|
||||
"function palindrome(str) {",
|
||||
@ -754,8 +755,8 @@
|
||||
},
|
||||
{
|
||||
"id": "a5de63ebea8dbee56860f4f2",
|
||||
"name": "bonfire-diff-two-arrays",
|
||||
"dashedName": "Bonfire: Diff Two Arrays",
|
||||
"name": "Bonfire: Diff Two Arrays",
|
||||
"dashedName": "bonfire-diff-two-arrays",
|
||||
"difficulty": "2.01",
|
||||
"description": [
|
||||
"Compare two arrays and return a new array with any items not found in both of the original arrays.",
|
||||
@ -1105,6 +1106,10 @@
|
||||
],
|
||||
"tests": [
|
||||
"assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');",
|
||||
"assert.strictEqual(convert('Hamburgers < Pizza < Tacos'), 'Hamburgers < Pizza < Tacos', 'should escape characters');",
|
||||
"assert.strictEqual(convert('Sixty > twelve'), 'Sixty > twelve', 'should escape characters');",
|
||||
"assert.strictEqual(convert('Stuff in \"quotation marks\"'), 'Stuff in "quotation marks"', 'should escape characters');",
|
||||
"assert.strictEqual(convert(\"Shindler's List\"), 'Shindler's List', 'should escape characters');",
|
||||
"assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');"
|
||||
],
|
||||
"MDNlinks": [
|
||||
|
@ -1005,7 +1005,7 @@
|
||||
],
|
||||
"tests": [
|
||||
"assert((/cat photos/gi).test($('a').text()), 'Your <code>a</code> element should have the anchor text of \"cat photos\"')",
|
||||
"assert($('a').filter(function(index) { return /com/gi.test($('a').attr('href')); }).length > 0, 'You need an <code>a</code> element that links to <code>http://catphotoapp.com<code>.')",
|
||||
"assert(/http:\\/\\/catphotoapp\\.com/gi.test($('a').attr('href')), 'You need an <code>a</code> element that links to <code>http://catphotoapp.com<code>.')",
|
||||
"assert(editor.match(/<\\/a>/g) && editor.match(/<\\/a>/g).length === editor.match(/<a/g).length, 'Make sure your <code>a</code> element has a closing tag.')"
|
||||
],
|
||||
"challengeSeed": [
|
||||
|
@ -626,7 +626,7 @@
|
||||
"The \"row\" class is applied to a <code>div</code>, and the buttons themselves can be wrapped within it."
|
||||
],
|
||||
"tests": [
|
||||
"assert($('div.row:has(button)'), 'Your buttons should all be wrapped within the same <code>div</code> element with the class \"row\".')",
|
||||
"assert($('div.row:has(button)').length > 0, 'Your buttons should all be wrapped within the same <code>div</code> element with the class \"row\".')",
|
||||
"assert($('div.col-xs-4:has(button)').length > 2, 'Each of your Bootstrap buttons should be wrapped within its own a <code>div</code> element with the class \"col-xs-4\".')",
|
||||
"assert(editor.match(/<\\/button>/g) && editor.match(/<button/g) && editor.match(/<\\/button>/g).length === editor.match(/<button/g).length, 'Make sure each of your <code>button</code> elements has a closing tag.')",
|
||||
"assert(editor.match(/<\\/div>/g) && editor.match(/<div/g) && editor.match(/<\\/div>/g).length === editor.match(/<div/g).length, 'Make sure each of your <code>div</code> elements has a closing tag.')"
|
||||
|
@ -56,7 +56,7 @@
|
||||
"<span class='text-info'>Hint:</span> Here's an example call to Twitch.tv's JSON API: <code>https://api.twitch.tv/kraken/streams/freecodecamp</code>.",
|
||||
"<span class='text-info'>Hint:</span> The relevant documentation about this API call is here: <a href='https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel' target='_blank'>https://github.com/justintv/Twitch-API/blob/master/v3_resources/streams.md#get-streamschannel</a>.",
|
||||
"<span class='text-info'>Hint:</span> Here's an array of the Twitch.tv usernames of people who regularly stream coding: <code>[\"freecodecamp\", \"storbeck\", \"terakilobyte\", \"habathcx\",\"RobotCaleb\",\"comster404\",\"brunofin\",\"thomasballinger\",\"noobs2ninjas\",\"beohoff\"]</code>",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.each/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.getjson/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
],
|
||||
@ -87,7 +87,7 @@
|
||||
"Here are the <a href='http://en.wikipedia.org/wiki/User_story' target='_blank'>user stories</a> you must enable, and optional bonus user stories:",
|
||||
"<span class='text-info'>User Story:</span> As a user, I can click a button to show me a new random quote.",
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I can press a button to tweet out a quote.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.each/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.getjson/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
],
|
||||
@ -120,7 +120,7 @@
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I can see an icon depending on the temperature..",
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I see a different background image depending on the temperature (e.g. snowy mountain, hot desert).",
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I can push a button to toggle between Fahrenheit and Celsius.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.each/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.getjson/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
],
|
||||
@ -154,7 +154,7 @@
|
||||
"<span class='text-info'>User Story:</span> As a user, I can click a link to go directly to the post's discussion page.",
|
||||
"<span class='text-info'>Bonus User Story:</span> As a user, I can see how many upvotes each story has.",
|
||||
"<span class='text-info'>Hint:</span> Here's the Camper News Hot Stories API endpoint: <code>http://www.freecodecamp.com/stories/hotStories</code>.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.each/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.getjson/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
],
|
||||
@ -187,7 +187,7 @@
|
||||
"<span class='text-info'>Bonus User Story:</span>As a user, I can click a button to see a random Wikipedia entry.",
|
||||
"<span class='text-info'>Bonus User Story:</span>As a user, when I type in the search box, I can see a dropdown menu with autocomplete options for matching Wikipedia entries.",
|
||||
"<span class='text-info'>Hint:</span> Here's an entry on using Wikipedia's API: <code>http://www.mediawiki.org/wiki/API:Main_page</code>.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.each/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"Remember to use <a href='/field-guide/how-do-i-get-help-when-I-get-stuck' target='_blank'>RSAP</a> if you get stuck. Try using <a href='http://api.jquery.com/jquery.getjson/'>jQuery's $.getJSON()</a> to consume APIs.",
|
||||
"When you are finished, click the \"I've completed this challenge\" button and include a link to your CodePen. If you pair programmed, you should also include the Free Code Camp username of your pair.",
|
||||
"If you'd like immediate feedback on your project, click this button and paste in a link to your CodePen project. Otherwise, we'll review it before you start your nonprofit projects.<br><br><a class='btn btn-primary btn-block' href='https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20%0A%20%23LearnToCode%20%23JavaScript' target='_blank'>Click here then add your link to your tweet's text</a>"
|
||||
],
|
||||
|
@ -32,50 +32,30 @@
|
||||
|
||||
var R = require('ramda'),
|
||||
utils = require('../utils'),
|
||||
userMigration = require('../utils/middleware').userMigration,
|
||||
MDNlinks = require('../../seed/bonfireMDNlinks');
|
||||
userMigration = require('../utils/middleware').userMigration;
|
||||
|
||||
var challengeMapWithNames = utils.getChallengeMapWithNames();
|
||||
var challengeMapWithIds = utils.getChallengeMapWithIds();
|
||||
var challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
|
||||
|
||||
|
||||
function getMDNlinks(links) {
|
||||
// takes in an array of links, which are strings
|
||||
var populatedLinks = [];
|
||||
|
||||
// for each key value, push the corresponding link
|
||||
// from the MDNlinks object into a new array
|
||||
if (links) {
|
||||
links.forEach(function (value) {
|
||||
populatedLinks.push(MDNlinks[value]);
|
||||
});
|
||||
}
|
||||
return populatedLinks;
|
||||
}
|
||||
var getMDNLinks = utils.getMDNLinks;
|
||||
|
||||
module.exports = function(app) {
|
||||
var router = app.loopback.Router();
|
||||
var Challenge = app.models.Challenge;
|
||||
var User = app.models.User;
|
||||
|
||||
router.get(
|
||||
'/challenges/next-challenge',
|
||||
userMigration,
|
||||
returnNextChallenge
|
||||
);
|
||||
|
||||
router.get(
|
||||
'/challenges/:challengeName',
|
||||
userMigration,
|
||||
returnIndividualChallenge
|
||||
);
|
||||
|
||||
router.get('/challenges/', userMigration, returnCurrentChallenge);
|
||||
router.post('/completed-challenge/', completedChallenge);
|
||||
router.post('/completed-zipline-or-basejump', completedZiplineOrBasejump);
|
||||
router.post('/completed-bonfire', completedBonfire);
|
||||
|
||||
// the follow routes are covered by userMigration
|
||||
router.use(userMigration);
|
||||
router.get('/challenges/next-challenge', returnNextChallenge);
|
||||
router.get('/challenges/:challengeName', returnIndividualChallenge);
|
||||
router.get('/challenges/', returnCurrentChallenge);
|
||||
router.get('/map', challengeMap);
|
||||
|
||||
app.use(router);
|
||||
|
||||
function returnNextChallenge(req, res, next) {
|
||||
@ -295,7 +275,7 @@ module.exports = function(app) {
|
||||
bonfires: challenge,
|
||||
challengeId: challenge.id,
|
||||
MDNkeys: challenge.MDNlinks,
|
||||
MDNlinks: getMDNlinks(challenge.MDNlinks),
|
||||
MDNlinks: getMDNLinks(challenge.MDNlinks),
|
||||
challengeType: challenge.challengeType
|
||||
});
|
||||
}
|
||||
@ -547,4 +527,51 @@ module.exports = function(app) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function challengeMap(req, res, next) {
|
||||
var completedList = [];
|
||||
|
||||
if (req.user) {
|
||||
completedList = req.user.completedChallenges;
|
||||
}
|
||||
|
||||
var noDuplicatedChallenges = R.uniq(completedList);
|
||||
|
||||
var completedChallengeList = noDuplicatedChallenges
|
||||
.map(function(challenge) {
|
||||
// backwards compatibility
|
||||
return (challenge.id || challenge._id);
|
||||
});
|
||||
var challengeList = utils.
|
||||
getChallengeMapForDisplay(completedChallengeList);
|
||||
|
||||
Object.keys(challengeList).forEach(function(key) {
|
||||
challengeList[key].completed = challengeList[key]
|
||||
.challenges.filter(function(elem) {
|
||||
// backwards compatibility hack
|
||||
return completedChallengeList.indexOf(elem.id || elem._id) > -1;
|
||||
});
|
||||
});
|
||||
|
||||
function numberWithCommas(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
}
|
||||
|
||||
var date1 = new Date('10/15/2014');
|
||||
var date2 = new Date();
|
||||
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
|
||||
var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
||||
|
||||
User.count(function(err, camperCount) {
|
||||
if (err) { return next(err); }
|
||||
|
||||
res.render('challengeMap/show', {
|
||||
daysRunning: daysRunning,
|
||||
camperCount: numberWithCommas(camperCount),
|
||||
title: "A map of all Free Code Camp's Challenges",
|
||||
challengeList: challengeList,
|
||||
completedChallengeList: completedChallengeList
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,66 +0,0 @@
|
||||
var R = require('ramda'),
|
||||
// debug = require('debug')('freecc:cntr:challengeMap'),
|
||||
utils = require('./../utils'),
|
||||
middleware = require('../utils/middleware');
|
||||
|
||||
|
||||
module.exports = function(app) {
|
||||
var User = app.models.User;
|
||||
var router = app.loopback.Router();
|
||||
|
||||
router.get('/map', middleware.userMigration, challengeMap);
|
||||
router.get('/learn-to-code', function(req, res) {
|
||||
res.redirect(301, '/map');
|
||||
});
|
||||
router.get('/about', function(req, res) {
|
||||
res.redirect(301, '/map');
|
||||
});
|
||||
|
||||
app.use(router);
|
||||
|
||||
function challengeMap(req, res, next) {
|
||||
var completedList = [];
|
||||
|
||||
if (req.user) {
|
||||
completedList = req.user.completedChallenges;
|
||||
}
|
||||
|
||||
var noDuplicatedChallenges = R.uniq(completedList);
|
||||
|
||||
var completedChallengeList = noDuplicatedChallenges
|
||||
.map(function(challenge) {
|
||||
return (challenge.id || challenge._id); // backwards compatibility
|
||||
});
|
||||
var challengeList = utils.
|
||||
getChallengeMapForDisplay(completedChallengeList);
|
||||
|
||||
Object.keys(challengeList).forEach(function(key) {
|
||||
challengeList[key].completed = challengeList[key]
|
||||
.challenges.filter(function(elem) {
|
||||
return completedChallengeList.indexOf(elem.id || elem._id) > -1;
|
||||
//backwards compatibility hack
|
||||
});
|
||||
});
|
||||
|
||||
function numberWithCommas(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
}
|
||||
|
||||
var date1 = new Date('10/15/2014');
|
||||
var date2 = new Date();
|
||||
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
|
||||
var daysRunning = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
||||
|
||||
User.count(function(err, camperCount) {
|
||||
if (err) { return next(err); }
|
||||
|
||||
res.render('challengeMap/show', {
|
||||
daysRunning: daysRunning,
|
||||
camperCount: numberWithCommas(camperCount),
|
||||
title: "A map of all Free Code Camp's Challenges",
|
||||
challengeList: challengeList,
|
||||
completedChallengeList: completedChallengeList
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
@ -18,5 +18,13 @@ module.exports = function(app) {
|
||||
);
|
||||
});
|
||||
|
||||
router.get('/learn-to-code', function(req, res) {
|
||||
res.redirect(301, '/map');
|
||||
});
|
||||
|
||||
router.get('/about', function(req, res) {
|
||||
res.redirect(301, '/map');
|
||||
});
|
||||
|
||||
app.use(router);
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ var secrets = require('../config/secrets');
|
||||
module.exports = {
|
||||
db: {
|
||||
connector: 'mongodb',
|
||||
connectionTimeout: 15000,
|
||||
url: process.env.MONGOHQ_URL
|
||||
},
|
||||
mail: {
|
||||
|
@ -41,7 +41,7 @@ module.exports = {
|
||||
},
|
||||
'google-login': {
|
||||
provider: 'google',
|
||||
authScheme: 'oauth2',
|
||||
authScheme: 'oauth',
|
||||
module: 'passport-google-oauth2',
|
||||
clientID: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
@ -55,7 +55,7 @@ module.exports = {
|
||||
},
|
||||
'google-link': {
|
||||
provider: 'google',
|
||||
authScheme: 'oauth2',
|
||||
authScheme: 'oauth',
|
||||
module: 'passport-google-oauth2',
|
||||
clientID: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
|
@ -1,5 +1,6 @@
|
||||
require('dotenv').load();
|
||||
require('pmx').init();
|
||||
var pmx = require('pmx');
|
||||
pmx.init();
|
||||
// handle uncaught exceptions. Forever will restart process on shutdown
|
||||
|
||||
var R = require('ramda'),
|
||||
@ -20,7 +21,6 @@ var R = require('ramda'),
|
||||
path = require('path'),
|
||||
expressValidator = require('express-validator'),
|
||||
lessMiddleware = require('less-middleware'),
|
||||
pmx = require('pmx'),
|
||||
|
||||
passportProviders = require('./passport-providers'),
|
||||
/**
|
||||
@ -42,12 +42,6 @@ app.set('port', process.env.PORT || 3000);
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
//if (process.env.NODE_ENV === 'production') {
|
||||
// app.use(forceDomain({
|
||||
// hostname: 'www.freecodecamp.com'
|
||||
// }));
|
||||
//}
|
||||
|
||||
app.use(compress());
|
||||
app.use(lessMiddleware(path.join(__dirname, '/public')));
|
||||
app.use(logger('dev'));
|
||||
@ -98,6 +92,8 @@ var trusted = [
|
||||
'https://freecodecamp.com',
|
||||
'https://freecodecamp.org',
|
||||
'*.freecodecamp.org',
|
||||
// NOTE(berks): add the following as the blob above was not covering www
|
||||
'http://www.freecodecamp.org',
|
||||
'ws://freecodecamp.com/',
|
||||
'ws://www.freecodecamp.com/',
|
||||
'*.gstatic.com',
|
||||
@ -143,7 +139,8 @@ app.use(helmet.csp({
|
||||
'*.aspnetcdn.com',
|
||||
'*.d3js.org',
|
||||
'https://cdn.inspectlet.com/inspectlet.js',
|
||||
'http://cdn.inspectlet.com/inspectlet.js'
|
||||
'http://cdn.inspectlet.com/inspectlet.js',
|
||||
'http://www.freecodecamp.org'
|
||||
].concat(trusted),
|
||||
'connect-src': [].concat(trusted),
|
||||
styleSrc: [
|
||||
@ -259,6 +256,8 @@ R.keys(passportProviders).map(function(strategy) {
|
||||
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
if (true) { // eslint-disable-line
|
||||
// NOTE(berks): adding pmx here for Beta test. Remove for production
|
||||
app.use(pmx.expressErrorHandler());
|
||||
app.use(errorHandler({
|
||||
log: true
|
||||
}));
|
||||
|
@ -7,6 +7,7 @@ var path = require('path'),
|
||||
fs = require('fs'),
|
||||
|
||||
|
||||
MDNlinks = require('../../seed/bonfireMDNlinks'),
|
||||
resources = require('./resources.json'),
|
||||
nonprofits = require('../../seed/nonprofits.json'),
|
||||
fieldGuides = require('../../seed/field-guides.json');
|
||||
@ -16,7 +17,7 @@ var path = require('path'),
|
||||
*/
|
||||
var allFieldGuideIds, allFieldGuideNames, allNonprofitNames,
|
||||
challengeMap, challengeMapForDisplay, challengeMapWithIds,
|
||||
challengeMapWithNames, allChallengeIds, allChallenges,
|
||||
challengeMapWithNames, allChallengeIds,
|
||||
challengeMapWithDashedNames;
|
||||
|
||||
/**
|
||||
@ -216,5 +217,18 @@ module.exports = {
|
||||
}
|
||||
});
|
||||
})();
|
||||
},
|
||||
|
||||
getMDNLinks: function(links) {
|
||||
if (!links) {
|
||||
return [];
|
||||
}
|
||||
// takes in an array of links, which are strings
|
||||
|
||||
// for each key value, push the corresponding link
|
||||
// from the MDNlinks object into a new array
|
||||
return links.map(function(value) {
|
||||
return MDNlinks[value];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
749
setup.js
749
setup.js
@ -1,749 +0,0 @@
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
var blessed = require('blessed');
|
||||
var multiline = require('multiline');
|
||||
|
||||
if (os.platform() === 'win32') {
|
||||
console.log('**************************************************************');
|
||||
console.log('Hackathon Starter Generator has been disabled on Windows until');
|
||||
console.log('https://github.com/chjj/blessed is fixed or until I find a');
|
||||
console.log('better CLI module.');
|
||||
console.log('**************************************************************');
|
||||
process.exit();
|
||||
}
|
||||
var screen = blessed.screen({
|
||||
autoPadding: true
|
||||
});
|
||||
|
||||
screen.key('q', function() {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
var home = blessed.list({
|
||||
parent: screen,
|
||||
padding: { top: 2 },
|
||||
mouse: true,
|
||||
keys: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
selectedFg: 'blue',
|
||||
selectedBg: 'white',
|
||||
items: [
|
||||
'» REMOVE AUTHENTICATION PROVIDER',
|
||||
'» CHANGE EMAIL SERVICE',
|
||||
'» ADD NODE.JS CLUSTER SUPPORT',
|
||||
'» EXIT'
|
||||
]
|
||||
});
|
||||
|
||||
var homeTitle = blessed.text({
|
||||
parent: screen,
|
||||
align: 'center',
|
||||
fg: 'blue',
|
||||
bg: 'white',
|
||||
content: 'Hackathon Starter (c) 2014'
|
||||
});
|
||||
|
||||
var footer = blessed.text({
|
||||
parent: screen,
|
||||
bottom: 0,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
tags: true,
|
||||
content: ' {cyan-fg}<Up/Down>{/cyan-fg} moves |' +
|
||||
' {cyan-fg}<Enter>{/cyan-fg} selects | {cyan-fg}<q>{/cyan-fg} exits'
|
||||
});
|
||||
|
||||
var inner = blessed.form({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
mouse: true,
|
||||
keys: true,
|
||||
width: 33,
|
||||
height: 10,
|
||||
border: {
|
||||
type: 'line',
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
},
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
});
|
||||
|
||||
var success = blessed.box({
|
||||
top: 'center',
|
||||
left: 'center',
|
||||
mouse: true,
|
||||
keys: true,
|
||||
tags: true,
|
||||
width: '50%',
|
||||
height: '40%',
|
||||
border: {
|
||||
type: 'line',
|
||||
fg: 'white',
|
||||
bg: 'green'
|
||||
},
|
||||
fg: 'white',
|
||||
bg: 'green',
|
||||
padding: 1
|
||||
});
|
||||
|
||||
success.on('keypress', function() {
|
||||
home.focus();
|
||||
home.remove(success);
|
||||
});
|
||||
|
||||
var clusterText = blessed.text({
|
||||
top: 'top',
|
||||
bg: 'red',
|
||||
fg: 'white',
|
||||
tags: true,
|
||||
content: 'Take advantage of multi-core systems' +
|
||||
' using built-in {underline}cluster{/underline} module.'
|
||||
});
|
||||
|
||||
|
||||
var enable = blessed.button({
|
||||
parent: inner,
|
||||
bottom: 0,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'enable',
|
||||
content: ' ENABLE ',
|
||||
border: {
|
||||
type: 'line',
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'red',
|
||||
focus: {
|
||||
fg: 'red',
|
||||
bg: 'white'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var disable = blessed.button({
|
||||
parent: inner,
|
||||
bottom: 0,
|
||||
left: 10,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'disable',
|
||||
content: ' DISABLE ',
|
||||
border: {
|
||||
type: 'line',
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'red',
|
||||
focus: {
|
||||
fg: 'red',
|
||||
bg: 'white'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var cancel = blessed.button({
|
||||
parent: inner,
|
||||
bottom: 0,
|
||||
left: 21,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'cancel',
|
||||
content: ' CANCEL ',
|
||||
border: {
|
||||
type: 'line',
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
},
|
||||
style: {
|
||||
fg: 'white',
|
||||
bg: 'red',
|
||||
focus: {
|
||||
fg: 'red',
|
||||
bg: 'white'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cancel.on('press', function() {
|
||||
home.focus();
|
||||
home.remove(inner);
|
||||
screen.render();
|
||||
|
||||
});
|
||||
|
||||
var authForm = blessed.form({
|
||||
mouse: true,
|
||||
keys: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
padding: { left: 1, right: 1 }
|
||||
});
|
||||
|
||||
authForm.on('submit', function() {
|
||||
var passportConfig = fs.readFileSync('config/passport.js')
|
||||
.toString().split(os.EOL);
|
||||
var loginTemplate = fs.readFileSync('views/account/login.jade')
|
||||
.toString().split(os.EOL);
|
||||
var profileTemplate = fs.readFileSync('views/account/profile.jade')
|
||||
.toString().split(os.EOL);
|
||||
var userModel = fs.readFileSync('models/User.js').toString().split(os.EOL);
|
||||
var app = fs.readFileSync('app.js').toString().split(os.EOL);
|
||||
var secrets = fs.readFileSync('config/secrets.js').toString().split(os.EOL);
|
||||
|
||||
var index = passportConfig
|
||||
.indexOf('var FacebookStrategy = require("passport-facebook").Strategy;');
|
||||
if (facebookCheckbox.checked && index !== -1) {
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with Facebook.');
|
||||
passportConfig.splice(index, 47);
|
||||
fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
' a.btn.btn-block.btn-facebook.btn-social(href="/auth/facebook")'
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
|
||||
|
||||
index = profileTemplate.indexOf(' if user.facebook');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade',
|
||||
profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = userModel.indexOf(' facebook: String,');
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
|
||||
index = app.indexOf([
|
||||
'app.get("/auth/facebook"',
|
||||
'passport.authenticate("facebook",',
|
||||
' { scope: ["email", "user_location"] }));'
|
||||
].join(' '));
|
||||
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
}
|
||||
|
||||
index = passportConfig.indexOf(
|
||||
"var GitHubStrategy = require('passport-github').Strategy;"
|
||||
);
|
||||
if (githubCheckbox.checked && index !== -1) {
|
||||
console.log(index);
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with GitHub.');
|
||||
passportConfig.splice(index, 48);
|
||||
fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
" a.btn.btn-block.btn-github.btn-social(href='/auth/github')"
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
|
||||
|
||||
index = profileTemplate.indexOf(' if user.github');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade',
|
||||
profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = userModel.indexOf(' github: String,');
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
|
||||
index = app.indexOf(
|
||||
'app.get("/auth/github", passport.authenticate("github"));'
|
||||
);
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
}
|
||||
|
||||
index = passportConfig.indexOf(
|
||||
'var GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;'
|
||||
);
|
||||
if (googleCheckbox.checked && index !== -1) {
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with Google.');
|
||||
passportConfig.splice(index, 46);
|
||||
fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
" a.btn.btn-block.btn-google-plus.btn-social(href='/auth/google')"
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
|
||||
|
||||
index = profileTemplate.indexOf(' if user.google');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade',
|
||||
profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = userModel.indexOf(' google: String,');
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
|
||||
index = app.indexOf(
|
||||
'app.get("/auth/google",' +
|
||||
' passport.authenticate("google", { scope: "profile email" }));'
|
||||
);
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
}
|
||||
|
||||
index = passportConfig.indexOf(
|
||||
'var TwitterStrategy = require("passport-twitter").Strategy;'
|
||||
);
|
||||
if (twitterCheckbox.checked && index !== -1) {
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with Twitter.');
|
||||
passportConfig.splice(index, 43);
|
||||
fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
' a.btn.btn-block.btn-twitter.btn-social(href="/auth/twitter")'
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
|
||||
|
||||
index = profileTemplate.indexOf(' if user.twitter');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade', profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = userModel.indexOf(' twitter: String,');
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
|
||||
index = app.indexOf(
|
||||
"app.get('/auth/twitter', passport.authenticate('twitter'));"
|
||||
);
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
}
|
||||
|
||||
index = passportConfig.indexOf(
|
||||
'var LinkedInStrategy = require("passport-linkedin-oauth2").Strategy;'
|
||||
);
|
||||
if (linkedinCheckbox.checked && index !== -1) {
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with LinkedIn.');
|
||||
passportConfig.splice(index, 47);
|
||||
fs.writeFileSync('config/passport.js', passportConfig.join(os.EOL));
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
' a.btn.btn-block.btn-linkedin.btn-social(href="/auth/linkedin")'
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
fs.writeFileSync('views/account/login.jade', loginTemplate.join(os.EOL));
|
||||
|
||||
index = profileTemplate.indexOf(' if user.linkedin');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade',
|
||||
profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = userModel.indexOf(' linkedin: String,');
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
|
||||
index = app.indexOf(
|
||||
'app.get("/auth/linkedin",',
|
||||
' passport.authenticate("linkedin", { state: "SOME STATE" }));'
|
||||
);
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
}
|
||||
|
||||
index = passportConfig.indexOf(
|
||||
'var InstagramStrategy = require("passport-instagram").Strategy;'
|
||||
);
|
||||
if (instagramCheckbox.checked && index !== -1) {
|
||||
passportConfig.splice(index, 1);
|
||||
index = passportConfig.indexOf('// Sign in with Instagram.');
|
||||
passportConfig.splice(index, 43);
|
||||
fs.writeFileSync(
|
||||
'config/passport.js',
|
||||
passportConfig.join(os.EOL)
|
||||
);
|
||||
|
||||
index = loginTemplate.indexOf(
|
||||
' a.btn.btn-block.btn-instagram.btn-social(href="/auth/instagram")'
|
||||
);
|
||||
loginTemplate.splice(index, 3);
|
||||
|
||||
fs.writeFileSync(
|
||||
'views/account/login.jade',
|
||||
loginTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = profileTemplate.indexOf(' if user.instagram');
|
||||
profileTemplate.splice(index - 1, 5);
|
||||
fs.writeFileSync(
|
||||
'views/account/profile.jade',
|
||||
profileTemplate.join(os.EOL)
|
||||
);
|
||||
|
||||
index = app.indexOf(
|
||||
'app.get("/auth/instagram", passport.authenticate("instagram"));'
|
||||
);
|
||||
app.splice(index, 4);
|
||||
fs.writeFileSync('app.js', app.join(os.EOL));
|
||||
|
||||
userModel.splice(index, 1);
|
||||
fs.writeFileSync('models/User.js', userModel.join(os.EOL));
|
||||
}
|
||||
|
||||
home.remove(authForm);
|
||||
home.append(success);
|
||||
success.setContent(
|
||||
'Selected authentication providers have been removed' +
|
||||
'from passportConfig.js, User.js, server.js, login.jade and profile.jade!'
|
||||
);
|
||||
success.focus();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
var authText = blessed.text({
|
||||
parent: authForm,
|
||||
content: 'Selecting a checkbox removes an authentication provider.' +
|
||||
' If authentication provider is already removed, no action will be taken.',
|
||||
padding: 1,
|
||||
bg: 'magenta',
|
||||
fg: 'white'
|
||||
});
|
||||
|
||||
var facebookCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 6,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Facebook'
|
||||
});
|
||||
|
||||
var githubCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 7,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'GitHub'
|
||||
});
|
||||
|
||||
var googleCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 8,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Google'
|
||||
});
|
||||
|
||||
var twitterCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 9,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Twitter'
|
||||
});
|
||||
|
||||
var linkedinCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 10,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'LinkedIn'
|
||||
});
|
||||
|
||||
var instagramCheckbox = blessed.checkbox({
|
||||
parent: authForm,
|
||||
top: 11,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Instagram'
|
||||
});
|
||||
|
||||
var authSubmit = blessed.button({
|
||||
parent: authForm,
|
||||
top: 13,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'submit',
|
||||
content: ' SUBMIT ',
|
||||
style: {
|
||||
fg: 'blue',
|
||||
bg: 'white',
|
||||
focus: {
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
authSubmit.on('press', function() {
|
||||
authForm.submit();
|
||||
});
|
||||
|
||||
var authCancel = blessed.button({
|
||||
parent: authForm,
|
||||
top: 13,
|
||||
left: 9,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'cancel',
|
||||
content: ' CANCEL ',
|
||||
style: {
|
||||
fg: 'blue',
|
||||
bg: 'white',
|
||||
focus: {
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
authCancel.on('press', function() {
|
||||
home.focus();
|
||||
home.remove(authForm);
|
||||
screen.render();
|
||||
});
|
||||
|
||||
var emailForm = blessed.form({
|
||||
mouse: true,
|
||||
keys: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
padding: { left: 1, right: 1 }
|
||||
});
|
||||
|
||||
emailForm.on('submit', function() {
|
||||
var contactCtrl = fs.readFileSync('controllers/contact.js')
|
||||
.toString().split(os.EOL);
|
||||
var userCtrl = fs.readFileSync('controllers/user.js')
|
||||
.toString().split(os.EOL);
|
||||
var choice = null;
|
||||
|
||||
if (sendgridRadio.checked) {
|
||||
choice = 'SendGrid';
|
||||
} else if (mailgunRadio.checked) {
|
||||
choice = 'Mailgun';
|
||||
} else if (mandrillRadio.checked) {
|
||||
choice = 'Mandrill';
|
||||
}
|
||||
|
||||
var index = contactCtrl.indexOf(
|
||||
'var transporter = nodemailer.createTransport({'
|
||||
);
|
||||
contactCtrl.splice(index + 1, 1, " service: '" + choice + "',");
|
||||
contactCtrl.splice(
|
||||
index + 3,
|
||||
1,
|
||||
' user: secrets.' + choice.toLowerCase() + '.user,'
|
||||
);
|
||||
contactCtrl.splice(
|
||||
index + 4,
|
||||
1,
|
||||
' pass: secrets.' + choice.toLowerCase() + '.password'
|
||||
);
|
||||
fs.writeFileSync('controllers/contact.js', contactCtrl.join(os.EOL));
|
||||
|
||||
index = userCtrl.indexOf(
|
||||
' var transporter = nodemailer.createTransport({'
|
||||
);
|
||||
userCtrl.splice(index + 1, 1, " service: '" + choice + "',");
|
||||
userCtrl.splice(
|
||||
index + 3,
|
||||
1,
|
||||
' user: secrets.' + choice.toLowerCase() + '.user,'
|
||||
);
|
||||
userCtrl.splice(
|
||||
index + 4,
|
||||
1,
|
||||
' pass: secrets.' + choice.toLowerCase() + '.password'
|
||||
);
|
||||
|
||||
index = userCtrl.indexOf(
|
||||
' var transporter = nodemailer.createTransport({',
|
||||
(index + 1)
|
||||
);
|
||||
userCtrl.splice(
|
||||
index + 1,
|
||||
1,
|
||||
' service: "' + choice + '",'
|
||||
);
|
||||
|
||||
userCtrl.splice(
|
||||
index + 3,
|
||||
1,
|
||||
' user: secrets.' + choice.toLowerCase() + '.user,'
|
||||
);
|
||||
userCtrl.splice(
|
||||
index + 4,
|
||||
1,
|
||||
' pass: secrets.' + choice.toLowerCase() + '.password'
|
||||
);
|
||||
fs.writeFileSync('controllers/user.js', userCtrl.join(os.EOL));
|
||||
|
||||
home.remove(emailForm);
|
||||
home.append(success);
|
||||
success.setContent('Email Service has been switched to ' + choice);
|
||||
success.focus();
|
||||
screen.render();
|
||||
});
|
||||
|
||||
var emailText = blessed.text({
|
||||
parent: emailForm,
|
||||
content: 'Select one of the following email service providers ' +
|
||||
'for {underline}contact form{/underline}' +
|
||||
' and {underline}password reset{/underline}.',
|
||||
padding: 1,
|
||||
bg: 'red',
|
||||
fg: 'white',
|
||||
tags: true
|
||||
});
|
||||
|
||||
var sendgridRadio = blessed.radiobutton({
|
||||
parent: emailForm,
|
||||
top: 5,
|
||||
checked: true,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'SendGrid'
|
||||
});
|
||||
|
||||
var mailgunRadio = blessed.radiobutton({
|
||||
parent: emailForm,
|
||||
top: 6,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Mailgun'
|
||||
});
|
||||
|
||||
var mandrillRadio = blessed.radiobutton({
|
||||
parent: emailForm,
|
||||
top: 7,
|
||||
mouse: true,
|
||||
fg: 'white',
|
||||
bg: 'blue',
|
||||
content: 'Mandrill'
|
||||
});
|
||||
|
||||
var emailSubmit = blessed.button({
|
||||
parent: emailForm,
|
||||
top: 9,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'submit',
|
||||
content: ' SUBMIT ',
|
||||
style: {
|
||||
fg: 'blue',
|
||||
bg: 'white',
|
||||
focus: {
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
emailSubmit.on('press', function() {
|
||||
emailForm.submit();
|
||||
});
|
||||
|
||||
var emailCancel = blessed.button({
|
||||
parent: emailForm,
|
||||
top: 9,
|
||||
left: 9,
|
||||
mouse: true,
|
||||
shrink: true,
|
||||
name: 'cancel',
|
||||
content: ' CANCEL ',
|
||||
style: {
|
||||
fg: 'blue',
|
||||
bg: 'white',
|
||||
focus: {
|
||||
fg: 'white',
|
||||
bg: 'red'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
emailCancel.on('press', function() {
|
||||
home.focus();
|
||||
home.remove(emailForm);
|
||||
screen.render();
|
||||
|
||||
});
|
||||
|
||||
home.on('select', function(child, index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
home.append(authForm);
|
||||
authForm.focus();
|
||||
screen.render();
|
||||
break;
|
||||
case 1:
|
||||
home.append(emailForm);
|
||||
emailForm.focus();
|
||||
break;
|
||||
case 2:
|
||||
addClusterSupport();
|
||||
home.append(success);
|
||||
success.setContent([
|
||||
'New file {underline}cluster_app.js{/underline} has been created.',
|
||||
'Your app is now able to use more than 1 CPU by running',
|
||||
'{underline}node cluster_app.js{/underline}, which in turn',
|
||||
'spawns multiple instances of {underline}server.js{/underline}'
|
||||
].join(' '));
|
||||
success.focus();
|
||||
screen.render();
|
||||
break;
|
||||
default:
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
|
||||
screen.render();
|
||||
|
||||
|
||||
function addClusterSupport() {
|
||||
|
||||
var fileContents = multiline(function() {
|
||||
/*
|
||||
var os = require('os');
|
||||
var cluster = require('cluster');
|
||||
|
||||
cluster.setupMaster({
|
||||
exec: 'server.js'
|
||||
});
|
||||
|
||||
cluster.on('exit', function(worker) {
|
||||
console.log('worker ' + worker.id + ' died');
|
||||
cluster.fork();
|
||||
});
|
||||
|
||||
for (var i = 0; i < os.cpus().length; i++) {
|
||||
cluster.fork();
|
||||
}
|
||||
*/
|
||||
});
|
||||
|
||||
fs.writeFileSync('cluster_app.js', fileContents);
|
||||
}
|
Reference in New Issue
Block a user