diff --git a/client/index.js b/client/index.js
index 79c5c541c1..44bdb0a82c 100644
--- a/client/index.js
+++ b/client/index.js
@@ -4,7 +4,7 @@ import React from 'react';
import Fetchr from 'fetchr';
import debugFactory from 'debug';
import { Router } from 'react-router';
-import { history } from 'react-router/lib/BrowserHistory';
+import { createLocation, createHistory } from 'history';
import { hydrate } from 'thundercats';
import { Render } from 'thundercats-react';
@@ -18,21 +18,29 @@ const services = new Fetchr({
});
Rx.config.longStackSupport = !!debug.enabled;
-
+const history = createHistory();
+const appLocation = createLocation(
+ location.pathname + location.search
+);
// returns an observable
-app$(history)
+app$({ history, location: appLocation })
.flatMap(
({ AppCat }) => {
+ // instantiate the cat with service
const appCat = AppCat(null, services);
+ // hydrate the stores
return hydrate(appCat, catState)
.map(() => appCat);
},
- ({ initialState }, appCat) => ({ initialState, appCat })
+ // not using nextLocation at the moment but will be used for
+ // redirects in the future
+ ({ nextLocation, props }, appCat) => ({ nextLocation, props, appCat })
)
- .flatMap(({ initialState, appCat }) => {
+ .flatMap(({ props, appCat }) => {
+ props.history = history;
return Render(
appCat,
- React.createElement(Router, initialState),
+ React.createElement(Router, props),
DOMContianer
);
})
diff --git a/client/main.js b/client/main.js
index 6e6ce8c696..c1578c1d6f 100644
--- a/client/main.js
+++ b/client/main.js
@@ -1,3 +1,32 @@
+var mapShareKey = 'map-shares';
+var lastCompleted = typeof lastCompleted !== 'undefined' ?
+ lastCompleted :
+ '';
+
+function getMapShares() {
+ var alreadyShared = JSON.parse(localStorage.getItem(mapShareKey) || '[]');
+ if (!alreadyShared || !Array.isArray(alreadyShared)) {
+ localStorage.setItem(mapShareKey, JSON.stringify([]));
+ alreadyShared = [];
+ }
+ return alreadyShared;
+}
+
+function setMapShare(id) {
+ var alreadyShared = getMapShares();
+ var found = false;
+ alreadyShared.forEach(function(_id) {
+ if (_id === id) {
+ found = true;
+ }
+ });
+ if (!found) {
+ alreadyShared.push(id);
+ }
+ localStorage.setItem(mapShareKey, JSON.stringify(alreadyShared));
+ return alreadyShared;
+}
+
$(document).ready(function() {
var challengeName = typeof challengeName !== 'undefined' ?
@@ -383,6 +412,40 @@ $(document).ready(function() {
}
}, false);
}
+
+
+ // map sharing
+ var alreadyShared = getMapShares();
+
+ if (lastCompleted && alreadyShared.indexOf(lastCompleted) === -1) {
+ $('div[id="' + lastCompleted + '"]')
+ .parent()
+ .parent()
+ .removeClass('hidden');
+ }
+
+ // on map view
+ $('.map-challenge-block-share').on('click', function(e) {
+ e.preventDefault();
+ var challengeBlockName = $(this).children().attr('id');
+ var challengeBlockEscapedName = challengeBlockName.replace(/\s/, '%20');
+ var username = typeof window.username !== 'undefined' ?
+ window.username :
+ '';
+
+ var link = 'https://www.facebook.com/dialog/feed?' +
+ 'app_id=1644598365767721' +
+ '&display=page&' +
+ 'caption=I%20just%20completed%20the%20' +
+ challengeBlockEscapedName +
+ '%20section%20on%20Free%20Code%20Camp%2E' +
+ '&link=http%3A%2F%2Ffreecodecamp%2Ecom%2F' +
+ username +
+ '&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap';
+
+ setMapShare(challengeBlockName);
+ window.location.href = link;
+ });
});
function defCheck(a){
diff --git a/common/app/app-stream.jsx b/common/app/app-stream.jsx
index 25ae2a6300..82d5568c09 100644
--- a/common/app/app-stream.jsx
+++ b/common/app/app-stream.jsx
@@ -1,17 +1,17 @@
import Rx from 'rx';
-import { Router } from 'react-router';
+import { match } from 'react-router';
import App from './App.jsx';
import AppCat from './Cat';
import childRoutes from './routes';
-const router$ = Rx.Observable.fromNodeCallback(Router.run, Router);
+const route$ = Rx.Observable.fromNodeCallback(match);
const routes = Object.assign({ components: App }, childRoutes);
-export default function app$(location) {
- return router$(routes, location)
- .map(([initialState, transistion]) => {
- return { initialState, transistion, AppCat };
+export default function app$({ location, history }) {
+ return route$({ routes, location, history })
+ .map(([nextLocation, props]) => {
+ return { nextLocation, props, AppCat };
});
}
diff --git a/common/app/routes/Jobs/components/CreateJobModal.jsx b/common/app/routes/Jobs/components/CreateJobModal.jsx
new file mode 100644
index 0000000000..446ed957d6
--- /dev/null
+++ b/common/app/routes/Jobs/components/CreateJobModal.jsx
@@ -0,0 +1,43 @@
+import React, { PropTypes } from 'react';
+import { History } from 'react-router';
+import { Button, Modal } from 'react-bootstrap';
+
+export default React.createClass({
+ displayName: 'CreateJobsModal',
+
+ propTypes: {
+ onHide: PropTypes.func,
+ showModal: PropTypes.bool
+ },
+
+ mixins: [History],
+
+ goToNewJob(onHide) {
+ onHide();
+ this.history.pushState(null, '/jobs/new');
+ },
+
+ render() {
+ const {
+ showModal,
+ onHide
+ } = this.props;
+
+ return (
+ We post jobs specifically target to our junior developers.Welcome to Free Code Camp's board
+
{ description }
-{ description }
+a
element should have the anchor text of \"cat photos\"')",
"assert($(\"p\") && $(\"p\").length > 2, 'Create a new p
element around your a
element.')",
"assert($(\"a[href=\\\"http://www.freecatphotoapp.com\\\"]\").parent().is(\"p\"), 'Your a
element should be nested within your new p
element.')",
- "assert($(\"p\").text().match(/View\\smore/gi), 'Your p
element should have the text \"View more\".')",
+ "assert($(\"p\").text().match(/^View\\smore\\s/gi), 'Your p
element should have the text \"View more \" (with a space after it).')",
+ "assert(!$(\"a\").text().match(/View\\smore/gi), 'Your a
element should not have the text \"View more\".')",
"assert(editor.match(/<\\/p>/g) && editor.match(//g).length === editor.match(/
p elements has a closing tag.')",
"assert(editor.match(/<\\/a>/g) && editor.match(//g).length === editor.match(/a elements has a closing tag.')"
],
diff --git a/seed/challenges/intermediate-bonfires.json b/seed/challenges/intermediate-bonfires.json
index 684afd44e8..62aef4687d 100644
--- a/seed/challenges/intermediate-bonfires.json
+++ b/seed/challenges/intermediate-bonfires.json
@@ -61,6 +61,7 @@
"diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);"
],
"tests": [
+<<<<<<< HEAD
"assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'message: diff()
should return an array.');",
"assert.deepEqual(diff([\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"pink wool\"], 'message: [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"pink wool\"]
.');",
"assert.includeMembers(diff([\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]), [\"diorite\", \"pink wool\"], 'message: [\"andesite\", \"grass\", \"dirt\", \"pink wool\", \"dead shrub\"], [\"diorite\", \"andesite\", \"grass\", \"dirt\", \"dead shrub\"]
should return [\"diorite\", \"pink wool\"]
.');",
@@ -68,6 +69,15 @@
"assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'message: [1, 2, 3, 5], [1, 2, 3, 4, 5]
should return [4]
.');",
"assert.includeMembers(diff([1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]), [\"piglet\", 4], 'message: [1, \"calf\", 3, \"piglet\"], [1, \"calf\", 3, 4]
should return [\"piglet\", 4]
.');",
"assert.deepEqual(diff([], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]), [\"snuffleupagus\", \"cookie monster\", \"elmo\"], 'message: [], [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
should return [\"snuffleupagus\", \"cookie monster\", \"elmo\"]
.');"
+=======
+ "assert(typeof(diff([1, 2, 3, 5], [1, 2, 3, 4, 5])) === \"object\", 'The result should be an array.');",
+ "assert.deepEqual(diff(['diorite', 'andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['pink wool'], 'arrays with only one difference');",
+ "assert.includeMembers(diff(['andesite', 'grass', 'dirt', 'pink wool', 'dead shrub'], ['diorite', 'andesite', 'grass', 'dirt', 'dead shrub']), ['diorite', 'pink wool'], 'arrays with more than one difference');",
+ "assert.deepEqual(diff(['andesite', 'grass', 'dirt', 'dead shrub'], ['andesite', 'grass', 'dirt', 'dead shrub']), [], 'arrays with no difference');",
+ "assert.deepEqual(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]), [4], 'arrays with numbers');",
+ "assert.includeMembers(diff([1, 'calf', 3, 'piglet'], [1, 'calf', 3, 4]), ['piglet', 4], 'arrays with numbers and strings');",
+ "assert.deepEqual(diff([], ['snuffleupagus', 'cookie monster', 'elmo']), ['snuffleupagus', 'cookie monster', 'elmo'], 'empty array');"
+>>>>>>> staging
],
"MDNlinks": [
"Comparison Operators",
@@ -93,11 +103,19 @@
"id": "a7f4d8f2483413a6ce226cac",
"title": "Roman Numeral Converter",
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(convert(12), \"XII\", 'message: convert(12)
should return \"XII\".');",
"assert.deepEqual(convert(5), \"V\", 'message: convert(5)
should return \"V\".');",
"assert.deepEqual(convert(9), \"IX\", 'message: convert(9)
should return \"IX\".');",
"assert.deepEqual(convert(29), \"XXIX\", 'message: convert(29)
should return \"XXIX\".');",
"assert.deepEqual(convert(16), \"XVI\", 'message: convert(16)
should return \"XVI\".');"
+=======
+ "assert.deepEqual(convert(12), \"XII\", 'convert(12)
should return \"XII\"');",
+ "assert.deepEqual(convert(5), \"V\", 'convert(5)
should return \"V\"');",
+ "assert.deepEqual(convert(9), \"IX\", 'convert(9)
should return \"IX\"');",
+ "assert.deepEqual(convert(29), \"XXIX\", 'convert(29)
should return \"XXIX\"');",
+ "assert.deepEqual(convert(16), \"XVI\", 'convert(16)
should return \"XVI\"');"
+>>>>>>> staging
],
"difficulty": "2.02",
"description": [
@@ -150,9 +168,16 @@
"where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" });"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(where([{ first: \"Romeo\", last: \"Montague\" }, { first: \"Mercutio\", last: null }, { first: \"Tybalt\", last: \"Capulet\" }], { last: \"Capulet\" }), [{ first: \"Tybalt\", last: \"Capulet\" }], 'message: where()
should return an array of objects.');",
"assert.deepEqual(where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 }), [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], 'message: where([{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }], { \"a\": 1 })
should return [{ \"a\": 1 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2 }]
.');",
"assert.deepEqual(where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 }), [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], 'message: where([{ \"a\": 1, \"b\": 2 }, { \"a\": 1 }, { \"a\": 1, \"b\": 2, \"c\": 2 }], { \"a\": 1, \"b\": 2 })
should return [{ \"a\": 1, \"b\": 2 }, { \"a\": 1, \"b\": 2, \"c\": 2 }]
.');"
+=======
+ "assert.deepEqual(where([{ first: 'Romeo', last: 'Montague' }, { first: 'Mercutio', last: null }, { first: 'Tybalt', last: 'Capulet' }], { last: 'Capulet' }), [{ first: 'Tybalt', last: 'Capulet' }], 'should return an array of objects');",
+ "assert.deepEqual(where([{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], { 'a': 1 }), [{ 'a': 1 }, { 'a': 1 }, { 'a': 1, 'b': 2 }], 'should return with multiples');",
+ "assert.deepEqual(where([{ 'a': 1, 'b': 2 }, { 'a': 1 }, { 'a': 1, 'b': 2, 'c': 2 }], { 'a': 1, 'b': 2 }), [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 2, 'c': 2 }], 'should return two objects in array');",
+ "assert.deepEqual(where([{ 'a': 5 }, { 'b': 10 }, { 'a': 5, 'b': 10 }], { 'a': 5, 'b': 10 }), [{ 'a': 5, 'b': 10 }], 'should return a single object in array');"
+>>>>>>> staging
],
"MDNlinks": [
"Global Object",
@@ -176,11 +201,19 @@
"id": "a0b5010f579e69b815e7c5d6",
"title": "Search and Replace",
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(myReplace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'message: myReplace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\".');",
"assert.deepEqual(myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'message: myReplace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\".');",
"assert.deepEqual(myReplace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'message: myReplace(\"This has a spellngi error\", \"spellingi\", \"spelling\")
should return \"This has a spelling error\".');",
"assert.deepEqual(myReplace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'message: myReplace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\".');",
"assert.deepEqual(myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'message: myReplace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")
should return \"Let us get back to more Bonfires\".');"
+=======
+ "assert.deepEqual(replace(\"Let us go to the store\", \"store\", \"mall\"), \"Let us go to the mall\", 'replace(\"Let us go to the store\", \"store\", \"mall\")
should return \"Let us go to the mall\"');",
+ "assert.deepEqual(replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\"), \"He is Sitting on the couch\", 'replace(\"He is Sleeping on the couch\", \"Sleeping\", \"sitting\")
should return \"He is Sitting on the couch\"');",
+ "assert.deepEqual(replace(\"This has a spellngi error\", \"spellngi\", \"spelling\"), \"This has a spelling error\", 'replace(\"This has a spellngi error\", \"spellingi\", \"spelling\")
should return \"This has a spelling error\"');",
+ "assert.deepEqual(replace(\"His name is Tom\", \"Tom\", \"john\"), \"His name is John\", 'replace(\"His name is Tom\", \"Tom\", \"john\")
should return \"His name is John\"');",
+ "assert.deepEqual(replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\"), \"Let us get back to more Bonfires\", 'replace(\"Let us get back to more Coding\", \"Coding\", \"bonfires\")
should return \"Let us get back to more Bonfires\"');"
+>>>>>>> staging
],
"difficulty": "2.035",
"description": [
@@ -220,11 +253,19 @@
"id": "aa7697ea2477d1316795783b",
"title": "Pig Latin",
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'message: translate(\"california\")
should return \"aliforniacay\".');",
"assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'message: translate(\"paragraphs\")
should return \"aragraphspay\".');",
"assert.deepEqual(translate(\"glove\"), \"oveglay\", 'message: translate(\"glove\")
should return \"oveglay\".');",
"assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'message: translate(\"algorithm\")
should return \"algorithmway\".');",
"assert.deepEqual(translate(\"eight\"), \"eightway\", 'message: translate(\"eight\")
should return \"eightway\".');"
+=======
+ "assert.deepEqual(translate(\"california\"), \"aliforniacay\", 'translate(\"california\")
should return \"aliforniacay\"');",
+ "assert.deepEqual(translate(\"paragraphs\"), \"aragraphspay\", 'translate(\"paragraphs\")
should return \"aragraphspay\"');",
+ "assert.deepEqual(translate(\"glove\"), \"oveglay\", 'translate(\"glove\")
should return \"oveglay\"');",
+ "assert.deepEqual(translate(\"algorithm\"), \"algorithmway\", 'translate(\"algorithm\")
should return \"algorithmway\"');",
+ "assert.deepEqual(translate(\"eight\"), \"eightway\", 'translate(\"eight\")
should return \"eightway\"');"
+>>>>>>> staging
],
"difficulty": "2.04",
"description": [
@@ -318,10 +359,17 @@
"fearNotLetter(\"abce\");"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'message: fearNotLetter(\"abce\")
should return \"d\".');",
"assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'message: fearNotLetter(\"abcdefghjklmno\")
should return \"i\".');",
"assert.isUndefined(fearNotLetter(\"bcd\"), 'message: fearNotLetter(\"bcd\")
should return undefined.');",
"assert.isUndefined(fearNotLetter(\"yz\"), 'message: fearNotLetter(\"yz\")
should return undefined.');"
+=======
+ "assert.deepEqual(fearNotLetter(\"abce\"), \"d\", 'fearNotLetter(\"abce\")
should return d');",
+ "assert.deepEqual(fearNotLetter(\"abcdefghjklmno\"), \"i\", 'fearNotLetter(\"abcdefghjklmno\")
should return i');",
+ "assert.isUndefined(fearNotLetter(\"bcd\"), 'fearNotLetter(\"bcd\")
should return undefined');",
+ "assert.isUndefined(fearNotLetter(\"yz\"), 'fearNotLetter(\"yz\")
should return undefined');"
+>>>>>>> staging
],
"MDNlinks": [
"String.charCodeAt()",
@@ -524,12 +572,21 @@
"sumFibs(4);"
],
"tests": [
+<<<<<<< HEAD
"assert(typeof(sumFibs(1)) === \"number\", 'message: sumFibs()
should return a number.');",
"assert.deepEqual(sumFibs(1000), 1785, 'message: sumFibs(1000)
should return 1785.');",
"assert.deepEqual(sumFibs(4000000), 4613732, 'message: sumFibs(4000000)
should return 4613732.');",
"assert.deepEqual(sumFibs(4), 5, 'message: sumFibs(4)
should return 5.');",
"assert.deepEqual(sumFibs(75024), 60696, 'message: sumFibs(75024)
should return 60696.');",
"assert.deepEqual(sumFibs(75025), 135721, 'message: sumFibs(75025)
should return 135721.');"
+=======
+ "assert.deepEqual(typeof(sumFibs(1)), \"number\", \"The result should be a number\");",
+ "assert.deepEqual(sumFibs(1000), 1785, 'sumFibs(1000)
should return 1785');",
+ "assert.deepEqual(sumFibs(4000000), 4613732, 'sumFibs(4000000)
should return 4613732');",
+ "assert.deepEqual(sumFibs(4), 5, 'sumFibs(4)
should return 5');",
+ "assert.deepEqual(sumFibs(75024), 60696, 'sumFibs(75024)
should return 60696');",
+ "assert.deepEqual(sumFibs(75025), 135721, 'sumFibs(75025)
should return 135721');"
+>>>>>>> staging
],
"MDNlinks": [
"Remainder"
@@ -565,9 +622,15 @@
"sumPrimes(10);"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(typeof(sumPrimes(10)), \"number\", 'message: sumPrimes()
should return a number.');",
"assert.deepEqual(sumPrimes(10), 17, 'message: sumPrimes(10)
should return 17.');",
"assert.deepEqual(sumPrimes(977), 73156, 'message: sumPrimes(977)
should return 73156.');"
+=======
+ "assert.deepEqual(typeof(sumPrimes(10)), \"number\", \"The result should be a number\");",
+ "assert.deepEqual(sumPrimes(10), 17, 'sumPrimes(10)
should return 17');",
+ "assert.deepEqual(sumPrimes(977), 73156, 'sumPrimes(977)
should return 73156');"
+>>>>>>> staging
],
"MDNlinks": [
"For Loops",
@@ -605,10 +668,17 @@
"smallestCommons([1,5]);"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", 'message: smallestCommons()
should return a number.');",
"assert.deepEqual(smallestCommons([1, 5]), 60, 'message: smallestCommons([1, 5])
should return 60.');",
"assert.deepEqual(smallestCommons([5, 1]), 60, 'message: smallestCommons([5, 1])
should return 60.');",
"assert.deepEqual(smallestCommons([1, 13]), 360360, 'message: smallestCommons([1, 13])
should return 360360.');"
+=======
+ "assert.deepEqual(typeof(smallestCommons([1, 5])), \"number\", \"The result should be a number\");",
+ "assert.deepEqual(smallestCommons([1, 5]), 60, 'smallestCommons([1, 5])
should return 60');",
+ "assert.deepEqual(smallestCommons([5, 1]), 60, 'smallestCommons([5, 1])
should return 60');",
+ "assert.deepEqual(smallestCommons([1, 13]), 360360, 'smallestCommons([1, 13])
should return 360360');"
+>>>>>>> staging
],
"MDNlinks": [
"Smallest Common Multiple"
@@ -679,10 +749,17 @@
"drop([1, 2, 3], function(n) {return n < 3; });"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'message: drop([1, 2, 3, 4], function(n) {return n>= 3;})
should return [3, 4]
.');",
"assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0; }), [1, 2, 3], 'message: drop([1, 2, 3], function(n) {return n > 0; })
should return [1, 2, 3]
.');",
"assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'message: drop([1, 2, 3, 4], function(n) {return n > 5;})
should return []
.');",
"assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'message: drop([1, 2, 3, 7, 4], function(n) {return n>= 3})
should return [7, 4]
.');"
+=======
+ "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n>= 3;}), [3, 4], 'drop([1, 2, 3, 4], function(n) {return n>= 3;})
should return [3, 4]');",
+ "assert.deepEqual(drop([1, 2, 3], function(n) {return n > 0; }), [1, 2, 3], 'drop([1, 2, 3], function(n) {return n > 0; })
should return [1, 2, 3]');",
+ "assert.deepEqual(drop([1, 2, 3, 4], function(n) {return n > 5;}), [], 'drop([1, 2, 3, 4], function(n) {return n > 5;})
should return []');",
+ "assert.deepEqual(drop([1, 2, 3, 7, 4], function(n) {return n > 3}), [7, 4], 'drop([1, 2, 3, 7, 4], function(n) {return n>= 3})
should return [7, 4]');"
+>>>>>>> staging
],
"MDNlinks": [
"Arguments object",
@@ -756,8 +833,13 @@
"binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\");"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", 'message: binaryAgent(\"01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111\")
should return \"Aren't bonfires fun!?\"');",
"assert.deepEqual(binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\"), \"I love FreeCodeCamp!\", 'message: binaryAgent(\"01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001\"
should return \"I love FreeCodeCamp!\"');"
+=======
+ "assert.deepEqual(binaryAgent('01000001 01110010 01100101 01101110 00100111 01110100 00100000 01100010 01101111 01101110 01100110 01101001 01110010 01100101 01110011 00100000 01100110 01110101 01101110 00100001 00111111'), \"Aren't bonfires fun!?\", \"binaryAgent()
should return Aren't bonfires fun!?\");",
+ "assert.deepEqual(binaryAgent('01001001 00100000 01101100 01101111 01110110 01100101 00100000 01000110 01110010 01100101 01100101 01000011 01101111 01100100 01100101 01000011 01100001 01101101 01110000 00100001'), \"I love FreeCodeCamp!\", 'binaryAgent()
should return \"I love FreeCodeCamp!\"');"
+>>>>>>> staging
],
"MDNlinks": [
"String.charCodeAt()",
@@ -837,11 +919,19 @@
"add(2,3);"
],
"tests": [
+<<<<<<< HEAD
"assert.deepEqual(add(2, 3), 5, 'message: add(2, 3)
should return 5.');",
"assert.deepEqual(add(2)(3), 5, 'message: add(2)(3)
should return 5.');",
"assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'message: add(\"http://bit.ly/IqT6zt\")
should return undefined.');",
"assert.isUndefined(add(2, \"3\"), 'message: add(2, \"3\")
should return undefined.');",
"assert.isUndefined(add(2)([3]), 'message: add(2)([3])
should return undefined.');"
+=======
+ "assert.deepEqual(add(2, 3), 5, 'add(2, 3)
should return 5');",
+ "assert.deepEqual(add(2)(3), 5, 'add(2)(3)
should return 5');",
+ "assert.isUndefined(add(\"http://bit.ly/IqT6zt\"), 'add(\"http://bit.ly/IqT6zt\")
should return undefined');",
+ "assert.isUndefined(add(2, \"3\"), 'add(2, \"3\")
should return undefined');",
+ "assert.isUndefined(add(2)([3]), 'add(2)([3])
should return undefined');"
+>>>>>>> staging
],
"MDNlinks": [
"Global Function Object",
diff --git a/seed/challenges/intermediate-ziplines.json b/seed/challenges/intermediate-ziplines.json
index ae92f3879d..c119db33af 100644
--- a/seed/challenges/intermediate-ziplines.json
+++ b/seed/challenges/intermediate-ziplines.json
@@ -37,7 +37,7 @@
},
{
"id": "bd7158d8c442eddfaeb5bd19",
- "title": "Wikipedia Viewer",
+ "title": "Build a Wikipedia Viewer",
"difficulty": 1.03,
"challengeSeed": ["126415131"],
"description": [
diff --git a/seed/challenges/jquery.json b/seed/challenges/jquery.json
index 3a7b988816..95214991e4 100644
--- a/seed/challenges/jquery.json
+++ b/seed/challenges/jquery.json
@@ -791,6 +791,7 @@
"description": [
"You can also target all the even-numbered elements.",
"Here's how you would target all the odd-numbered elements with class target
and give them classes: $(\".target:odd\").addClass(\"animated shake\");
",
+ "Note that jQuery is zero-indexed, meaning that, counter-intuitively, :odd
selects the second element, fourth element, and so on.",
"Try selecting all the even-numbered elements - that is, what your browser will consider even-numbered elements - and giving them the classes of animated
and shake
."
],
"tests": [
diff --git a/server/boot/a-react.js b/server/boot/a-react.js
index 6c0cd04819..9b1f4926c9 100644
--- a/server/boot/a-react.js
+++ b/server/boot/a-react.js
@@ -1,7 +1,7 @@
import React from 'react';
-import Router from 'react-router';
+import { RoutingContext } from 'react-router';
import Fetchr from 'fetchr';
-import Location from 'react-router/lib/Location';
+import { createLocation } from 'history';
import debugFactory from 'debug';
import { app$ } from '../../common/app';
import { RenderToString } from 'thundercats-react';
@@ -30,25 +30,25 @@ export default function reactSubRouter(app) {
function serveReactApp(req, res, next) {
const services = new Fetchr({ req });
- const location = new Location(req.path, req.query);
+ const location = createLocation(req.path);
// returns a router wrapped app
- app$(location)
+ app$({ location })
// if react-router does not find a route send down the chain
- .filter(function({ initialState }) {
- if (!initialState) {
+ .filter(function({ props}) {
+ if (!props) {
debug('react tried to find %s but got 404', location.pathname);
return next();
}
- return !!initialState;
+ return !!props;
})
- .flatMap(function({ initialState, AppCat }) {
+ .flatMap(function({ props, AppCat }) {
// call thundercats renderToString
// prefetches data and sets up it up for current state
debug('rendering to string');
return RenderToString(
AppCat(null, services),
- React.createElement(Router, initialState)
+ React.createElement(RoutingContext, props)
);
})
// makes sure we only get one onNext and closes subscription
diff --git a/server/boot/challenge.js b/server/boot/challenge.js
index 15736e3a51..239d21d4d0 100644
--- a/server/boot/challenge.js
+++ b/server/boot/challenge.js
@@ -471,6 +471,7 @@ module.exports = function(app) {
}
function challengeMap({ user = {} }, res, next) {
+ let lastCompleted;
const daysRunning = moment().diff(new Date('10/15/2014'), 'days');
// if user
@@ -513,7 +514,13 @@ module.exports = function(app) {
})
.filter(({ name }) => name !== 'Hikes')
// turn stream of blocks into a stream of an array
- .toArray();
+ .toArray()
+ .doOnNext((blocks) => {
+ const lastCompletedBlock = _.findLast(blocks, (block) => {
+ return block.completed === 100;
+ });
+ lastCompleted = lastCompletedBlock.name;
+ });
Observable.combineLatest(
camperCount$,
@@ -526,6 +533,7 @@ module.exports = function(app) {
blocks,
daysRunning,
camperCount,
+ lastCompleted,
title: "A map of all Free Code Camp's Challenges"
});
},
diff --git a/server/boot/story.js b/server/boot/story.js
index 02b92e93b3..d46b79f079 100755
--- a/server/boot/story.js
+++ b/server/boot/story.js
@@ -170,7 +170,6 @@ module.exports = function(app) {
title: story.headline,
link: story.link,
originalStoryLink: dashedName,
- originalStoryAuthorEmail: story.author.email || '',
author: story.author,
rank: story.upVotes.length,
upVotes: story.upVotes,
@@ -373,13 +372,11 @@ module.exports = function(app) {
author: {
picture: req.user.picture,
userId: req.user.id,
- username: req.user.username,
- email: req.user.email
+ username: req.user.username
},
image: data.image,
storyLink: storyLink,
- metaDescription: data.storyMetaDescription,
- originalStoryAuthorEmail: req.user.email
+ metaDescription: data.storyMetaDescription
});
return saveInstance(newStory);
});
diff --git a/server/boot/user.js b/server/boot/user.js
index 33a80c5c62..9c6450db9c 100644
--- a/server/boot/user.js
+++ b/server/boot/user.js
@@ -76,6 +76,8 @@ module.exports = function(app) {
);
router.get('/account/unlink/:provider', getOauthUnlink);
router.get('/account', getAccount);
+ router.get('/vote1', vote1);
+ router.get('/vote2', vote2);
// Ensure this is the last route!
router.get('/:username', returnUser);
@@ -332,4 +334,36 @@ module.exports = function(app) {
});
});
}
+
+ function vote1(req, res) {
+ if (req.user) {
+ req.user.tshirtVote = 1;
+ req.user.save(function (err) {
+ if (err) {
+ return next(err);
+ }
+ req.flash('success', {msg: 'Thanks for voting!'});
+ res.redirect('/map');
+ });
+ } else {
+ req.flash('error', {msg: 'You must be signed in to vote.'});
+ res.redirect('/map');
+ }
+ }
+
+ function vote2(req, res) {
+ if (req.user) {
+ req.user.tshirtVote = 2;
+ req.user.save(function (err) {
+ if (err) {
+ return next(err);
+ }
+ req.flash('success', {msg: 'Thanks for voting!'});
+ res.redirect('/map');
+ });
+ } else {
+ req.flash('error', {msg: 'You must be signed in to vote.'});
+ res.redirect('/map');
+ }
+ }
};
diff --git a/server/middlewares/add-return-to.js b/server/middlewares/add-return-to.js
index 59163d42da..6771c38481 100644
--- a/server/middlewares/add-return-to.js
+++ b/server/middlewares/add-return-to.js
@@ -26,13 +26,12 @@ export default function addReturnToUrl() {
return function(req, res, next) {
// Remember original destination before login.
var path = req.path.split('/')[1];
- var subPath = req.path.split('/')[2];
if (
req.method !== 'GET' ||
pathsOfNoReturnRegex.test(path) ||
!whiteListRegex.test(path) ||
- (/news/i).test(path) && (/hot/i).test(subPath)
+ (/news/i).test(path) && (/hot/i).test(req.path)
) {
return next();
}
diff --git a/server/views/challengeMap/show.jade b/server/views/challengeMap/show.jade
index 05d591b010..42fa90422b 100644
--- a/server/views/challengeMap/show.jade
+++ b/server/views/challengeMap/show.jade
@@ -17,7 +17,36 @@ block content
| since we launched
span.text-primary #{daysRunning}
| days ago.
- a.btn.btn-lg.signup-btn.btn-block(href="https://www.facebook.com/sharer/sharer.php?u=http://freecodecamp.com" target='_blank') Share our open source community on Facebook and help us grow.
+ .spacer
+ if (user && !user.tshirtVote && user.progressTimestamps.length > 5)
+ h3.text-center Vote for the T-shirt design you like the most.
+ h4.text-center We'll announce the winning design during our Summit on Saturday at Noon EST on
+ a(href='https://twitch.tv/freecodecamp' target='_blank') Twitch.tv
+ | and it will become our community's first official t-shirt (in women's and men's sizes).
+ .row
+ .col-xs-6
+ a(href="http://i.imgur.com/LlXGa5y.png" data-lightbox="img-enlarge")
+ img.img-responsive(src='http://i.imgur.com/LlXGa5y.png' alt="t-shirt option 1 women's")
+ .col-xs-6
+ a(href="http://i.imgur.com/aefwnnv.png" data-lightbox="img-enlarge")
+ img.img-responsive(src='http://i.imgur.com/aefwnnv.png' alt="t-shirt option 2 women's")
+ .button-spacer
+ .row
+ .col-xs-6
+ a(href="http://i.imgur.com/aYH0aqf.png" data-lightbox="img-enlarge")
+ img.img-responsive(src='http://i.imgur.com/aYH0aqf.png' alt="t-shirt option 1 men's")
+ .col-xs-6
+ a(href="http://i.imgur.com/v9KlV4g.png" data-lightbox="img-enlarge")
+ img.img-responsive(src='http://i.imgur.com/v9KlV4g.png' alt="t-shirt option 2 men's")
+ .button-spacer
+ .row
+ .col-xs-6
+ h3.text-center "Minified JavaScript Logo"
+ a.button.btn.btn-block.btn-primary(href='/vote1') Vote for this Design
+ .col-xs-6
+ h3.text-center "Function Call Logo"
+ a.button.btn.btn-block.btn-primary(href='/vote2') Vote for this design
+ .spacer
.row
.col-xs-12.col-sm-8.col-sm-offset-2
h3 800 Hours of Practice:
@@ -102,7 +131,16 @@ block content
span= challenge.title
span.sr-only= " Incomplete"
- //#announcementModal.modal(tabindex='-1')
+ if (challengeBlock.completed === 100)
+ .button-spacer
+ .row
+ .col-xs-12.col-sm-8.col-md-6.col-sm-offset-3.col-md-offset-2.hidden
+ a.btn.btn-lg.btn-block.signup-btn.map-challenge-block-share Section complete. Share your Portfolio with your friends.
+ .hidden(id="#{challengeBlock.name}")
+ script.
+ var username = !{JSON.stringify(user && user.username || '')};
+ var lastCompleted = !{JSON.stringify(lastCompleted || false)}
+ // #announcementModal.modal(tabindex='-1')
// .modal-dialog.animated.fadeInUp.fast-animation
// .modal-content
// .modal-header.challenge-list-header Add us to your LinkedIn profile
diff --git a/server/views/coursewares/showBonfire.jade b/server/views/coursewares/showBonfire.jade
index 084fd03d4b..e64424e1ac 100644
--- a/server/views/coursewares/showBonfire.jade
+++ b/server/views/coursewares/showBonfire.jade
@@ -55,9 +55,6 @@ block content
label.btn.btn-success#trigger-help-modal
i.fa.fa-medkit
| Help
- label.btn.btn-success#trigger-pair-modal
- i.fa.fa-user-plus
- | Pair
label.btn.btn-success#trigger-issue-modal
i.fa.fa-bug
| Bug
diff --git a/server/views/coursewares/showJS.jade b/server/views/coursewares/showJS.jade
index 03d6b823e1..f4621b5b28 100644
--- a/server/views/coursewares/showJS.jade
+++ b/server/views/coursewares/showJS.jade
@@ -94,10 +94,6 @@ block content
.row
if (user)
#submit-challenge.animated.fadeIn.btn.btn-lg.btn-primary.btn-block Submit and go to my next challenge (ctrl + enter)
- if (user.progressTimestamps.length > 2)
- a.btn.btn-lg.btn-block.btn-twitter(target="_blank", href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript")
- i.fa.fa-twitter
- = phrase
else
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) Go to my next challenge
include ../partials/challenge-modals
diff --git a/server/views/coursewares/showVideo.jade b/server/views/coursewares/showVideo.jade
index 30ad2d5f1a..bd7f42e5ed 100644
--- a/server/views/coursewares/showVideo.jade
+++ b/server/views/coursewares/showVideo.jade
@@ -69,12 +69,6 @@ block content
a.btn.btn-lg.btn-primary.btn-block#next-courseware-button(name='_csrf', value=_csrf) I've completed this challenge (ctrl + enter)
script.
$('#complete-courseware-editorless-dialog').bind('keypress', modalControlEnterHandler);
-
- if (user.progressTimestamps.length > 2)
- .button-spacer
- a.btn.btn-lg.btn-block.btn-twitter(href="https://twitter.com/intent/tweet?text=I%20just%20#{verb}%20%40FreeCodeCamp%20#{name}&url=http%3A%2F%2Ffreecodecamp.com/challenges/#{dashedName}&hashtags=LearnToCode, JavaScript" target="_blank")
- i.fa.fa-twitter
- = phrase
else
a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block(href='/challenges/next-challenge?id=' + challengeId) I've completed this challenge (ctrl + enter)
script.
diff --git a/server/views/coursewares/showZiplineOrBasejump.jade b/server/views/coursewares/showZiplineOrBasejump.jade
index 58f84f1c77..174be42e3e 100644
--- a/server/views/coursewares/showZiplineOrBasejump.jade
+++ b/server/views/coursewares/showZiplineOrBasejump.jade
@@ -27,9 +27,6 @@ block content
.btn.btn-success.btn-big#trigger-help-modal
i.fa.fa-medkit
| Help
- .btn.btn-success.btn-big#trigger-pair-modal
- i.fa.fa-user-plus
- | Pair
.btn.btn-success.btn-big#trigger-issue-modal
i.fa.fa-bug
| Bug
diff --git a/server/views/partials/challenge-modals.jade b/server/views/partials/challenge-modals.jade
index 4503e2ac17..746c1a6929 100644
--- a/server/views/partials/challenge-modals.jade
+++ b/server/views/partials/challenge-modals.jade
@@ -1,17 +1,3 @@
-#pair-modal.modal(tabindex='-1')
- .modal-dialog.animated.fadeIn.fast-animation
- .modal-content
- .modal-header.challenge-list-header Ready to pair program?
- a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') ×
- .modal-body.text-center
- h3 This will take you to our pair programming room where you can request a pair.
- h3 You'll need
- a(href='//github.com/FreeCodeCamp/freecodecamp/wiki/How-to-install-Screenhero' target='_blank') Screenhero
- | .
- h3 Other campers may then message you about pair programming.
- a.btn.btn-lg.btn-primary.btn-block.close-modal(href='https://gitter.im/FreeCodeCamp/LetsPair', target='_blank') Take me to the pair programming room
- a.btn.btn-lg.btn-info.btn-block(href='#', data-dismiss='modal', aria-hidden='true') Cancel
-
#issue-modal.modal(tabindex='-1')
.modal-dialog.animated.fadeIn.fast-animation
.modal-content
diff --git a/server/views/resources/get-started.jade b/server/views/resources/get-started.jade
index a3d19984f8..8767841a66 100644
--- a/server/views/resources/get-started.jade
+++ b/server/views/resources/get-started.jade
@@ -65,7 +65,7 @@ block content
.big-spacer
.thumbnail
- img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EZHzKCV.gif' alt='A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.')
+ img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Uuc2Ked.gif' alt='A gif showing you how to click the link below to go to our chat room and click the \"sign in with GitHub\" button. Then you can click into the text input field and type a message to your fellow campers.')
.caption
p.large-p Try this:
| Now that you have a GitHub account, you can
@@ -99,12 +99,6 @@ block content
a(href='https://gitter.im/apps' target='_blank') download the chat room app
| to your computer or phone.
- .big-spacer
- .thumbnail
- img.gif-block.img-center.img-responsive(src='http://i.imgur.com/DoOqkNW.gif' alt='A gif showing how you can click the "Wiki" button in your upper-right corner to access the wiki.')
- .caption
- p.large-p Try this: Click the "Wiki" button in your upper right hand corner. Our community has contributed lots of useful information to this searchable wiki.
-
.big-spacer
.thumbnail
img.gif-block.img-center.img-responsive(src='http://i.imgur.com/FkEzbto.gif' alt='A gif showing how you can click your profile image in your upper right hand corner to access the account page and connect GitHub.')
@@ -128,25 +122,15 @@ block content
.thumbnail
img.gif-block.img-center.img-responsive(src='http://i.imgur.com/Elb3dfj.jpg' alt='A picture of some of our campers meeting in a local cafe. 3 men and 3 women are sitting around a table with laptops out, and are smiling and coding.')
.caption
- p.large-p Our Campsites help you code with campers in your city. You can coordinate study groups or attend local coding events together.
+ p.large-p Our Campsites help you code with campers in your city. You can discuss coding and attend local Coffee-n-Code events.
.big-spacer
.thumbnail
- img.gif-block.img-center.img-responsive(src='http://i.imgur.com/EZHzKCV.gif' alt="A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.")
+ img.gif-block.img-center.img-responsive(src='http://i.imgur.com/tYf8jrI.gif' alt="A gif showing how you can click the link below, find your city on the list of Campsites, then click on the Facebook link for your city and join your city's Facebook group.")
.caption
p.large-p Try this:
a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Find your city on this list
- | . Click the "Join group" button to join your city's Facebook group. If your city isn't on this list,
- a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/How-to-create-a-Campsite-for-your-city' target='_blank') follow these directions to create a Facebook group for your city
- | .
-
- .big-spacer
- .thumbnail
- img.gif-block.img-center.img-responsive(src='http://i.imgur.com/3AgvJQg.gif' alt="A gif showing how click the link below, find your city, and click the \"Gitter\" button to join your city's Gitter chat room")
- .caption
- p.large-p Try this:
- a(href='https://github.com/FreeCodeCamp/freecodecamp/wiki/List-of-Free-Code-Camp-city-based-Campsites' target='_blank') Go back to our list of Campsites
- | and click "Gitter" to join your city's chat room.
+ | , then click it. Click the "Join group" button to join your city's Campsite.
.big-spacer
.thumbnail
diff --git a/server/views/stories/show.jade b/server/views/stories/show.jade
index 20c6346e01..cced0f41f5 100644
--- a/server/views/stories/show.jade
+++ b/server/views/stories/show.jade
@@ -1,7 +1,6 @@
script.
var storyId = !{JSON.stringify(id)};
var originalStoryLink = !{JSON.stringify(originalStoryLink)};
- var originalStoryAuthorEmail = !{JSON.stringify(originalStoryAuthorEmail)};
var upVotes = !{JSON.stringify(upVotes)};
var image = !{JSON.stringify(image)};
var hasUserVoted = !{JSON.stringify(hasUserVoted)};