Abstract map and showChallenge logic
Rename some legacy naming conventions Remove logic for waypoint,basejumps, etc...
This commit is contained in:
@ -31,11 +31,7 @@ destroy()
|
|||||||
|
|
||||||
var challenges = challengeSpec.challenges
|
var challenges = challengeSpec.challenges
|
||||||
.map(function(challenge, index) {
|
.map(function(challenge, index) {
|
||||||
// NOTE(berks): add title for displaying in views
|
challenge.name = challenge.title.replace(/[^a-zA-Z0-9\s]/g, '');
|
||||||
challenge.name =
|
|
||||||
_.capitalize(challenge.type) +
|
|
||||||
': ' +
|
|
||||||
challenge.title.replace(/[^a-zA-Z0-9\s]/g, '');
|
|
||||||
|
|
||||||
challenge.dashedName = challenge.name
|
challenge.dashedName = challenge.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
|
@ -33,13 +33,13 @@ const debug = debugFactory('freecc:challenges');
|
|||||||
const challengesRegex = /^(bonfire|waypoint|zipline|basejump|checkpoint)/i;
|
const challengesRegex = /^(bonfire|waypoint|zipline|basejump|checkpoint)/i;
|
||||||
const firstChallenge = 'waypoint-learn-how-free-code-camp-works';
|
const firstChallenge = 'waypoint-learn-how-free-code-camp-works';
|
||||||
const challengeView = {
|
const challengeView = {
|
||||||
0: 'coursewares/showHTML',
|
0: 'challenges/showHTML',
|
||||||
1: 'coursewares/showJS',
|
1: 'challenges/showJS',
|
||||||
2: 'coursewares/showVideo',
|
2: 'challenges/showVideo',
|
||||||
3: 'coursewares/showZiplineOrBasejump',
|
3: 'challenges/showZiplineOrBasejump',
|
||||||
4: 'coursewares/showZiplineOrBasejump',
|
4: 'challenges/showZiplineOrBasejump',
|
||||||
5: 'coursewares/showBonfire',
|
5: 'challenges/showBonfire',
|
||||||
7: 'coursewares/showStep'
|
7: 'challenges/showStep'
|
||||||
};
|
};
|
||||||
|
|
||||||
function isChallengeCompleted(user, challengeId) {
|
function isChallengeCompleted(user, challengeId) {
|
||||||
@ -50,9 +50,11 @@ function isChallengeCompleted(user, challengeId) {
|
|||||||
challenge.id === challengeId );
|
challenge.id === challengeId );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
function numberWithCommas(x) {
|
function numberWithCommas(x) {
|
||||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
function updateUserProgress(user, challengeId, completedChallenge) {
|
function updateUserProgress(user, challengeId, completedChallenge) {
|
||||||
let { completedChallenges } = user;
|
let { completedChallenges } = user;
|
||||||
@ -116,6 +118,131 @@ function shouldNotFilterComingSoon({ isComingSoon, isBeta: challengeIsBeta }) {
|
|||||||
(isBeta && challengeIsBeta);
|
(isBeta && challengeIsBeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRenderData$(user, challenge$, origChallengeName, solution) {
|
||||||
|
const challengeName = unDasherize(origChallengeName)
|
||||||
|
.replace(challengesRegex, '');
|
||||||
|
|
||||||
|
const testChallengeName = new RegExp(challengeName, 'i');
|
||||||
|
debug('looking for %s', testChallengeName);
|
||||||
|
|
||||||
|
return challenge$
|
||||||
|
.filter((challenge) => {
|
||||||
|
return testChallengeName.test(challenge.name) &&
|
||||||
|
shouldNotFilterComingSoon(challenge);
|
||||||
|
})
|
||||||
|
.last({ defaultValue: null })
|
||||||
|
.flatMap(challenge => {
|
||||||
|
if (challenge && isDev) {
|
||||||
|
return getFromDisk$(challenge);
|
||||||
|
}
|
||||||
|
return Observable.just(challenge);
|
||||||
|
})
|
||||||
|
.flatMap(challenge => {
|
||||||
|
|
||||||
|
// Handle not found
|
||||||
|
if (!challenge) {
|
||||||
|
debug('did not find challenge for ' + origChallengeName);
|
||||||
|
return Observable.just({
|
||||||
|
type: 'redirect',
|
||||||
|
redirectUrl: '/map',
|
||||||
|
message: dedent`
|
||||||
|
404: We couldn\'t find a challenge with the name ${origChallengeName}.
|
||||||
|
Please double check the name.
|
||||||
|
`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dasherize(challenge.name) !== origChallengeName) {
|
||||||
|
let redirectUrl = `/challenges/${dasherize(challenge.name)}`;
|
||||||
|
|
||||||
|
if (solution) {
|
||||||
|
redirectUrl += `?solution=${encodeURIComponent(solution)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Observable.just({
|
||||||
|
type: 'redirect',
|
||||||
|
redirectUrl
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// save user does nothing if user does not exist
|
||||||
|
return Observable.just({
|
||||||
|
data: {
|
||||||
|
...challenge,
|
||||||
|
// identifies if a challenge is completed
|
||||||
|
isCompleted: isChallengeCompleted(user, challenge.id),
|
||||||
|
|
||||||
|
// video challenges
|
||||||
|
video: challenge.challengeSeed[0],
|
||||||
|
|
||||||
|
// bonfires specific
|
||||||
|
bonfires: challenge,
|
||||||
|
MDNkeys: challenge.MDNlinks,
|
||||||
|
MDNlinks: getMDNLinks(challenge.MDNlinks),
|
||||||
|
|
||||||
|
// htmls specific
|
||||||
|
verb: randomVerb(),
|
||||||
|
phrase: randomPhrase(),
|
||||||
|
compliment: randomCompliment()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a stream of an array of all the challenge blocks
|
||||||
|
function getSuperBlocks$(challenge$, completedChallenges) {
|
||||||
|
return challenge$
|
||||||
|
// mark challenge completed
|
||||||
|
.map(challengeModel => {
|
||||||
|
const challenge = challengeModel.toJSON();
|
||||||
|
if (completedChallenges.indexOf(challenge.id) !== -1) {
|
||||||
|
challenge.completed = true;
|
||||||
|
}
|
||||||
|
challenge.markNew = shouldShowNew(challenge);
|
||||||
|
return challenge;
|
||||||
|
})
|
||||||
|
// group challenges by block | returns a stream of observables
|
||||||
|
.groupBy(challenge => challenge.block)
|
||||||
|
// turn block group stream into an array
|
||||||
|
.flatMap(block$ => block$.toArray())
|
||||||
|
.map(blockArray => {
|
||||||
|
const completedCount = blockArray.reduce((sum, { completed }) => {
|
||||||
|
if (completed) {
|
||||||
|
return sum + 1;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}, 0);
|
||||||
|
const isBeta = _.every(blockArray, 'isBeta');
|
||||||
|
const isComingSoon = _.every(blockArray, 'isComingSoon');
|
||||||
|
|
||||||
|
return {
|
||||||
|
isBeta,
|
||||||
|
isComingSoon,
|
||||||
|
name: blockArray[0].block,
|
||||||
|
superBlock: blockArray[0].superBlock,
|
||||||
|
dashedName: dasherize(blockArray[0].block),
|
||||||
|
markNew: shouldShowNew(null, blockArray),
|
||||||
|
challenges: blockArray,
|
||||||
|
completed: completedCount / blockArray.length * 100,
|
||||||
|
time: blockArray[0] && blockArray[0].time || '???'
|
||||||
|
};
|
||||||
|
})
|
||||||
|
// filter out hikes
|
||||||
|
.filter(({ superBlock }) => {
|
||||||
|
return !(/hikes/i).test(superBlock);
|
||||||
|
})
|
||||||
|
// turn stream of blocks into a stream of an array
|
||||||
|
.toArray()
|
||||||
|
.flatMap(blocks => Observable.from(blocks, null, null, Scheduler.default))
|
||||||
|
.groupBy(block => block.superBlock)
|
||||||
|
.flatMap(blocks$ => blocks$.toArray())
|
||||||
|
.map(superBlockArray => ({
|
||||||
|
name: superBlockArray[0].superBlock,
|
||||||
|
blocks: superBlockArray
|
||||||
|
}))
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
const router = app.loopback.Router();
|
const router = app.loopback.Router();
|
||||||
|
|
||||||
@ -167,8 +294,6 @@ module.exports = function(app) {
|
|||||||
.shareReplay();
|
.shareReplay();
|
||||||
|
|
||||||
const User = app.models.User;
|
const User = app.models.User;
|
||||||
const userCount$ = observeMethod(User, 'count');
|
|
||||||
|
|
||||||
const send200toNonUser = ifNoUserSend(true);
|
const send200toNonUser = ifNoUserSend(true);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
@ -182,13 +307,13 @@ module.exports = function(app) {
|
|||||||
completedZiplineOrBasejump
|
completedZiplineOrBasejump
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get('/map', challengeMap);
|
router.get('/map', showMap);
|
||||||
router.get(
|
router.get(
|
||||||
'/challenges/next-challenge',
|
'/challenges/next-challenge',
|
||||||
returnNextChallenge
|
returnNextChallenge
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get('/challenges/:challengeName', returnIndividualChallenge);
|
router.get('/challenges/:challengeName', showChallenge);
|
||||||
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
|
||||||
@ -279,92 +404,20 @@ module.exports = function(app) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnIndividualChallenge(req, res, next) {
|
function showChallenge(req, res, next) {
|
||||||
const origChallengeName = req.params.challengeName;
|
const solution = req.query.solution;
|
||||||
const solutionCode = req.query.solution;
|
|
||||||
const unDashedName = unDasherize(origChallengeName);
|
|
||||||
|
|
||||||
const challengeName = challengesRegex.test(unDashedName) ?
|
getRenderData$(req.user, challenge$, req.params.challengeName, solution)
|
||||||
// remove first word if matches
|
|
||||||
unDashedName.split(' ').slice(1).join(' ') :
|
|
||||||
unDashedName;
|
|
||||||
|
|
||||||
const testChallengeName = new RegExp(challengeName, 'i');
|
|
||||||
debug('looking for %s', testChallengeName);
|
|
||||||
challenge$
|
|
||||||
.filter((challenge) => {
|
|
||||||
return testChallengeName.test(challenge.name) &&
|
|
||||||
shouldNotFilterComingSoon(challenge);
|
|
||||||
})
|
|
||||||
.last({ defaultValue: null })
|
|
||||||
.flatMap(challenge => {
|
|
||||||
if (challenge && isDev) {
|
|
||||||
return getFromDisk$(challenge);
|
|
||||||
}
|
|
||||||
return Observable.just(challenge);
|
|
||||||
})
|
|
||||||
.flatMap(challenge => {
|
|
||||||
|
|
||||||
// Handle not found
|
|
||||||
if (!challenge) {
|
|
||||||
debug('did not find challenge for ' + origChallengeName);
|
|
||||||
req.flash('errors', {
|
|
||||||
msg:
|
|
||||||
'404: We couldn\'t find a challenge with the name `' +
|
|
||||||
origChallengeName +
|
|
||||||
'` Please double check the name.'
|
|
||||||
});
|
|
||||||
return Observable.just('/map');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dasherize(challenge.name) !== origChallengeName) {
|
|
||||||
let redirectUrl = `/challenges/${dasherize(challenge.name)}`;
|
|
||||||
|
|
||||||
if (solutionCode) {
|
|
||||||
redirectUrl += `?solution=${encodeURIComponent(solutionCode)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Observable.just(redirectUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save user does nothing if user does not exist
|
|
||||||
return Observable.just({
|
|
||||||
|
|
||||||
title: challenge.name,
|
|
||||||
name: challenge.name,
|
|
||||||
details: challenge.description,
|
|
||||||
description: challenge.description,
|
|
||||||
challengeId: challenge.id,
|
|
||||||
challengeType: challenge.challengeType,
|
|
||||||
dashedName: origChallengeName,
|
|
||||||
|
|
||||||
challengeSeed: challenge.challengeSeed,
|
|
||||||
head: challenge.head,
|
|
||||||
tail: challenge.tail,
|
|
||||||
tests: challenge.tests,
|
|
||||||
|
|
||||||
// identifies if a challenge is completed
|
|
||||||
isCompleted: isChallengeCompleted(req.user, challenge.id),
|
|
||||||
|
|
||||||
// video challenges
|
|
||||||
video: challenge.challengeSeed[0],
|
|
||||||
|
|
||||||
// bonfires specific
|
|
||||||
bonfires: challenge,
|
|
||||||
MDNkeys: challenge.MDNlinks,
|
|
||||||
MDNlinks: getMDNLinks(challenge.MDNlinks),
|
|
||||||
|
|
||||||
// htmls specific
|
|
||||||
verb: randomVerb(),
|
|
||||||
phrase: randomPhrase(),
|
|
||||||
compliment: randomCompliment()
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.subscribe(
|
.subscribe(
|
||||||
function(data) {
|
({ type, redirectUrl, message, data }) => {
|
||||||
if (typeof data === 'string') {
|
if (message) {
|
||||||
debug('redirecting to %s', data);
|
req.flash('info', {
|
||||||
return res.redirect(data);
|
msg: message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type === 'redirect') {
|
||||||
|
debug('redirecting to %s', redirectUrl);
|
||||||
|
return res.redirect(redirectUrl);
|
||||||
}
|
}
|
||||||
var view = challengeView[data.challengeType];
|
var view = challengeView[data.challengeType];
|
||||||
res.render(view, data);
|
res.render(view, data);
|
||||||
@ -500,93 +553,18 @@ module.exports = function(app) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function challengeMap({ user = {} }, res, next) {
|
function showMap({ user = {} }, res, next) {
|
||||||
|
|
||||||
let lastCompleted;
|
|
||||||
const daysRunning = moment().diff(new Date('10/15/2014'), 'days');
|
|
||||||
|
|
||||||
// if user
|
// if user
|
||||||
// get the id's of all the users completed challenges
|
// get the id's of all the users completed challenges
|
||||||
const completedChallenges = !user.completedChallenges ?
|
const completedChallenges = !user.completedChallenges ?
|
||||||
[] :
|
[] :
|
||||||
_.uniq(user.completedChallenges).map(({ id, _id }) => id || _id);
|
_.uniq(user.completedChallenges).map(({ id, _id }) => id || _id);
|
||||||
|
|
||||||
const camperCount$ = userCount$()
|
getSuperBlocks$(challenge$, completedChallenges)
|
||||||
.map(camperCount => numberWithCommas(camperCount));
|
|
||||||
|
|
||||||
// create a stream of an array of all the challenge blocks
|
|
||||||
const superBlocks$ = challenge$
|
|
||||||
// mark challenge completed
|
|
||||||
.map(challengeModel => {
|
|
||||||
const challenge = challengeModel.toJSON();
|
|
||||||
if (completedChallenges.indexOf(challenge.id) !== -1) {
|
|
||||||
challenge.completed = true;
|
|
||||||
}
|
|
||||||
challenge.markNew = shouldShowNew(challenge);
|
|
||||||
return challenge;
|
|
||||||
})
|
|
||||||
// group challenges by block | returns a stream of observables
|
|
||||||
.groupBy(challenge => challenge.block)
|
|
||||||
// turn block group stream into an array
|
|
||||||
.flatMap(block$ => block$.toArray())
|
|
||||||
.map(blockArray => {
|
|
||||||
const completedCount = blockArray.reduce((sum, { completed }) => {
|
|
||||||
if (completed) {
|
|
||||||
return sum + 1;
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}, 0);
|
|
||||||
const isBeta = _.every(blockArray, 'isBeta');
|
|
||||||
const isComingSoon = _.every(blockArray, 'isComingSoon');
|
|
||||||
|
|
||||||
return {
|
|
||||||
isBeta,
|
|
||||||
isComingSoon,
|
|
||||||
name: blockArray[0].block,
|
|
||||||
superBlock: blockArray[0].superBlock,
|
|
||||||
dashedName: dasherize(blockArray[0].block),
|
|
||||||
markNew: shouldShowNew(null, blockArray),
|
|
||||||
challenges: blockArray,
|
|
||||||
completed: completedCount / blockArray.length * 100,
|
|
||||||
time: blockArray[0] && blockArray[0].time || '???'
|
|
||||||
};
|
|
||||||
})
|
|
||||||
// filter out hikes
|
|
||||||
.filter(({ superBlock }) => {
|
|
||||||
return !(/hikes/i).test(superBlock);
|
|
||||||
})
|
|
||||||
// turn stream of blocks into a stream of an array
|
|
||||||
.toArray()
|
|
||||||
.doOnNext(blocks => {
|
|
||||||
const lastCompletedBlock = _.findLast(blocks, (block) => {
|
|
||||||
return block.completed === 100;
|
|
||||||
});
|
|
||||||
lastCompleted = lastCompletedBlock && lastCompletedBlock.name || null;
|
|
||||||
})
|
|
||||||
.flatMap(blocks => Observable.from(blocks, null, null, Scheduler.default))
|
|
||||||
.groupBy(block => block.superBlock)
|
|
||||||
.flatMap(blocks$ => blocks$.toArray())
|
|
||||||
.map(superBlockArray => ({
|
|
||||||
name: superBlockArray[0].superBlock,
|
|
||||||
blocks: superBlockArray
|
|
||||||
}))
|
|
||||||
.toArray();
|
|
||||||
|
|
||||||
Observable.combineLatest(
|
|
||||||
camperCount$,
|
|
||||||
superBlocks$,
|
|
||||||
(camperCount, superBlocks) => ({ camperCount, superBlocks })
|
|
||||||
)
|
|
||||||
.subscribe(
|
.subscribe(
|
||||||
({ camperCount, superBlocks }) => {
|
superBlocks => {
|
||||||
res.render('challengeMap/show', {
|
res.render('map/show', {
|
||||||
superBlocks,
|
superBlocks,
|
||||||
daysRunning,
|
|
||||||
globalCompletedCount: numberWithCommas(
|
|
||||||
5612952 + (Math.floor((Date.now() - 1446268581061) / 2000))
|
|
||||||
),
|
|
||||||
camperCount,
|
|
||||||
lastCompleted,
|
|
||||||
title: 'A Map to Learn to Code and Become a Software Engineer'
|
title: 'A Map to Learn to Code and Become a Software Engineer'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import _ from 'lodash';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Observable } from 'rx';
|
import { Observable } from 'rx';
|
||||||
|
|
||||||
@ -22,10 +21,7 @@ export default function getFromDisk$(challenge) {
|
|||||||
challenge.tail = challenge.tail || [];
|
challenge.tail = challenge.tail || [];
|
||||||
challenge.challengeType = '' + challenge.challengeType;
|
challenge.challengeType = '' + challenge.challengeType;
|
||||||
|
|
||||||
challenge.name =
|
challenge.name = challenge.title.replace(/[^a-zA-Z0-9\s]/g, '');
|
||||||
_.capitalize(challenge.type) +
|
|
||||||
': ' +
|
|
||||||
challenge.title.replace(/[^a-zA-Z0-9\s]/g, '');
|
|
||||||
|
|
||||||
challenge.dashedName = challenge.name
|
challenge.dashedName = challenge.name
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
|
@ -17,7 +17,7 @@ block content
|
|||||||
.row
|
.row
|
||||||
.col-xs-12
|
.col-xs-12
|
||||||
.bonfire-instructions
|
.bonfire-instructions
|
||||||
for sentence in details
|
for sentence in description
|
||||||
if (/blockquote|h4|table/.test(sentence))
|
if (/blockquote|h4|table/.test(sentence))
|
||||||
!=sentence
|
!=sentence
|
||||||
else
|
else
|
||||||
@ -83,7 +83,7 @@ block content
|
|||||||
i.fa.fa-twitter  
|
i.fa.fa-twitter  
|
||||||
= phrase
|
= phrase
|
||||||
else
|
else
|
||||||
a#next-challenge.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+challengeId) Go to my next challenge (ctrl + enter)
|
a#next-challenge.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+id) Go to my next challenge (ctrl + enter)
|
||||||
include ../partials/challenge-modals
|
include ../partials/challenge-modals
|
||||||
script(type="text/javascript").
|
script(type="text/javascript").
|
||||||
var common = window.common = window.common || { init: [] };
|
var common = window.common = window.common || { init: [] };
|
||||||
@ -92,7 +92,7 @@ block content
|
|||||||
common.head = !{JSON.stringify(head)};
|
common.head = !{JSON.stringify(head)};
|
||||||
common.tail = !{JSON.stringify(tail)};
|
common.tail = !{JSON.stringify(tail)};
|
||||||
|
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
@ -16,7 +16,7 @@ block content
|
|||||||
i.ion-checkmark-circled.text-primary(title="Completed")
|
i.ion-checkmark-circled.text-primary(title="Completed")
|
||||||
hr
|
hr
|
||||||
.bonfire-instructions
|
.bonfire-instructions
|
||||||
for sentence in details
|
for sentence in description
|
||||||
p.wrappable.negative-10!= sentence
|
p.wrappable.negative-10!= sentence
|
||||||
.negative-bottom-margin-30
|
.negative-bottom-margin-30
|
||||||
.button-spacer
|
.button-spacer
|
||||||
@ -74,7 +74,7 @@ block content
|
|||||||
if(user)
|
if(user)
|
||||||
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
|
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
|
||||||
else
|
else
|
||||||
a#next-challenge.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+challengeId) Go to my next challenge (ctrl + enter)
|
a#next-challenge.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+id) Go to my next challenge (ctrl + enter)
|
||||||
include ../partials/challenge-modals
|
include ../partials/challenge-modals
|
||||||
script(type="text/javascript").
|
script(type="text/javascript").
|
||||||
$('#next-courseware-button').attr('disabled', 'disabled');
|
$('#next-courseware-button').attr('disabled', 'disabled');
|
||||||
@ -84,7 +84,7 @@ block content
|
|||||||
common.head = !{JSON.stringify(head)};
|
common.head = !{JSON.stringify(head)};
|
||||||
common.tail = !{JSON.stringify(tail)};
|
common.tail = !{JSON.stringify(tail)};
|
||||||
|
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
@ -17,7 +17,7 @@ block content
|
|||||||
.row
|
.row
|
||||||
.col-xs-12
|
.col-xs-12
|
||||||
.bonfire-instructions
|
.bonfire-instructions
|
||||||
for sentence in details
|
for sentence in description
|
||||||
if (/blockquote|h4|table/.test(sentence))
|
if (/blockquote|h4|table/.test(sentence))
|
||||||
!=sentence
|
!=sentence
|
||||||
else
|
else
|
||||||
@ -82,7 +82,7 @@ block content
|
|||||||
if (user)
|
if (user)
|
||||||
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
|
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
|
||||||
else
|
else
|
||||||
a#next-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+challengeId) Go to my next challenge (ctrl + enter)
|
a#next-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href="/challenges/next-challenge?id="+id) Go to my next challenge (ctrl + enter)
|
||||||
include ../partials/challenge-modals
|
include ../partials/challenge-modals
|
||||||
script(type="text/javascript").
|
script(type="text/javascript").
|
||||||
var common = window.common = { init: [] };
|
var common = window.common = { init: [] };
|
||||||
@ -91,7 +91,7 @@ block content
|
|||||||
common.head = !{JSON.stringify(head)};
|
common.head = !{JSON.stringify(head)};
|
||||||
common.tail = !{JSON.stringify(tail)};
|
common.tail = !{JSON.stringify(tail)};
|
||||||
|
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
common.challengeSeed = !{JSON.stringify(challengeSeed)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
@ -37,11 +37,11 @@ block content
|
|||||||
if (user)
|
if (user)
|
||||||
#challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge
|
#challenge-step-btn-submit.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge
|
||||||
else
|
else
|
||||||
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
|
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + id) Go to my next challenge
|
||||||
script.
|
script.
|
||||||
var common = window.common || { init: [] };
|
var common = window.common || { init: [] };
|
||||||
|
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
||||||
common.dashedName = !{JSON.stringify(dashedName || '')};
|
common.dashedName = !{JSON.stringify(dashedName || '')};
|
@ -6,7 +6,7 @@ block content
|
|||||||
.well
|
.well
|
||||||
h4
|
h4
|
||||||
ol
|
ol
|
||||||
for step, index in details
|
for step, index in description
|
||||||
.row.checklist-element(id="#{dashedName + index}")
|
.row.checklist-element(id="#{dashedName + index}")
|
||||||
.col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center
|
.col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center
|
||||||
input(type='checkbox' class='challenge-list-checkbox')
|
input(type='checkbox' class='challenge-list-checkbox')
|
||||||
@ -19,7 +19,7 @@ block content
|
|||||||
if (user)
|
if (user)
|
||||||
a.btn.btn-primary.btn-big.btn-block#completed-courseware-editorless I've completed this challenge (ctrl + enter)
|
a.btn.btn-primary.btn-big.btn-block#completed-courseware-editorless I've completed this challenge (ctrl + enter)
|
||||||
else
|
else
|
||||||
a.btn.btn-big.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) I've completed this challenge (ctrl + enter)
|
a.btn.btn-big.btn-primary.btn-block(href='/challenges/next-challenge?id=' + id) I've completed this challenge (ctrl + enter)
|
||||||
script.
|
script.
|
||||||
var userLoggedIn = true;
|
var userLoggedIn = true;
|
||||||
.button-spacer
|
.button-spacer
|
||||||
@ -51,13 +51,13 @@ block content
|
|||||||
if (user)
|
if (user)
|
||||||
a.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) I've completed this challenge (ctrl + enter)
|
a.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) I've completed this challenge (ctrl + enter)
|
||||||
else
|
else
|
||||||
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) I've completed this challenge (ctrl + enter)
|
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + id) I've completed this challenge (ctrl + enter)
|
||||||
|
|
||||||
include ../partials/challenge-modals
|
include ../partials/challenge-modals
|
||||||
script.
|
script.
|
||||||
var common = window.common || { init: [] };
|
var common = window.common || { init: [] };
|
||||||
|
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
||||||
common.dashedName = !{JSON.stringify(dashedName)};
|
common.dashedName = !{JSON.stringify(dashedName)};
|
@ -6,7 +6,7 @@ block content
|
|||||||
hr
|
hr
|
||||||
h4
|
h4
|
||||||
ol
|
ol
|
||||||
for step, index in details
|
for step, index in description
|
||||||
.row.checklist-element(id="#{dashedName + index}")
|
.row.checklist-element(id="#{dashedName + index}")
|
||||||
.col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center
|
.col-xs-3.col-sm-1.col-md-2.padded-ionic-icon.text-center
|
||||||
input(type='checkbox' class='challenge-list-checkbox')
|
input(type='checkbox' class='challenge-list-checkbox')
|
||||||
@ -21,7 +21,7 @@ block content
|
|||||||
script.
|
script.
|
||||||
var userLoggedIn = true;
|
var userLoggedIn = true;
|
||||||
else
|
else
|
||||||
a.btn.btn-big.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge (ctrl + enter)
|
a.btn.btn-big.btn-primary.btn-block(href='/challenges/next-challenge?id=' + id) Go to my next challenge (ctrl + enter)
|
||||||
.button-spacer
|
.button-spacer
|
||||||
.btn-group.input-group.btn-group-justified
|
.btn-group.input-group.btn-group-justified
|
||||||
.btn.btn-primary.btn-primary-ghost.btn-big#challenge-help-btn
|
.btn.btn-primary.btn-primary-ghost.btn-big#challenge-help-btn
|
||||||
@ -65,12 +65,12 @@ block content
|
|||||||
a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE_USING_FULL_INSTEAD_OF_PEN%20%0A%20%23LearnToCode%20%23JavaScript", onclick="ga('send', 'event', 'twitter', 'share', 'challenge completion share');")
|
a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=Check%20out%20the%20project%20I%20just%20built%20with%20%40FreeCodeCamp:%20PASTE_YOUR_CODEPEN_URL_HERE_USING_FULL_INSTEAD_OF_PEN%20%0A%20%23LearnToCode%20%23JavaScript", onclick="ga('send', 'event', 'twitter', 'share', 'challenge completion share');")
|
||||||
i.fa.fa-twitter  Tweet this project
|
i.fa.fa-twitter  Tweet this project
|
||||||
else
|
else
|
||||||
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
|
a.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + id) Go to my next challenge
|
||||||
|
|
||||||
include ../partials/challenge-modals
|
include ../partials/challenge-modals
|
||||||
script.
|
script.
|
||||||
var common = window.common || { init: [] };
|
var common = window.common || { init: [] };
|
||||||
common.challengeId = !{JSON.stringify(challengeId)};
|
common.challengeId = !{JSON.stringify(id)};
|
||||||
common.challengeName = !{JSON.stringify(name)};
|
common.challengeName = !{JSON.stringify(name)};
|
||||||
common.dashedName = !{JSON.stringify(dashedName)};
|
common.dashedName = !{JSON.stringify(dashedName)};
|
||||||
common.challengeType = !{JSON.stringify(challengeType)};
|
common.challengeType = !{JSON.stringify(challengeType)};
|
Reference in New Issue
Block a user