diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index ea5084d13a..798213cf41 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,5 @@ - @@ -23,8 +22,9 @@ ```js + + ``` - #### Screenshot diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 65a6a27838..98abfe73b2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,7 +10,7 @@ - [ ] Your pull request targets the `staging` branch of FreeCodeCamp. - [ ] Branch starts with either `fix/`, `feature/`, or `translate/` (e.g. `fix/signin-issue`) -- [ ] You have only one commit (if not, [squash](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Git-Squash) them into one commit). +- [ ] You have only one commit (if not, [squash](http://forum.freecodecamp.com/t/how-to-squash-multiple-commits-into-one-with-git/13231) them into one commit). - [ ] All new and existing tests pass the command `npm run test-challenges`. Use `git commit --amend` to amend any fixes. #### Type of Change @@ -28,4 +28,3 @@ #### Description - diff --git a/.varci.yml b/.varci.yml new file mode 100644 index 0000000000..f173bd5759 --- /dev/null +++ b/.varci.yml @@ -0,0 +1,22 @@ +ruleset: + label_and_comment_help_questions: + name: "Label & comment on issues with help in title or description" + events: [ issues ] + label: question + when: + - title matches "/help/i" or body matches "/help/i" + - action = "opened" or action = "reopened" + comment: > + Hi @{{ user.login }} + + + The issue tracker is for reporting bugs only. If this is a request + for help with a challenge, please use the [help chat room](https://gitter.im/FreeCodeCamp/Help) + or try looking through the [forum](http://forum.freecodecamp.com/c/free-code-camp) for help + with a specific challenge. + + + If this is the case, please close this issue. + + + Happy Coding. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e633fa8ec9..76ebc2b554 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ If you've found a bug that is not on the board, [follow these steps](#found-a-bu ### Contribution Guidelines 1. Fork the project: [How To Fork And Maintain a Local Instance of Free Code - Camp](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/FreeCodeCamp-Fork-Local) + Camp](http://forum.freecodecamp.com/t/how-to-fork-and-maintain-a-local-instance-of-free-code-camp/19116) 2. Create a branch specific to the issue or feature you are working on. Push your work to that branch. ([Need help with @@ -47,10 +47,10 @@ If you've found a bug that is not on the board, [follow these steps](#found-a-bu run by using `npm run test-challenges`, as jsonlint will always fail on Windows, given the wildcard parameters. -6. Squash your Commits. Ref: [rebasing](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/git-rebase) +6. Squash your Commits. Ref: [rebasing](http://forum.freecodecamp.com/t/how-to-use-git-rebase/13226) 7. Submit a [pull - request](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Pull-Request-Contribute) + request](http://forum.freecodecamp.com/t/how-to-make-a-pull-request-on-free-code-camp/19114) from your branch to Free Code Camp's `staging` branch. [Travis CI](https://travis-ci.org/FreeCodeCamp/FreeCodeCamp) will then take your code and run `npm test`. Make sure this passes, then we'll do a quick code @@ -142,7 +142,7 @@ issue and with your error. You should have [ESLint running in your editor](http://eslint.org/docs/user-guide/integrations.html), and it will highlight anything doesn't conform to [Free Code Camp's JavaScript Style -Guide](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Free-Code-Camp-JavaScript-Style-Guide) +Guide](http://forum.freecodecamp.com/t/free-code-camp-javascript-style-guide/19121) (you can find a summary of those rules [here](https://github.com/FreeCodeCamp/FreeCodeCamp/blob/staging/.eslintrc). Please do not ignore any linting errors, as they are meant to **help** you and @@ -156,10 +156,10 @@ does not fully support wildcard paths in Windows. Do not file an issue until you have followed these steps: 1. Read [Help I've Found a - Bug](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/FreeCodeCamp-Report-Bugs) + Bug](http://forum.freecodecamp.com/t/how-to-report-a-bug/19543) wiki page and follow the instructions there. -2. Asked for confirmation in the appropriate [Help Room](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Help-Rooms) +2. Asked for confirmation in the appropriate [Help Room](http://forum.freecodecamp.com/t/free-code-camp-official-chat-rooms/19390/2) 3. Please _do not_ open an issue without a 3rd party confirmation of your problem. @@ -240,7 +240,7 @@ possible to update your fork via GitHub's interface without deleting and recreating your fork. Read the [Wiki -article](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/How-To-Create-A-Pull-Request-for-Free-Code-Camp#editing-via-the-github-interface) +article](http://forum.freecodecamp.com/t/how-to-make-a-pull-request-on-free-code-camp/19114) for further information ### Common Steps @@ -252,7 +252,7 @@ for further information branch. 3. Submit a [pull - request](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Pull-Request-Contribute) + request](http://forum.freecodecamp.com/t/how-to-contribute-via-a-pull-request/19368) from your branch to Free Code Camp's `staging` branch. 4. The title (also called the subject) of your PR should be descriptive of your @@ -303,22 +303,22 @@ Be sure to post in the PR conversation that you have made the requested changes. ### Other resources - [Searching for Your Issue on - GitHub](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Search-Existing-Issues) + GitHub](http://forum.freecodecamp.com/t/searching-for-existing-issues/19139) - [Creating a New GitHub - Issue](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Creating-a-New-GitHub-Issue) + Issue](http://forum.freecodecamp.com/t/creating-a-new-github-issue/18392) - [Select Issues for Contributing Using - Labels](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/FreeCodeCamp-Issue-Labels) + Labels](http://forum.freecodecamp.com/t/free-code-camp-issue-labels/19556) - [How to clone the FreeCodeCamp website on a Windows - pc](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/FreeCodeCamp-Fork-Windows) + pc](http://forum.freecodecamp.com/t/how-to-clone-and-setup-the-free-code-camp-website-on-a-windows-pc/19366) - [How to log in to your local FCC site - using - GitHub](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/FreeCodeCamp-Log-In-To-Local-Instance) + GitHub](http://forum.freecodecamp.com/t/how-to-log-in-to-your-local-instance-of-free-code-camp/19552) - [Writing great git commit - message](https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/Git-Commit-Message) + message](http://forum.freecodecamp.com/t/writing-good-git-commit-messages/13210) - [Contributor Chat Support - For the FCC Repositories, and running a local instance](https://gitter.im/FreeCodeCamp/HelpContributors) diff --git a/client/commonFramework/bindings.js b/client/commonFramework/bindings.js index 7c3c8d382e..e2165848bc 100644 --- a/client/commonFramework/bindings.js +++ b/client/commonFramework/bindings.js @@ -191,8 +191,7 @@ window.common = (function(global) { $('#help-ive-found-a-bug-wiki-article').on('click', function() { window.open( - 'https://github.com/FreeCodeCamp/FreeCodeCamp/wiki/' + - 'FreeCodeCamp-Report-Bugs', + 'http://forum.freecodecamp.com/t/how-to-report-a-bug/19543', '_blank' ); }); diff --git a/client/less/challenge.less b/client/less/challenge.less index 262277f458..ceaf40c2a8 100644 --- a/client/less/challenge.less +++ b/client/less/challenge.less @@ -1,6 +1,10 @@ -.challenges-editor { - height: 100%; - width: 99%; +.challenges-instructions-panel { + clear: both; + overflow-x: hidden; + overflow-y: auto; + padding-left: 5px; + padding-right: 5px; + margin-bottom: 10px; } .challenge-step-description { @@ -135,38 +139,6 @@ color: @alert-info-bg; } -iframe.iphone { - border: none; - @media(min-width: 992px) { - width: 280px; - height: 500px; - position: absolute; - top: 70px; - right: 35px; - overflow-y: scroll; - } - @media(max-width: 991px) { - width: 100%; - border-radius: 5px; - overflow-y: visible; - height: 500px; - } - @media (min-width: 1200px) and (max-width: 1250px){ - right: 22px; - } -} - -// To adjust right margin, negative values bring the image closer to the edge of the screen -.iphone-position { - position: absolute; - top: -45px; - z-index: -1; - right: -195px; - @media (min-width: 1200px) and (max-width: 1250px){ - right: -207px; - } -} - .night { .challenge-instructions blockquote { background-color: #242424; @@ -191,3 +163,58 @@ iframe.iphone { } } } + +.challenges-editor { + height: auto; + width: 100%; + overflow-y: auto; +} + +.challenges-preview { + clear: both; + overflow: hidden; +} + +@media only screen and (min-width: 993px) { + .iframe-scroll { + z-index: 1; + } +} +@media only screen and (max-width: 992px) { + .iframe-scroll { + height: auto; + overflow: auto; + } +} + +iframe.iphone { + border: none; + @media(min-width: 992px) { + width: 280px; + height: 497px; + position: absolute; + top: 75px; + right: 35px; + overflow-y: scroll; + } + @media(max-width: 991px) { + width: 100%; + border-radius: 5px; + overflow-y: visible; + height: 500px; + } + @media (min-width: 1200px) and (max-width: 1250px){ + right: 22px; + } +} + +// To adjust right margin, negative values bring the image closer to the edge of the screen +.iphone-position { + position: absolute; + top: -45px; + z-index: -1; + right: -195px; + @media (min-width: 1200px) and (max-width: 1250px){ + right: -207px; + } +} \ No newline at end of file diff --git a/client/less/drawers.less b/client/less/drawers.less index aa256ab9ae..102e412154 100644 --- a/client/less/drawers.less +++ b/client/less/drawers.less @@ -44,6 +44,22 @@ width: 100%; height: 100%; } + + h2 > a { + font-size: 20px; + } + a > h3 { + font-size: 18px; + font-weight: bold; + } + p { + font-size: 16px; + margin-left: 32px !important; + } + > .challenge-block-time { + width: 100%; + padding-top: 5px; + } } .drawer-content { @@ -110,3 +126,13 @@ .drawer-action-collapse { background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNzEuNDI5IDE3MS40MjkiIGZpbGw9IiMzYTMxMzMiPjxwYXRoIGQ9Ik0xMjIuNDMzLDEwNi4xMzhsLTE2LjI5NSwxNi4yOTVjLTAuNzQ0LDAuNzQ0LTEuNiwxLjExNi0yLjU2NiwxLjExNmMtMC45NjgsMC0xLjgyMy0wLjM3Mi0yLjU2Ny0xLjExNmwtMTUuMjktMTUuMjkgbC0xNS4yOSwxNS4yOWMtMC43NDQsMC43NDQtMS42LDEuMTE2LTIuNTY3LDEuMTE2cy0xLjgyMy0wLjM3Mi0yLjU2Ny0xLjExNmwtMTYuMjk0LTE2LjI5NWMtMC43NDQtMC43NDQtMS4xMTYtMS42LTEuMTE2LTIuNTY2IGMwLTAuOTY4LDAuMzcyLTEuODIzLDEuMTE2LTIuNTY3bDE1LjI5LTE1LjI5bC0xNS4yOS0xNS4yOWMtMC43NDQtMC43NDQtMS4xMTYtMS42LTEuMTE2LTIuNTY3czAuMzcyLTEuODIzLDEuMTE2LTIuNTY3IEw2NS4yOSw0OC45OTZjMC43NDQtMC43NDQsMS42LTEuMTE2LDIuNTY3LTEuMTE2czEuODIzLDAuMzcyLDIuNTY3LDEuMTE2bDE1LjI5LDE1LjI5bDE1LjI5LTE1LjI5IGMwLjc0NC0wLjc0NCwxLjYtMS4xMTYsMi41NjctMS4xMTZjMC45NjcsMCwxLjgyMiwwLjM3MiwyLjU2NiwxLjExNmwxNi4yOTUsMTYuMjk0YzAuNzQ0LDAuNzQ0LDEuMTE2LDEuNiwxLjExNiwyLjU2NyBzLTAuMzcyLDEuODIzLTEuMTE2LDIuNTY3bC0xNS4yOSwxNS4yOWwxNS4yOSwxNS4yOWMwLjc0NCwwLjc0NCwxLjExNiwxLjYsMS4xMTYsMi41NjcgQzEyMy41NDksMTA0LjUzOSwxMjMuMTc3LDEwNS4zOTQsMTIyLjQzMywxMDYuMTM4eiBNMTQ2LjQyOSw4NS43MTRjMC0xMS4wMTItMi43MTctMjEuMTY4LTguMTQ4LTMwLjQ2OSBzLTEyLjc5Ny0xNi42NjctMjIuMDk4LTIyLjA5OFM5Ni43MjYsMjUsODUuNzE0LDI1cy0yMS4xNjgsMi43MTYtMzAuNDY5LDguMTQ3UzM4LjU3OSw0NS45NDUsMzMuMTQ3LDU1LjI0NlMyNSw3NC43MDMsMjUsODUuNzE0IHMyLjcxNiwyMS4xNjgsOC4xNDcsMzAuNDY5czEyLjc5NywxNi42NjYsMjIuMDk4LDIyLjA5OHMxOS40NTcsOC4xNDgsMzAuNDY5LDguMTQ4czIxLjE2OC0yLjcxNywzMC40NjktOC4xNDggczE2LjY2Ni0xMi43OTcsMjIuMDk4LTIyLjA5OFMxNDYuNDI5LDk2LjcyNiwxNDYuNDI5LDg1LjcxNHogTTE3MS40MjksODUuNzE0YzAsMTUuNTUxLTMuODMyLDI5Ljg5My0xMS40OTYsNDMuMDI0IGMtNy42NjQsMTMuMTMzLTE4LjA2MiwyMy41My0zMS4xOTQsMzEuMTk0Yy0xMy4xMzIsNy42NjQtMjcuNDc0LDExLjQ5Ni00My4wMjQsMTEuNDk2cy0yOS44OTItMy44MzItNDMuMDI0LTExLjQ5NiBjLTEzLjEzMy03LjY2NC0yMy41MzEtMTguMDYyLTMxLjE5NC0zMS4xOTRDMy44MzIsMTE1LjYwNywwLDEwMS4yNjUsMCw4NS43MTRTMy44MzIsNTUuODIyLDExLjQ5Niw0Mi42OSBjNy42NjQtMTMuMTMzLDE4LjA2Mi0yMy41MzEsMzEuMTk0LTMxLjE5NEM1NS44MjIsMy44MzIsNzAuMTY0LDAsODUuNzE0LDBzMjkuODkzLDMuODMyLDQzLjAyNCwxMS40OTYgYzEzLjEzMyw3LjY2NCwyMy41MywxOC4wNjIsMzEuMTk0LDMxLjE5NEMxNjcuNTk3LDU1LjgyMiwxNzEuNDI5LDcwLjE2NCwxNzEuNDI5LDg1LjcxNHoiLz48L3N2Zz4=) } + +.night { + .drawer { + background-color: @night-body-bg; + } + .drawer-action-item{ + filter: brightness(4) saturate(0); + -webkit-filter: brightness(4) saturate(0); + } +} diff --git a/client/less/main.less b/client/less/main.less index 7839a7ea92..334356617d 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -69,7 +69,11 @@ body.no-top-and-bottom-margins { body.react-layout { margin-top: 75px; - margin-bottom: 0px; + margin-bottom: 15px; + width: auto; + padding-left: 15px; + padding-right: 15px; + min-height: 650px; } h1, h2 { @@ -906,18 +910,6 @@ code { padding: 1px 5px; } -@media only screen and (min-width: 993px) { - .iframe-scroll { - z-index: 1; - } -} -@media only screen and (max-width: 992px) { - .iframe-scroll { - height: auto; - overflow: auto; - } -} - // Calculator styles .chart rect { diff --git a/client/less/map.less b/client/less/map.less index 89bd78f43f..3a2311aa28 100644 --- a/client/less/map.less +++ b/client/less/map.less @@ -118,19 +118,10 @@ cursor: pointer; } - a { - margin:15px 0; - padding:0; - - &:first-child { - margin-top:25px - } - - > h3 { - padding-left: 40px; - padding-bottom: 10px; - display: block; - } + a > h3 { + padding-left: 40px; + padding-bottom: 10px; + display: block; } .map-accordion-block { diff --git a/client/sagas/execute-challenge-saga.js b/client/sagas/execute-challenge-saga.js index 96b7c6e566..247502a910 100644 --- a/client/sagas/execute-challenge-saga.js +++ b/client/sagas/execute-challenge-saga.js @@ -79,7 +79,7 @@ function cacheLink({ link } = {}, crossDomain = true) { const htmlCatch = '\n'; -const jsCatch = '\n;/*fcc*/'; +const jsCatch = '\n;/*fcc*/\n'; export default function executeChallengeSaga(action$, getState) { const frameRunner$ = cacheScript( @@ -103,14 +103,19 @@ export default function executeChallengeSaga(action$, getState) { // createbuild .flatMap(file$ => file$.reduce((build, file) => { let finalFile; + const finalContents = [ + file.head, + file.contents, + file.tail + ]; if (file.ext === 'js') { finalFile = setExt('html', updateContents( - ``, + ``, file )); } else if (file.ext === 'css') { finalFile = setExt('html', updateContents( - ``, + ``, file )); } else { @@ -125,6 +130,13 @@ export default function executeChallengeSaga(action$, getState) { if (required.src) { return cacheScript(required, required.crossDomain); } + // css files with `url(...` may not work in style tags + // so we put them in raw links + if (required.link && required.raw) { + return Observable.just( + `` + ); + } if (required.link) { return cacheLink(required, required.crossDomain); } @@ -136,7 +148,7 @@ export default function executeChallengeSaga(action$, getState) { return Observable.combineLatest(head$, frameRunner$) .map(([ head, frameRunner ]) => { const body = ` - + ${source} diff --git a/client/sagas/index.js b/client/sagas/index.js index ec4074af58..13e755f9fa 100644 --- a/client/sagas/index.js +++ b/client/sagas/index.js @@ -8,6 +8,7 @@ import codeStorageSaga from './code-storage-saga'; import gitterSaga from './gitter-saga'; import mouseTrapSaga from './mouse-trap-saga'; import analyticsSaga from './analytics-saga'; +import nightModeSaga from './night-mode-saga'; export default [ errSaga, @@ -19,5 +20,6 @@ export default [ codeStorageSaga, gitterSaga, mouseTrapSaga, - analyticsSaga + analyticsSaga, + nightModeSaga ]; diff --git a/client/sagas/night-mode-saga.js b/client/sagas/night-mode-saga.js new file mode 100644 index 0000000000..efc5e9d5c9 --- /dev/null +++ b/client/sagas/night-mode-saga.js @@ -0,0 +1,47 @@ +import { Observable } from 'rx'; +import { postJSON$ } from '../../common/utils/ajax-stream'; +import types from '../../common/app/redux/types'; +import { + addThemeToBody, + updateTheme, + createErrorObservable +} from '../../common/app/redux/actions'; + +export default function nightModeSaga( + actions, + getState, + { document: { body } } +) { + const toggleBodyClass = actions + .filter(({ type }) => types.addThemeToBody === type) + .doOnNext(({ payload: theme }) => { + if (theme === 'night') { + body.classList.add('night'); + } else { + body.classList.remove('night'); + } + }) + .filter(() => false); + const toggle = actions + .filter(({ type }) => types.toggleNightMode === type); + + const optimistic = toggle + .flatMap(() => { + const { app: { theme } } = getState(); + const newTheme = !theme || theme === 'default' ? 'night' : 'default'; + return Observable.of( + updateTheme(newTheme), + addThemeToBody(newTheme) + ); + }); + + const ajax = toggle + .debounce(250) + .flatMapLatest(() => { + const { app: { theme, csrfToken: _csrf } } = getState(); + return postJSON$('/update-my-theme', { _csrf, theme }) + .catch(createErrorObservable); + }); + + return Observable.merge(optimistic, toggleBodyClass, ajax); +} diff --git a/common/app/App.jsx b/common/app/App.jsx index 28ec870e0c..de4fb7722d 100644 --- a/common/app/App.jsx +++ b/common/app/App.jsx @@ -11,7 +11,8 @@ import { toggleMapDrawer, toggleMainChat, updateAppLang, - trackEvent + trackEvent, + loadCurrentChallenge } from './redux/actions'; import { submitChallenge } from './routes/challenges/redux/actions'; @@ -28,7 +29,8 @@ const bindableActions = { toggleMapDrawer, toggleMainChat, updateAppLang, - trackEvent + trackEvent, + loadCurrentChallenge }; const mapStateToProps = createSelector( @@ -80,7 +82,8 @@ export class FreeCodeCamp extends React.Component { shouldShowSignIn: PropTypes.bool, params: PropTypes.object, updateAppLang: PropTypes.func.isRequired, - trackEvent: PropTypes.func.isRequired + trackEvent: PropTypes.func.isRequired, + loadCurrentChallenge: PropTypes.func.isRequired }; componentWillReceiveProps(nextProps) { @@ -124,7 +127,8 @@ export class FreeCodeCamp extends React.Component { toggleMainChat, shouldShowSignIn, params: { lang }, - trackEvent + trackEvent, + loadCurrentChallenge } = this.props; const navProps = { isOnMap: router.isActive(`/${lang}/map`), @@ -135,7 +139,8 @@ export class FreeCodeCamp extends React.Component { toggleMapDrawer, toggleMainChat, shouldShowSignIn, - trackEvent + trackEvent, + loadCurrentChallenge }; return ( diff --git a/common/app/components/Nav/Nav.jsx b/common/app/components/Nav/Nav.jsx index a3c60b4894..d902c72b45 100644 --- a/common/app/components/Nav/Nav.jsx +++ b/common/app/components/Nav/Nav.jsx @@ -10,21 +10,11 @@ import { } from 'react-bootstrap'; import navLinks from './links.json'; -import FCCNavItem from './NavItem.jsx'; +import PointsNavItem from './Points-Nav-Item.jsx'; import AvatarNavItem from './Avatar-Nav-Item.jsx'; const fCClogo = 'https://s3.amazonaws.com/freecodecamp/freecodecamp_logo.svg'; -const logoElement = ( - - learn to code javascript at Free Code Camp logo - -); - const toggleButtonChild = ( Menu @@ -43,6 +33,7 @@ export default class extends React.Component { constructor(...props) { super(...props); this.handleMapClickOnMap = this.handleMapClickOnMap.bind(this); + this.handleLogoClick = this.handleLogoClick.bind(this); navLinks.forEach(({ content }) => { this[`handle${content}Click`] = handleNavLinkEvent.bind(this, content); }); @@ -58,7 +49,8 @@ export default class extends React.Component { toggleMapDrawer: PropTypes.func, toggleMainChat: PropTypes.func, shouldShowSignIn: PropTypes.bool, - trackEvent: PropTypes.func.isRequired + trackEvent: PropTypes.func.isRequired, + loadCurrentChallenge: PropTypes.func.isRequired }; componentDidMount() { @@ -83,6 +75,11 @@ export default class extends React.Component { }); } + handleLogoClick(e) { + e.preventDefault(); + this.props.loadCurrentChallenge(); + } + renderMapLink(isOnMap, toggleMapDrawer) { if (isOnMap) { return ( @@ -176,9 +173,10 @@ export default class extends React.Component { key='points' to='/settings' > - - [ { points } ] - + ); } @@ -218,7 +216,18 @@ export default class extends React.Component { className='nav-height' fixedTop={ true } > - { logoElement } + + + learn to code javascript at Free Code Camp logo + +