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-session": "~1.9.2",
|
||||||
"express-validator": "~2.8.0",
|
"express-validator": "~2.8.0",
|
||||||
"font-awesome": "~4.3.0",
|
"font-awesome": "~4.3.0",
|
||||||
"forcedomain": "~0.4.0",
|
|
||||||
"forever": "~0.14.1",
|
"forever": "~0.14.1",
|
||||||
"frameguard": "^0.2.2",
|
"frameguard": "^0.2.2",
|
||||||
"github-api": "~0.7.0",
|
"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
|
// Hijack tab key to enter two spaces intead
|
||||||
editor.setOption("extraKeys", {
|
editor.setOption("extraKeys", {
|
||||||
Tab: function(cm) {
|
Tab: function(cm) {
|
||||||
if (cm.somethingSelected()){
|
if (cm.somethingSelected()) {
|
||||||
cm.indentSelection("add");
|
cm.indentSelection("add");
|
||||||
} else {
|
} else {
|
||||||
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
||||||
@ -26,7 +26,7 @@ editor.setOption("extraKeys", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Shift-Tab": function(cm) {
|
"Shift-Tab": function(cm) {
|
||||||
if (cm.somethingSelected()){
|
if (cm.somethingSelected()) {
|
||||||
cm.indentSelection("subtract");
|
cm.indentSelection("subtract");
|
||||||
} else {
|
} else {
|
||||||
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
|
||||||
@ -121,7 +121,10 @@ codeOutput.setValue('/**\n' +
|
|||||||
' */');
|
' */');
|
||||||
codeOutput.setSize("100%", "100%");
|
codeOutput.setSize("100%", "100%");
|
||||||
var info = editor.getScrollInfo();
|
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)
|
if (info.top + info.clientHeight < after)
|
||||||
editor.scrollTo(null, after - info.clientHeight + 3);
|
editor.scrollTo(null, after - info.clientHeight + 3);
|
||||||
|
|
||||||
@ -143,8 +146,8 @@ editorValue = (localBonfire.isAlive())? localBonfire.getEditorValue() : allSeeds
|
|||||||
|
|
||||||
myCodeMirror.setValue(editorValue);
|
myCodeMirror.setValue(editorValue);
|
||||||
|
|
||||||
function doLinting () {
|
function doLinting() {
|
||||||
editor.operation(function () {
|
editor.operation(function() {
|
||||||
for (var i = 0; i < widgets.length; ++i)
|
for (var i = 0; i < widgets.length; ++i)
|
||||||
editor.removeLineWidget(widgets[i]);
|
editor.removeLineWidget(widgets[i]);
|
||||||
widgets.length = 0;
|
widgets.length = 0;
|
||||||
@ -166,14 +169,14 @@ function doLinting () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$('#submitButton').on('click', function () {
|
$('#submitButton').on('click', function() {
|
||||||
bonfireExecute();
|
bonfireExecute();
|
||||||
});
|
});
|
||||||
|
|
||||||
function bonfireExecute() {
|
function bonfireExecute() {
|
||||||
attempts++;
|
attempts++;
|
||||||
ga('send', 'event', 'Challenge', 'ran-code', challenge_Name);
|
ga('send', 'event', 'Challenge', 'ran-code', challenge_Name);
|
||||||
userTests= null;
|
userTests = null;
|
||||||
$('#codeOutput').empty();
|
$('#codeOutput').empty();
|
||||||
var userJavaScript = myCodeMirror.getValue();
|
var userJavaScript = myCodeMirror.getValue();
|
||||||
userJavaScript = removeComments(userJavaScript);
|
userJavaScript = removeComments(userJavaScript);
|
||||||
@ -205,16 +208,23 @@ var scrapeTests = function(userJavaScript) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var counter = 0;
|
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);
|
var match = regex.exec(userJavaScript);
|
||||||
while (match != null) {
|
while (match != null) {
|
||||||
var replacement = '//' + counter + testSalt;
|
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) {
|
if (!userTests) {
|
||||||
userTests= [];
|
userTests = [];
|
||||||
}
|
}
|
||||||
userTests.push({"text": match[0], "line": counter, "err": null});
|
userTests.push({
|
||||||
|
"text": match[0],
|
||||||
|
"line": counter,
|
||||||
|
"err": null
|
||||||
|
});
|
||||||
counter++;
|
counter++;
|
||||||
match = regex.exec(userJavaScript);
|
match = regex.exec(userJavaScript);
|
||||||
}
|
}
|
||||||
@ -236,17 +246,22 @@ var createTestDisplay = function() {
|
|||||||
if (pushed) {
|
if (pushed) {
|
||||||
userTests.pop();
|
userTests.pop();
|
||||||
}
|
}
|
||||||
for (var i = 0; i < userTests.length;i++) {
|
for (var i = 0; i < userTests.length; i++) {
|
||||||
var test = userTests[i];
|
var test = userTests[i];
|
||||||
var testDoc = document.createElement("div");
|
var testDoc = document.createElement("div");
|
||||||
if (test.err != null) {
|
if (test.err != null) {
|
||||||
console.log('Should be displaying bad tests');
|
console.log('Should be displaying bad tests');
|
||||||
$(testDoc)
|
$(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'));
|
.appendTo($('#testSuite'));
|
||||||
} else {
|
} else {
|
||||||
$(testDoc)
|
$(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'));
|
.appendTo($('#testSuite'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -268,18 +283,21 @@ var runTests = function(err, data) {
|
|||||||
pushed = false;
|
pushed = false;
|
||||||
$('#testSuite').children().remove();
|
$('#testSuite').children().remove();
|
||||||
if (err && userTests.length > 0) {
|
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();
|
createTestDisplay();
|
||||||
} else if (userTests) {
|
} else if (userTests) {
|
||||||
userTests.push(false);
|
userTests.push(false);
|
||||||
pushed = true;
|
pushed = true;
|
||||||
userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, __testArray){
|
userTests.forEach(function(chaiTestFromJSON, indexOfTestArray,
|
||||||
|
__testArray) {
|
||||||
try {
|
try {
|
||||||
if (chaiTestFromJSON) {
|
if (chaiTestFromJSON) {
|
||||||
var output = eval(reassembleTest(chaiTestFromJSON, data));
|
var output = eval(reassembleTest(chaiTestFromJSON, data));
|
||||||
debugger;
|
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch (error) {
|
||||||
allTestsPassed = false;
|
allTestsPassed = false;
|
||||||
__testArray[indexOfTestArray].err = error.message;
|
__testArray[indexOfTestArray].err = error.message;
|
||||||
} finally {
|
} finally {
|
||||||
@ -299,12 +317,12 @@ var runTests = function(err, data) {
|
|||||||
|
|
||||||
function showCompletion() {
|
function showCompletion() {
|
||||||
var time = Math.floor(Date.now()) - started;
|
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 bonfireSolution = myCodeMirror.getValue();
|
||||||
var didCompleteWith = $('#completed-with').val() || null;
|
var didCompleteWith = $('#completed-with').val() || null;
|
||||||
$.post(
|
$.post(
|
||||||
'/completed-bonfire/',
|
'/completed-bonfire/', {
|
||||||
{
|
|
||||||
challengeInfo: {
|
challengeInfo: {
|
||||||
challengeId: challenge_Id,
|
challengeId: challenge_Id,
|
||||||
challengeName: challenge_Name,
|
challengeName: challenge_Name,
|
||||||
@ -312,10 +330,11 @@ function showCompletion() {
|
|||||||
challengeType: challengeType,
|
challengeType: challengeType,
|
||||||
solution: bonfireSolution
|
solution: bonfireSolution
|
||||||
}
|
}
|
||||||
}, function(res) {
|
},
|
||||||
|
function(res) {
|
||||||
if (res) {
|
if (res) {
|
||||||
$('#complete-courseware-dialog').modal('show');
|
$('#complete-courseware-dialog').modal('show');
|
||||||
$('#complete-courseware-dialog').keydown(function (e) {
|
$('#complete-courseware-dialog').keydown(function(e) {
|
||||||
if (e.ctrlKey && e.keyCode == 13) {
|
if (e.ctrlKey && e.keyCode == 13) {
|
||||||
$('#next-courseware-button').click();
|
$('#next-courseware-button').click();
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,8 @@
|
|||||||
"assert.deepEqual(palindrome(\"not a palindrome\"), false);",
|
"assert.deepEqual(palindrome(\"not a palindrome\"), false);",
|
||||||
"assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);",
|
"assert.deepEqual(palindrome(\"A man, a plan, a canal. Panama\"), true);",
|
||||||
"assert.deepEqual(palindrome(\"never odd or even\"), 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": [
|
"challengeSeed": [
|
||||||
"function palindrome(str) {",
|
"function palindrome(str) {",
|
||||||
@ -754,8 +755,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "a5de63ebea8dbee56860f4f2",
|
"id": "a5de63ebea8dbee56860f4f2",
|
||||||
"name": "bonfire-diff-two-arrays",
|
"name": "Bonfire: Diff Two Arrays",
|
||||||
"dashedName": "Bonfire: Diff Two Arrays",
|
"dashedName": "bonfire-diff-two-arrays",
|
||||||
"difficulty": "2.01",
|
"difficulty": "2.01",
|
||||||
"description": [
|
"description": [
|
||||||
"Compare two arrays and return a new array with any items not found in both of the original arrays.",
|
"Compare two arrays and return a new array with any items not found in both of the original arrays.",
|
||||||
@ -1105,6 +1106,10 @@
|
|||||||
],
|
],
|
||||||
"tests": [
|
"tests": [
|
||||||
"assert.strictEqual(convert('Dolce & Gabbana'), 'Dolce & Gabbana', 'should escape characters');",
|
"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');"
|
"assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');"
|
||||||
],
|
],
|
||||||
"MDNlinks": [
|
"MDNlinks": [
|
||||||
|
@ -1005,7 +1005,7 @@
|
|||||||
],
|
],
|
||||||
"tests": [
|
"tests": [
|
||||||
"assert((/cat photos/gi).test($('a').text()), 'Your <code>a</code> element should have the anchor text of \"cat photos\"')",
|
"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.')"
|
"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": [
|
"challengeSeed": [
|
||||||
|
@ -626,7 +626,7 @@
|
|||||||
"The \"row\" class is applied to a <code>div</code>, and the buttons themselves can be wrapped within it."
|
"The \"row\" class is applied to a <code>div</code>, and the buttons themselves can be wrapped within it."
|
||||||
],
|
],
|
||||||
"tests": [
|
"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($('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(/<\\/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.')"
|
"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> 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> 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>",
|
"<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.",
|
"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>"
|
"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:",
|
"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'>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.",
|
"<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.",
|
"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>"
|
"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 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 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.",
|
"<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.",
|
"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>"
|
"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'>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'>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>.",
|
"<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.",
|
"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>"
|
"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, 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'>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>.",
|
"<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.",
|
"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>"
|
"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'),
|
var R = require('ramda'),
|
||||||
utils = require('../utils'),
|
utils = require('../utils'),
|
||||||
userMigration = require('../utils/middleware').userMigration,
|
userMigration = require('../utils/middleware').userMigration;
|
||||||
MDNlinks = require('../../seed/bonfireMDNlinks');
|
|
||||||
|
|
||||||
var challengeMapWithNames = utils.getChallengeMapWithNames();
|
var challengeMapWithNames = utils.getChallengeMapWithNames();
|
||||||
var challengeMapWithIds = utils.getChallengeMapWithIds();
|
var challengeMapWithIds = utils.getChallengeMapWithIds();
|
||||||
var challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
|
var challengeMapWithDashedNames = utils.getChallengeMapWithDashedNames();
|
||||||
|
|
||||||
|
var getMDNLinks = utils.getMDNLinks;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
var router = app.loopback.Router();
|
var router = app.loopback.Router();
|
||||||
var Challenge = app.models.Challenge;
|
var Challenge = app.models.Challenge;
|
||||||
var User = app.models.User;
|
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-challenge/', completedChallenge);
|
||||||
router.post('/completed-zipline-or-basejump', completedZiplineOrBasejump);
|
router.post('/completed-zipline-or-basejump', completedZiplineOrBasejump);
|
||||||
router.post('/completed-bonfire', completedBonfire);
|
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);
|
app.use(router);
|
||||||
|
|
||||||
function returnNextChallenge(req, res, next) {
|
function returnNextChallenge(req, res, next) {
|
||||||
@ -295,7 +275,7 @@ module.exports = function(app) {
|
|||||||
bonfires: challenge,
|
bonfires: challenge,
|
||||||
challengeId: challenge.id,
|
challengeId: challenge.id,
|
||||||
MDNkeys: challenge.MDNlinks,
|
MDNkeys: challenge.MDNlinks,
|
||||||
MDNlinks: getMDNlinks(challenge.MDNlinks),
|
MDNlinks: getMDNLinks(challenge.MDNlinks),
|
||||||
challengeType: challenge.challengeType
|
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);
|
app.use(router);
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@ var secrets = require('../config/secrets');
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
db: {
|
db: {
|
||||||
connector: 'mongodb',
|
connector: 'mongodb',
|
||||||
|
connectionTimeout: 15000,
|
||||||
url: process.env.MONGOHQ_URL
|
url: process.env.MONGOHQ_URL
|
||||||
},
|
},
|
||||||
mail: {
|
mail: {
|
||||||
|
@ -41,7 +41,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
'google-login': {
|
'google-login': {
|
||||||
provider: 'google',
|
provider: 'google',
|
||||||
authScheme: 'oauth2',
|
authScheme: 'oauth',
|
||||||
module: 'passport-google-oauth2',
|
module: 'passport-google-oauth2',
|
||||||
clientID: process.env.GOOGLE_ID,
|
clientID: process.env.GOOGLE_ID,
|
||||||
clientSecret: process.env.GOOGLE_SECRET,
|
clientSecret: process.env.GOOGLE_SECRET,
|
||||||
@ -55,7 +55,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
'google-link': {
|
'google-link': {
|
||||||
provider: 'google',
|
provider: 'google',
|
||||||
authScheme: 'oauth2',
|
authScheme: 'oauth',
|
||||||
module: 'passport-google-oauth2',
|
module: 'passport-google-oauth2',
|
||||||
clientID: process.env.GOOGLE_ID,
|
clientID: process.env.GOOGLE_ID,
|
||||||
clientSecret: process.env.GOOGLE_SECRET,
|
clientSecret: process.env.GOOGLE_SECRET,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
require('dotenv').load();
|
require('dotenv').load();
|
||||||
require('pmx').init();
|
var pmx = require('pmx');
|
||||||
|
pmx.init();
|
||||||
// handle uncaught exceptions. Forever will restart process on shutdown
|
// handle uncaught exceptions. Forever will restart process on shutdown
|
||||||
|
|
||||||
var R = require('ramda'),
|
var R = require('ramda'),
|
||||||
@ -20,7 +21,6 @@ var R = require('ramda'),
|
|||||||
path = require('path'),
|
path = require('path'),
|
||||||
expressValidator = require('express-validator'),
|
expressValidator = require('express-validator'),
|
||||||
lessMiddleware = require('less-middleware'),
|
lessMiddleware = require('less-middleware'),
|
||||||
pmx = require('pmx'),
|
|
||||||
|
|
||||||
passportProviders = require('./passport-providers'),
|
passportProviders = require('./passport-providers'),
|
||||||
/**
|
/**
|
||||||
@ -42,12 +42,6 @@ app.set('port', process.env.PORT || 3000);
|
|||||||
app.set('views', path.join(__dirname, 'views'));
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'jade');
|
app.set('view engine', 'jade');
|
||||||
|
|
||||||
//if (process.env.NODE_ENV === 'production') {
|
|
||||||
// app.use(forceDomain({
|
|
||||||
// hostname: 'www.freecodecamp.com'
|
|
||||||
// }));
|
|
||||||
//}
|
|
||||||
|
|
||||||
app.use(compress());
|
app.use(compress());
|
||||||
app.use(lessMiddleware(path.join(__dirname, '/public')));
|
app.use(lessMiddleware(path.join(__dirname, '/public')));
|
||||||
app.use(logger('dev'));
|
app.use(logger('dev'));
|
||||||
@ -98,6 +92,8 @@ var trusted = [
|
|||||||
'https://freecodecamp.com',
|
'https://freecodecamp.com',
|
||||||
'https://freecodecamp.org',
|
'https://freecodecamp.org',
|
||||||
'*.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://freecodecamp.com/',
|
||||||
'ws://www.freecodecamp.com/',
|
'ws://www.freecodecamp.com/',
|
||||||
'*.gstatic.com',
|
'*.gstatic.com',
|
||||||
@ -143,7 +139,8 @@ app.use(helmet.csp({
|
|||||||
'*.aspnetcdn.com',
|
'*.aspnetcdn.com',
|
||||||
'*.d3js.org',
|
'*.d3js.org',
|
||||||
'https://cdn.inspectlet.com/inspectlet.js',
|
'https://cdn.inspectlet.com/inspectlet.js',
|
||||||
'http://cdn.inspectlet.com/inspectlet.js'
|
'http://cdn.inspectlet.com/inspectlet.js',
|
||||||
|
'http://www.freecodecamp.org'
|
||||||
].concat(trusted),
|
].concat(trusted),
|
||||||
'connect-src': [].concat(trusted),
|
'connect-src': [].concat(trusted),
|
||||||
styleSrc: [
|
styleSrc: [
|
||||||
@ -259,6 +256,8 @@ R.keys(passportProviders).map(function(strategy) {
|
|||||||
|
|
||||||
// if (process.env.NODE_ENV === 'development') {
|
// if (process.env.NODE_ENV === 'development') {
|
||||||
if (true) { // eslint-disable-line
|
if (true) { // eslint-disable-line
|
||||||
|
// NOTE(berks): adding pmx here for Beta test. Remove for production
|
||||||
|
app.use(pmx.expressErrorHandler());
|
||||||
app.use(errorHandler({
|
app.use(errorHandler({
|
||||||
log: true
|
log: true
|
||||||
}));
|
}));
|
||||||
|
@ -7,6 +7,7 @@ var path = require('path'),
|
|||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
|
|
||||||
|
|
||||||
|
MDNlinks = require('../../seed/bonfireMDNlinks'),
|
||||||
resources = require('./resources.json'),
|
resources = require('./resources.json'),
|
||||||
nonprofits = require('../../seed/nonprofits.json'),
|
nonprofits = require('../../seed/nonprofits.json'),
|
||||||
fieldGuides = require('../../seed/field-guides.json');
|
fieldGuides = require('../../seed/field-guides.json');
|
||||||
@ -16,7 +17,7 @@ var path = require('path'),
|
|||||||
*/
|
*/
|
||||||
var allFieldGuideIds, allFieldGuideNames, allNonprofitNames,
|
var allFieldGuideIds, allFieldGuideNames, allNonprofitNames,
|
||||||
challengeMap, challengeMapForDisplay, challengeMapWithIds,
|
challengeMap, challengeMapForDisplay, challengeMapWithIds,
|
||||||
challengeMapWithNames, allChallengeIds, allChallenges,
|
challengeMapWithNames, allChallengeIds,
|
||||||
challengeMapWithDashedNames;
|
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