Merge branch 'staging' into jquery
Conflicts: seed/challenges/bootstrap.json seed/challenges/jquery.json
This commit is contained in:
@ -98,7 +98,6 @@ TWITTER_TOKEN=stuff
|
||||
TWITTER_TOKEN_SECRET=stuff
|
||||
|
||||
BLOGGER_KEY=stuff
|
||||
SLACK_WEBHOOK=stuff
|
||||
|
||||
SESSION_SECRET=secretstuff
|
||||
COOKIE_SECRET='this is a secret'
|
||||
|
@ -79,7 +79,7 @@ export default function(UserIdent) {
|
||||
}
|
||||
|
||||
// if user signed in with github refresh their info
|
||||
if (userIdent.provider === 'github-login') {
|
||||
if (/github/.test(userIdent.provider)) {
|
||||
debug("user isn't github cool or username from github is different");
|
||||
setProfileFromGithub(user, profile, profile._json);
|
||||
userChanged = true;
|
||||
|
@ -4,6 +4,10 @@
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index": {
|
||||
@ -22,6 +26,9 @@
|
||||
"order": {
|
||||
"type": "number"
|
||||
},
|
||||
"suborder": {
|
||||
"type": "number"
|
||||
},
|
||||
"dashedName": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -4,6 +4,10 @@
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"position": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -4,6 +4,10 @@
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index": {
|
||||
|
@ -4,6 +4,10 @@
|
||||
"idInjection": true,
|
||||
"trackChanges": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"index": {
|
||||
|
@ -1071,17 +1071,17 @@
|
||||
"title": "Create a JavaScript Slot Machine",
|
||||
"difficulty":"9.988",
|
||||
"description":[
|
||||
"We are now going to try and combine some of the stuff we've just learnt abd create the logic for a slot machine game",
|
||||
"We are now going to try and combine some of the stuff we've just learned and create the logic for a slot machine game",
|
||||
"For this we will need to generate three random numbers between <code>1</code> and <code>5</code> to represent the possible values of each individual slot",
|
||||
"Store the three random numbers in <code>slotOne</code>, <code>slotTwo</code> and <code>slotThree</code>",
|
||||
"Generate the random numbers by using the system we used earlier in /challenges/random-whole-numbers-in-a-range",
|
||||
"<code>Math.floor(Math.random() * (5 - 1 + 1)) + 1; </code>"
|
||||
],
|
||||
"tests":[
|
||||
"assert(typeof(runSlots($('.slot'))[0]) == 'number', 'SlotOne should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[1]) == 'number', 'SlotTwo should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[2]) == 'number', 'SlotThree should be a random number');",
|
||||
"assert((function(){if(editor.match(/Math.floor\\(Math\\.random\\(\\)\\s\\*\\s\\(5\\s\\-\\s1\\s\\+\\s1\\)\\)\\s\\+\\s1;/gi) !== null){return(editor.match(/Math.floor\\(Math\\.random\\(\\)\\s\\*\\s\\(5\\s\\-\\s1\\s\\+\\s1\\)\\)\\s\\+\\s1;/gi).length >= 3);}else{return(false);}})(), 'You should have used Math.floor(Math.random() * (5 - 1 + 1)) + 1; three times to generate your random numbers');"
|
||||
"assert(typeof(runSlots($('.slot'))[0]) == 'number', 'slotOne should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[1]) == 'number', 'slotTwo should be a random number');",
|
||||
"assert(typeof(runSlots($('.slot'))[2]) == 'number', 'slotThree should be a random number');",
|
||||
"assert((function(){if(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?5\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi) !== null){return(editor.match(/Math\\.floor\\(\\s?Math\\.random\\(\\)\\s?\\*\\s?\\(\\s?5\\s?\\-\\s?1\\s?\\+\\s?1\\s?\\)\\s?\\)\\s?\\+\\s?1;/gi).length >= 3);}else{return(false);}})(), 'You should have used Math.floor(Math.random() * (5 - 1 + 1)) + 1; three times to generate your random numbers');"
|
||||
],
|
||||
"challengeSeed":[
|
||||
"fccss",
|
||||
|
@ -16,9 +16,9 @@
|
||||
"Go to <a href='http://codepen.io' target='_blank'>http://codepen.io</a> and create an account.",
|
||||
"Click your user image in the top right corner, then click the \"New pen\" button that drops down.",
|
||||
"Drag the windows around and press the buttons in the lower-right hand corner to change the orientation to suit your preference.",
|
||||
"Click the gear next to CSS. Click the \"Quick-add...\" select box and choose Bootstrap.",
|
||||
"Click the gear next to CSS. Then under the \"Add External CSS\" section, use the \"Quick-add\" select box to select Bootstrap. Then click \"Save & Close\".",
|
||||
"Verify that bootstrap is active by adding the following code to your HTML: <code><h1 class='text-primary'>Hello CodePen!</h1></code>. The text's color should be Bootstrap blue.",
|
||||
"Click the gear next to JavaScript. Click the \"Quick-add...\" select box and choose jQuery.",
|
||||
"Click the gear next to JavaScript. Click the \"Quick-add\" select box and choose jQuery (not jQuery UI). Then click \"Save & Close\".",
|
||||
"Now add the following code to your JavaScript: <code>$(document).ready(function() { $('.text-primary').text('Hi CodePen!') });</code>. Click the \"Save\" button at the top. Your \"Hello CodePen!\" should change to \"Hi CodePen!\". This means that jQuery is working.",
|
||||
"You can use this CodePen that you've just created as a starting point for your Ziplines. Just click the \"fork\" button at the top of your CodePen and it will create a duplicate CodePen.",
|
||||
"Now you're ready for your first Zipline. Click the \"I've completed this challenge\" button."
|
||||
|
@ -91,7 +91,7 @@
|
||||
"title": "Make Images Mobile Responsive",
|
||||
"difficulty": 2.02,
|
||||
"description": [
|
||||
"First, Add a new image with the <code>src</code> attribute of \"http://bit.ly/fcc-running-cats\".",
|
||||
"First, Add a new image below the existing one. Set it's <code>src</code> attribute to \"http://bit.ly/fcc-running-cats\".",
|
||||
"It would be great if this image could be exactly the width of our phone's screen.",
|
||||
"Fortunately, with Bootstrap, all we need to do is add the \"img-responsive\" class to your image. Do this, and the image should perfectly fit the width of your page."
|
||||
],
|
||||
|
@ -459,8 +459,17 @@
|
||||
"descriptionFr": [],
|
||||
"nameRu": "",
|
||||
"descriptionRu": [],
|
||||
"nameEs": "",
|
||||
"descriptionEs": [],
|
||||
"nameEs": "Waypoint: Utiliza una clase CSS para darle estilo a un elemento",
|
||||
"descriptionEs": [
|
||||
"Crea una clase CSS llamada \"red-text\" y aplicala a tu elemento <code>h2</code>.",
|
||||
"Las clases son estilos reutilizables que pueden ser añadidos a elementos HTML",
|
||||
"Esta es la anatomía de una clase CSS:",
|
||||
"<img class='img-responsive' alt='a diagram of how style tags are composed, which is also described in detail on the following lines.' src='https://www.evernote.com/l/AHSCzZV0l_dDLrqD8r9JsHaBWfEzdN0OpRwB/image.png'/>",
|
||||
"Puedes ver que hemos creado una clase CSS llamada \"blue-text\" dentro de la etiqueta <code><style></code>.",
|
||||
"Puedes aplicar una clase a un elemento HTML de esta manera: <code><h2 class=\"blue-text\">CatPhotoApp</h2></code>.",
|
||||
"Nota que en el elemento CSS <code>style</code>, las clases deberían comenzar con un punto. En los elementos HTML, las declaraciones de clase, NO deberían comenzar con punto. ",
|
||||
"En vez de de crear un nuevo elemento <code>style</code>, prueba remover la declaración de estilo de <code>h2</code> y reemplazarla por la declaración \"red-text\"."
|
||||
],
|
||||
"namePt": "",
|
||||
"descriptionPt": [],
|
||||
"nameDe": "Waypoint: Nutze eine CSS Klasse um ein Element zu gestalten",
|
||||
@ -509,8 +518,12 @@
|
||||
"descriptionFr": [],
|
||||
"nameRu": "",
|
||||
"descriptionRu": [],
|
||||
"nameEs": "",
|
||||
"descriptionEs": [],
|
||||
"nameEs": "Waypoint: Estila multiples elementos con una clase CSS",
|
||||
"descriptionEs": [
|
||||
"Aplica la clase \"red-text\" a tus elementos <code>h2</code> y <code>p</code>.",
|
||||
"Recuerda que puedes agregar clases a elementos HTML utilizando <code>class=\"your-class-here\"</code> dentro de la tag de entrada del mismo.",
|
||||
"Recuerda que los selectores CSS requieren un punto al principio: <code>.blue-text { color: blue; }</code>, pero que las declaraciones de clase NO llevan punto: <code><h2 class=\"blue-text\">CatPhotoApp<h2></code>."
|
||||
],
|
||||
"namePt": "",
|
||||
"descriptionPt": [],
|
||||
"nameDe": "Waypoint: Gestalte mehrere Elemente mit einer CSS Klasse",
|
||||
@ -555,8 +568,13 @@
|
||||
"descriptionFr": [],
|
||||
"nameRu": "",
|
||||
"descriptionRu": [],
|
||||
"nameEs": "",
|
||||
"descriptionEs": [],
|
||||
"nameEs": "Waypoint: Cambia el tamaño de fuente de un elemento.",
|
||||
"descriptionEs": [
|
||||
"Crea un segundo elemento <code>p</code>. Luego, dentro de tu elemento <code><style></code>, pon el \"font-size\" de todos los elementos <code>p</code> a 16 pixeles.",
|
||||
"El tamaño de fuente es controlado por el atributo CSS \"font-size\", como aquí: <code>h1 { font-size: 30px; }</code>.",
|
||||
"Primero, crea un segundo elemento <code>p</code> con el siguiente texto Kitty Ipsum: <code>Purr jump eat the grass rip the couch scratched sunbathe, shed everywhere rip the couch sleep in the sink fluffy fur catnip scratched.</code>",
|
||||
"Ve si puedes encontrar una manera de darle a ambos elementos <code>p</code> un font-size de 16 pixeles (<code>16px</code>). Puedes hacer esto dentro de la misma etiqueta <code><style></code> que creamos para la clase \"red-text\"."
|
||||
],
|
||||
"namePt": "",
|
||||
"descriptionPt": [],
|
||||
"nameDe": "Waypoint: Ändere die Schriftgröße eines Elements",
|
||||
@ -1971,7 +1989,7 @@
|
||||
],
|
||||
"tests": [
|
||||
"assert($('input[type=\"radio\"]').length > 1, 'Your page should have two radio button elements.')",
|
||||
"assert($('input[type=\"radio\"]:nth-child(1)').attr('name') === 'indoor-outdoor', 'Give your radio buttons the <code>name</code> attribute of \"indoor-outdoor\".')",
|
||||
"assert($('input[type=\"radio\"]:nth-child(1)').attr('name') === 'indoor-outdoor' && $('input[type=\"radio\"]:nth-child(2)').attr('name') === 'indoor-outdoor', 'Give your radio buttons the <code>name</code> attribute of \"indoor-outdoor\".')",
|
||||
"assert($('label').length > 1, 'Each of your two radio button elements should be nested in a label element.')",
|
||||
"assert(editor.match(/<\\/label>/g) && editor.match(/<label/g) && editor.match(/<\\/label>/g).length === editor.match(/<label/g).length, 'Make sure each of your <code>label</code> elements has a closing tag.')",
|
||||
"assert($('label').text().match(/indoor/gi), 'One of your radio buttons should have the label \"indoor\".')",
|
||||
|
@ -397,12 +397,12 @@
|
||||
"convert('Dolce & Gabbana');"
|
||||
],
|
||||
"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('<>'), '<>', 'should escape characters');",
|
||||
"assert.match(convert('Dolce & Gabbana'), /Dolce &(amp|AMP|#x00026|#38); Gabbana/, 'should escape characters');",
|
||||
"assert.match(convert('Hamburgers < Pizza < Tacos'), /Hamburgers &(lt|LT|#x0003C|#60); Pizza &(lt|LT|#x0003C|#60); Tacos/, 'should escape characters');",
|
||||
"assert.match(convert('Sixty > twelve'), /Sixty &(gt|GT|#x0003E|#62); twelve/, 'should escape characters');",
|
||||
"assert.match(convert('Stuff in \"quotation marks\"'), /Stuff in &(quot|QUOT|#x00022|#34);quotation marks&(quot|QUOT|#x00022|#34);/, 'should escape characters');",
|
||||
"assert.match(convert(\"Shindler's List\"), /Shindler&(apos|#x00027|#39);s List/, 'should escape characters');",
|
||||
"assert.match(convert('<>'), /&(lt|LT|#x0003C|#60);&(gt|GT|#x0003E|#62);/, 'should escape characters');",
|
||||
"assert.strictEqual(convert('abc'), 'abc', 'should handle strings with nothing to escape');"
|
||||
],
|
||||
"MDNlinks": [
|
||||
|
@ -140,7 +140,7 @@
|
||||
"difficulty": 1.07,
|
||||
"challengeSeed": ["126415123"],
|
||||
"description": [
|
||||
"<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='' target='_blank'>http://codepen.io/dting/full/KpJXZV/</a>.",
|
||||
"<span class='text-info'>Objective:</span> Build a <a href='http://codepen.io' target='_blank'>CodePen.io</a> app that successfully reverse-engineers this: <a href='http://codepen.io/dting/full/KpJXZV/' target='_blank'>http://codepen.io/dting/full/KpJXZV/</a>.",
|
||||
"<span class='text-info'>Rule #1:</span> Don't look at the example project's code on CodePen. Figure it out for yourself.",
|
||||
"<span class='text-info'>Rule #2:</span> You may use whichever libraries or APIs you need.",
|
||||
"<span class='text-info'>Rule #3:</span> Reverse engineer the example project's functionality, and also feel free to personalize it.",
|
||||
|
@ -63,7 +63,8 @@ Challenge.destroyAll(function(err, info) {
|
||||
.toLowerCase()
|
||||
.replace(/\:/g, '')
|
||||
.replace(/\s/g, '-');
|
||||
challenge.order = +('' + order + (index + 1));
|
||||
challenge.order = order;
|
||||
challenge.suborder = index + 1;
|
||||
challenge.block = block;
|
||||
|
||||
return challenge;
|
||||
|
@ -38,9 +38,10 @@ function updateUserProgress(user, challengeId, completedChallenge) {
|
||||
return id === challengeId;
|
||||
});
|
||||
|
||||
if (alreadyCompleted) {
|
||||
if (!alreadyCompleted) {
|
||||
user.progressTimestamps.push({
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
completedChallenge
|
||||
});
|
||||
}
|
||||
user.completedChallenges.push(completedChallenge);
|
||||
@ -458,7 +459,10 @@ module.exports = function(app) {
|
||||
.map(camperCount => numberWithCommas(camperCount));
|
||||
|
||||
const query = {
|
||||
order: 'order ASC'
|
||||
order: [
|
||||
'order ASC',
|
||||
'suborder ASC'
|
||||
]
|
||||
};
|
||||
|
||||
// create a stream of all the challenges
|
||||
|
@ -1,29 +1,29 @@
|
||||
var defaultProfileImage =
|
||||
require('../../common/utils/constantStrings.json').defaultProfileImage;
|
||||
var message =
|
||||
import { defaultProfileImage } from '../../common/utils/constantStrings.json';
|
||||
|
||||
const message =
|
||||
'Learn to Code JavaScript and get a Coding Job by Helping Nonprofits';
|
||||
|
||||
module.exports = function(app) {
|
||||
var router = app.loopback.Router();
|
||||
router.get('/', index);
|
||||
router.get('/', addDefaultImage, index);
|
||||
|
||||
app.use(router);
|
||||
|
||||
function index(req, res, next) {
|
||||
if (req.user)
|
||||
if (!req.user.picture) {
|
||||
req.user.picture = defaultProfileImage;
|
||||
|
||||
req.user.save(function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.render('get-started', {title: message});
|
||||
});
|
||||
} else {
|
||||
res.render('resources/get-started', {title: message});
|
||||
} else {
|
||||
res.render('home', { title: message });
|
||||
function addDefaultImage(req, res, next) {
|
||||
if (!req.user || req.user.picture) {
|
||||
return next();
|
||||
}
|
||||
req.user.picture = defaultProfileImage;
|
||||
req.user.save(function(err) {
|
||||
if (err) { return next(err); }
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function index(req, res) {
|
||||
if (req.user) {
|
||||
return res.render('resources/get-started', { title: message });
|
||||
}
|
||||
res.render('home', { title: message });
|
||||
}
|
||||
};
|
||||
|
@ -141,5 +141,19 @@ module.exports = {
|
||||
clientSecret: process.env.GITHUB_SECRET,
|
||||
scope: ['email'],
|
||||
failureFlash: true
|
||||
},
|
||||
'github-link': {
|
||||
provider: 'github',
|
||||
authScheme: 'oauth2',
|
||||
module: 'passport-github',
|
||||
authPath: '/link/github',
|
||||
callbackURL: '/link/github/callback',
|
||||
callbackPath: '/link/github/callback',
|
||||
successRedirect: successRedirect,
|
||||
failureRedirect: failureRedirect,
|
||||
clientID: process.env.GITHUB_ID,
|
||||
clientSecret: process.env.GITHUB_SECRET,
|
||||
scope: ['email'],
|
||||
failureFlash: true
|
||||
}
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ var passportOptions = {
|
||||
userObj.email = email;
|
||||
}
|
||||
|
||||
if (provider === 'github-login') {
|
||||
if (/github/.test(provider)) {
|
||||
setProfileFromGithub(userObj, profile, profile._json);
|
||||
}
|
||||
return userObj;
|
||||
|
Reference in New Issue
Block a user