From 29db5f8b94d4e94a5f12ec95c8aff3dd0c692ae8 Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Thu, 29 Jan 2015 00:17:49 -0500 Subject: [PATCH 01/23] Adding person challenge, need to inspect execution failure in testing. --- seed_data/bonfires.json | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 369ee60fd6..c78aa8cae3 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -255,6 +255,34 @@ "assert.deepEqual(inventory([], [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]), [[2, 'Hair Pin'], [3, 'Half-Eaten Apple'], [67, 'Bowling Ball'], [7, 'Toothpaste']]);", "assert.deepEqual(inventory([[0, 'Bowling Ball'], [0, 'Dirty Sock'], [0, 'Hair pin'], [0, 'Microphone']], [[1, 'Hair Pin'], [1, 'Half-Eaten Apple'], [1, 'Bowling Ball'], [1, 'Toothpaste']]), [[1, 'Bowling Ball'], [1, 'Dirty Sock'], [1, 'Hair pin'], [1, 'Half-Eaten Apple'], [1, 'Microphone'], [1, 'Toothpaste']]);" ] + }, + { + "_id": "a2f1d72d9b908d0bd72bb9f6", + "name": "Make a Person", + "difficulty": "3.12", + "description": [ + "Fill in the object constructor with the methods specified in the tests.", + "Those methods are getFirstName(), getLastName(), getFullName(), setFirstName(), setLastName(), and setFullName().", + "These methods must be the only available means for interacting with the object.", + "There will be some linting errors on the tests, you may safely ignore them. You should see undefined in the console output." + ], + "challengeEntryPoint": "var bob = new Person('Bob Ross');", + "challengeSeed": "var Person = function(firstAndLast) {\n return firstAndLast;\r\n};", + "tests": [ + "expect(Object.keys(bob).length).to.eql(6);", + "expect(bob instanceof Person).to.be.true;", + "expect(bob.firstName).to.be.undefined();", + "expect(bob.lastName).to.be.undefined();", + "expect(bob.getFirstName()).to.eql('Bob');", + "expect(bob.getLastName()).to.eql('Ross');", + "expect(bob.getFullName()).to.eql('Bob Ross');", + "bob.setFirstName('Happy');", + "expect(bob.getFirstName()).to.eql('Happy');", + "bob.setLastName('Trees');", + "expect(bob.getLastName()).to.eql('Trees');", + "bob.setFullName('George Carlin');", + "expect(bob.getFullName()).to.eql('George Carlin');" + ] } ] From e82b45e34c039ca63c8f1cbe51aadd6d6e1e80b4 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Thu, 29 Jan 2015 22:01:27 -0800 Subject: [PATCH 02/23] make the account page purely settings and make the photo redirect to the user public profile --- views/account/account.jade | 18 +----------------- views/partials/navbar.jade | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/views/account/account.jade b/views/account/account.jade index 2612dfe818..48641cdc3f 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -293,23 +293,7 @@ block content a.btn.btn-lg.btn-block.btn-twitter.btn-link-social(href='/auth/twitter') i.fa.fa-twitter | Link Twitter with your account - br - - if (ch[0] > 0) - .panel.panel-primary - .panel-heading.text-center Completed Challenges: - .panel-body - .col-xs-12 - table.table.table-striped - thead - tr - th Challenge - th Date Finished - for challenge in challenges - if ch[challenge.challengeNumber] > 0 - tr - td= challenges[challenge.challengeNumber].name - td= moment(ch[challenge.challengeNumber], 'X').format("MMM DD, YYYY") - br + .panel.panel-danger .panel-heading.text-center Danger Zone: .panel-body diff --git a/views/partials/navbar.jade b/views/partials/navbar.jade index 8388ea2ba6..a8f9f3ce20 100644 --- a/views/partials/navbar.jade +++ b/views/partials/navbar.jade @@ -37,8 +37,16 @@ a(href='/account') [ #{user.points} ] .hidden-xs if user.profile.picture - a(href='/account') - img.profile-picture.float-right(src='#{user.profile.picture}') + if (user.profile.username) + a(href='/' + user.profile.username) + img.profile-picture.float-right(src='#{user.profile.picture}') + else + a(href='/account') + img.profile-picture.float-right(src='#{user.profile.picture}') else - a(href='/account') - img.profile-picture.float-right(src='#{user.gravatar(60)}') \ No newline at end of file + if (user.profile.username) + a(href='/' + user.profile.username) + img.profile-picture.float-right(src='#{user.gravatar(60)}') + else + a(href='/account') + img.profile-picture.float-right(src='#{user.gravatar(60)}') \ No newline at end of file From 0526375c5e372f78298587ea48a0b44a14e8d931 Mon Sep 17 00:00:00 2001 From: Branden Byers Date: Fri, 30 Jan 2015 00:58:21 -0600 Subject: [PATCH 03/23] Update challenges.json --- seed_data/challenges.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seed_data/challenges.json b/seed_data/challenges.json index 7b324a05c4..905760ed54 100644 --- a/seed_data/challenges.json +++ b/seed_data/challenges.json @@ -420,8 +420,8 @@ "OK, we're finally ready to start pair programming!", "Pair Programming is where two people code together on the same computer. It is an efficient way to collaborate, and widely practiced at software companies. Pair Programming is one of the core concepts of \"Agile\" Software Development, which you will hear more about later.", "Many people use Skype or Google Hangouts to pair program, but if you talk with professional software engineers, they will tell you that it's not really pair programming unless both people have the ability to use the keyboard and mouse.", - "The most popular tool for pair programming is Screen Hero. Note that Screen Hero isn't free, and isn't yet available for Linux. Screen Hero does come with a 14 day free trial, is free for students, and you can also use it for free if your pair has a 14-day trial or a paid subscription to it. Download Screen Hero here: https://screenhero.com/download.html.", - "If you are using Linux, or if your 14 day free trial for Screen Hero has expired and you don't want to pay $10 per month for it, go to http://www.freecodecamp.com/pair-program-with-team-viewer to learn how to use an alternative (but inferior) tool called Team Viewer.", + "The most popular tool for pair programming is Screen Hero. You can download Screen Hero for Mac or Windows. Create your new user account from within the app.", + "If you are using Linux, go to http://www.freecodecamp.com/pair-program-with-team-viewer to learn how to use an alternative (but inferior) tool called Team Viewer.", "We have a special chat room for people ready to pair program. Go to https://gitter.im/FreeCodeCamp/LetsPair and type \"Hello Pair Programmers!\"", "If someone is available, they will be your \"pair\" - the person you pair programming with.", "Private message your pair and ask for the email address he or she used to register Screen Hero.", From 380a7ce8c98a86fbed1b5af95726bad4cbebc9b8 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 12:06:21 -0800 Subject: [PATCH 04/23] add ng-cloak to our ng-show alert messages to prevent them from showing while the page is loading --- views/account/account.jade | 56 ++++++++++---------- views/account/email-signup.jade | 14 ++--- views/bonfire/show.jade | 2 +- views/contact/done-with-first-100-hours.jade | 4 +- views/contact/nonprofits.jade | 6 +-- views/layout.jade | 2 +- 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/views/account/account.jade b/views/account/account.jade index 2612dfe818..a5bd9fc0a5 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -14,15 +14,15 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='name') Name * .col-sm-4 input.form-control(type='text', placeholder='Name', name='name', autocomplete="off", ng-model='user.profile.name', ng-minlength='3', ng-maxlength='50', required='required', id='name') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.name.$invalid && profileForm.name.$error.required") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.name.$invalid && profileForm.name.$error.required") alert(type='danger') span.ion-close-circled(id='#name-error') | Your name is required. - .col-sm-4.col-sm-offset-5(ng-show='profileForm.name.$error.minlength && !profileForm.name.$pristine') + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.name.$error.minlength && !profileForm.name.$pristine') alert(type='danger') span.ion-close-circled | Your name must be at least 3 characters. - .col-sm-4.col-sm-offset-5(ng-show='profileForm.name.$error.maxlength && !profileForm.name.$pristine') + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.name.$error.maxlength && !profileForm.name.$pristine') alert(type='danger') span.ion-close-circled | Your name must be fewer than 50 characters. @@ -31,23 +31,23 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='username') Username (path to public profile) * .col-sm-4 input.form-control(type='text', placeholder='username' name='username', autocomplete="off", id='username', ng-model='user.profile.username', required='required', ng-minlength='5', ng-maxlength='20', ng-keypress='', unique-username='', ng-pattern="/^[A-z0-9_]+$/") - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.pattern") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.pattern") alert(type='danger') span.ion-close-circled | Your username should only contain letters, numbers and underscores (az10_). - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.required") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.required") alert(type='danger') span.ion-close-circled | Your username is required. - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.minlength && !profileForm.username.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.minlength && !profileForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your username must be at least 5 characters. - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.maxlength && !profileForm.username.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.maxlength && !profileForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your username must be fewer than 15 characters. - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.unique && !profileForm.username.$pristine && $scope.storedUsername !== user.profile.username") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.unique && !profileForm.username.$pristine && $scope.storedUsername !== user.profile.username") alert(type='danger') span.ion-close-circled | That username is already taken. @@ -56,15 +56,15 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') Email * .col-sm-4 input.form-control(type='email', name='email', id='email', autocomplete="off", ng-model='user.email', required='required', ng-keypress='', unique-email='') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.email.$error.required") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.email.$error.required") alert(type='danger') span.ion-close-circled | Your email address is required. - .col-sm-4.col-sm-offset-5(ng-show="profileForm.$error.email && !profileForm.email.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.$error.email && !profileForm.email.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid email format. - .col-sm-4.col-sm-offset-5(ng-show="profileForm.email.$error.unique && !profileForm.email.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.email.$error.unique && !profileForm.email.$pristine") alert(type='danger') span.ion-close-circled | That email is already taken. @@ -78,7 +78,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') Link to Profile Photo (1:1 ratio) .col-sm-4 input.form-control(type='url', name='picture', id='picture', ng-model='user.profile.picture', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.picture.$error.url && !profileForm.picture.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.picture.$error.url && !profileForm.picture.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -87,7 +87,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='bio') Bio (140 characters) .col-sm-4 input.form-control(type='text', name='bio', autocomplete="off", ng-model='user.profile.bio', ng-maxlength='140', id='bio') - .col-sm-4.col-sm-offset-5(ng-show='profileForm.bio.$error.maxlength && !profileForm.bio.$pristine') + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.bio.$error.maxlength && !profileForm.bio.$pristine') alert(type='danger') span.ion-close-circled | Your bio must be fewer than 140 characters. @@ -107,11 +107,11 @@ block content .input-group.twitter-input span.input-group-addon @ input.form-control(type='text', name='twitterHandle', autocomplete="off", id='twitterHandle', ng-model='user.profile.twitterHandle', ng-maxlength='15', ng-pattern="/^[A-z0-9_]+$/") - .col-sm-4.col-sm-offset-5(ng-show="profileForm.twitterHandle.$error.pattern") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.twitterHandle.$error.pattern") alert(type='danger') span.ion-close-circled | Your Twitter handle should only contain letters, numbers and underscores (az10_). - .col-sm-4.col-sm-offset-5(ng-show='profileForm.twitterHandle.$error.maxlength && !profileForm.twitterHandle.$pristine') + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show='profileForm.twitterHandle.$error.maxlength && !profileForm.twitterHandle.$pristine') alert(type='danger') span.ion-close-circled | Your name must be fewer than 15 characters. @@ -119,7 +119,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') Github .col-sm-4 input.form-control(type='url', name='githubProfile', id='githubProfile', autocomplete="off", ng-model='user.profile.githubProfile', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.githubProfile.$error.url && !profileForm.githubProfile.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.githubProfile.$error.url && !profileForm.githubProfile.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -128,7 +128,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') CodePen .col-sm-4 input.form-control(type='url', name='codepenProfile', id='codepenProfile', autocomplete="off", ng-model='user.profile.codepenProfile', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.codepenProfile.$error.url && !profileForm.codepenProfile.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.codepenProfile.$error.url && !profileForm.codepenProfile.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -137,7 +137,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') CoderByte .col-sm-4 input.form-control(type='url', name='coderbyteProfile', id='coderbyteProfile', autocomplete="off", ng-model='user.profile.coderbyteProfile', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.coderbyteProfile.$error.url && !profileForm.coderbyteProfile.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.coderbyteProfile.$error.url && !profileForm.coderbyteProfile.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -146,7 +146,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='email') LinkedIn .col-sm-4 input.form-control(type='url', name='linkedinProfile', id='linkedinProfile', autocomplete="off", ng-model='user.profile.linkedinProfile', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.linkedinProfile.$error.url && !profileForm.linkedinProfile.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.linkedinProfile.$error.url && !profileForm.linkedinProfile.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -167,7 +167,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website1Title') Title .col-sm-4 input.form-control(type='text', name='website1Title', id='website1Title', autocomplete="off", ng-model='user.portfolio.website1Title', ng-maxlength='140') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Title.$error.maxlength && !profileForm.website1Title.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website1Title.$error.maxlength && !profileForm.website1Title.$pristine") alert(type='danger') span.ion-close-circled | Portfolio project title must be fewer than 140 characters. @@ -176,7 +176,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website1Link') Link .col-sm-4 input.form-control(type='url', name='website1Link', id='website1Link', autocomplete="off", ng-model='user.portfolio.website1Link', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Link.$error.url && !profileForm.website1Link.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website1Link.$error.url && !profileForm.website1Link.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -185,7 +185,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website1Image') Image Link (4:3 ratio) .col-sm-4 input.form-control(type='url', name='website1Image', id='website1Image', autocomplete="off", ng-model='user.portfolio.website1Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Image.$error.url && !profileForm.website1Image.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website1Image.$error.url && !profileForm.website1Image.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -197,7 +197,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website2Title') Title .col-sm-4 input.form-control(type='text', name='website2Title', id='website2Title', autocomplete="off", ng-model='user.portfolio.website2Title', ng-maxlength='140') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Title.$error.maxlength && !profileForm.website2Title.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website2Title.$error.maxlength && !profileForm.website2Title.$pristine") alert(type='danger') span.ion-close-circled | Portfolio project title must be fewer than 140 characters. @@ -206,7 +206,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website2Link') Link .col-sm-4 input.form-control(type='url', name='website2Link', id='website2Link', autocomplete="off", ng-model='user.portfolio.website2Link', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Link.$error.url && !profileForm.website2Link.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website2Link.$error.url && !profileForm.website2Link.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -214,7 +214,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website2Image') Image Link (4:3 ratio) .col-sm-4 input.form-control(type='url', name='website2Image', id='website2Image', autocomplete="off", ng-model='user.portfolio.website2Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -226,7 +226,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website3Title') Title .col-sm-4 input.form-control(type='text', name='website3Title', id='website3Title', autocomplete="off", ng-model='user.portfolio.website3Title', ng-maxlength='140') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Title.$error.maxlength && !profileForm.website3Title.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website3Title.$error.maxlength && !profileForm.website3Title.$pristine") alert(type='danger') span.ion-close-circled | Portfolio project title must be fewer than 140 characters. @@ -235,7 +235,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website3Link') Link .col-sm-4 input.form-control(type='url', name='website3Link', id='website3Link', autocomplete="off", ng-model='user.portfolio.website3Link', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Link.$error.url && !profileForm.website3Link.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website3Link.$error.url && !profileForm.website3Link.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). @@ -244,7 +244,7 @@ block content label.col-sm-3.col-sm-offset-2.control-label(for='website3Image') Image Link (4:3 ratio) .col-sm-4 input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid URL format (http://www.example.com). diff --git a/views/account/email-signup.jade b/views/account/email-signup.jade index 826af1f806..67a36fdf52 100644 --- a/views/account/email-signup.jade +++ b/views/account/email-signup.jade @@ -7,40 +7,40 @@ block content .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='email', ng-model='email', ng-keypress='', name='email', id='email', placeholder='email', autofocus, required, autocomplete="off", unique-email='') - .col-sm-6.col-sm-offset-3(ng-show="signupForm.email.$error.unique && !signupForm.email.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.email.$error.unique && !signupForm.email.$pristine") alert(type='danger') span.ion-close-circled | This email is taken. .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='text', name='username', ng-keypress='', autocomplete="off", id='username', placeholder='username', ng-model='username', unique-username='', required, ng-minlength=5, ng-maxlength=20, ng-pattern="/^[A-z0-9_]+$/") - .col-sm-4.col-sm-offset-5(ng-show="profileForm.username.$error.pattern && !signupForm.username.$pristine") + .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.pattern && !signupForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your username should only contain letters, numbers and underscores (az10_). - .col-sm-6.col-sm-offset-3(ng-show="signupForm.username.$error.unique && !signupForm.username.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.username.$error.unique && !signupForm.username.$pristine") alert(type='danger') span.ion-close-circled | This username is taken. - .col-sm-6.col-sm-offset-3(ng-show="signupForm.username.$error.minlength && !signupForm.username.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.username.$error.minlength && !signupForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your username must be at least 5 characters long. - .col-sm-6.col-sm-offset-3(ng-show="signupForm.username.$error.maxlength && !signupForm.username.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.username.$error.maxlength && !signupForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your usernames must be 20 characters or fewer. .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='password', ng-model='password', name='password', id='password', placeholder='password', required, ng-minlength=5) - .col-sm-6.col-sm-offset-3(ng-show="signupForm.password.$error.minlength && !signupForm.password.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.password.$error.minlength && !signupForm.password.$pristine") alert(type='danger') span.ion-close-circled | Your password must be at least 8 characters long. .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='password', ng-model='confirmPassword', name='confirmPassword', id='confirmPassword', placeholder='confirm password', required, ng-minlength=5) - .col-sm-6.col-sm-offset-3(ng-show="(confirmPassword !== password) && !signupForm.confirmPassword.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="(confirmPassword !== password) && !signupForm.confirmPassword.$pristine") alert(type='danger') span.ion-close-circled | Passwords must match. diff --git a/views/bonfire/show.jade b/views/bonfire/show.jade index 1c33faa304..4732bb15b6 100644 --- a/views/bonfire/show.jade +++ b/views/bonfire/show.jade @@ -116,7 +116,7 @@ block content // extra field to distract password tools like lastpass from injecting css into our username field input.form-control(ng-show="false") input.form-control#completed-with(name="existingUser", placeholder="If you paired, enter your pair's username here", existing-username='', ng-model="existingUser", autofocus) - .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") + .col-xs-10.col-xs-offset-1.col-sm-8.col-sm-offset-2.col-md-8.col-md-offset-2(ng-cloak, ng-show="completedWithForm.$error.exists && !completedWithForm.existingUser.$pristine && existingUser.length > 0") alert(type='danger') span.ion-close-circled | Username not found diff --git a/views/contact/done-with-first-100-hours.jade b/views/contact/done-with-first-100-hours.jade index 82406a6fee..070af7a11e 100644 --- a/views/contact/done-with-first-100-hours.jade +++ b/views/contact/done-with-first-100-hours.jade @@ -14,11 +14,11 @@ block content label(class='col-sm-3 control-label', for='email') Your email * .col-sm-8 input.form-control(type='text', name='email', id='email', autocomplete="off", ng-model='email', required='required', ng-keypress='') - .col-sm-8.col-sm-offset-3(ng-show="doneWithFirst100HoursForm.$error.email && !doneWithFirst100HoursForm.email.$pristine") + .col-sm-8.col-sm-offset-3(ng-cloak, ng-show="doneWithFirst100HoursForm.$error.email && !doneWithFirst100HoursForm.email.$pristine") alert(type='danger') span.ion-close-circled | Please enter a valid email format. - .col-sm-8.col-sm-offset-3(ng-show="doneWithFirst100HoursForm.email.$invalid && doneWithFirst100HoursForm.email.$error.required && !doneWithFirst100HoursForm.email.$pristine") + .col-sm-8.col-sm-offset-3(ng-cloak, ng-show="doneWithFirst100HoursForm.email.$invalid && doneWithFirst100HoursForm.email.$error.required && !doneWithFirst100HoursForm.email.$pristine") alert(type='danger') span.ion-close-circled(id='#email-error'). Your email is required. diff --git a/views/contact/nonprofits.jade b/views/contact/nonprofits.jade index 689d03f785..7df7fe5ae5 100644 --- a/views/contact/nonprofits.jade +++ b/views/contact/nonprofits.jade @@ -20,7 +20,7 @@ block content label(class='col-sm-2 control-label', for='name') Your name * .col-sm-8 input.form-control(type='text', name='name', id='name', autocomplete="off", ng-model='name', required='required') - .col-sm-8.col-sm-offset-2(ng-show="nonprofitForm.name.$invalid && nonprofitForm.name.$error.required && !nonprofitForm.name.$pristine") + .col-sm-8.col-sm-offset-2(ng-cloak, ng-show="nonprofitForm.name.$invalid && nonprofitForm.name.$error.required && !nonprofitForm.name.$pristine") alert(type='danger') span.ion-close-circled(id='#name-error') | Your name is required. @@ -28,7 +28,7 @@ block content label(class='col-sm-2 control-label', for='email') Your email * .col-sm-8 input.form-control(type='text', name='email', id='email', autocomplete="off", ng-model='email', required='required') - .col-sm-8.col-sm-offset-2(ng-show="nonprofitForm.email.$invalid && nonprofitForm.email.$error.required && !nonprofitForm.email.$pristine") + .col-sm-8.col-sm-offset-2(ng-cloak, ng-show="nonprofitForm.email.$invalid && nonprofitForm.email.$error.required && !nonprofitForm.email.$pristine") alert(type='danger') span.ion-close-circled(id='#email-error'). Your email is required. @@ -36,7 +36,7 @@ block content label(class='col-sm-2 control-label', for='message') Briefly describe what problem you need to solve, and for whom. * .col-sm-8 textarea.form-control(type='text', name='message', id='message', rows='7', autocomplete="off", ng-model='message', required='required') - .col-sm-8.col-sm-offset-2(ng-show="nonprofitForm.message.$invalid && nonprofitForm.message.$error.required && !nonprofitForm.message.$pristine") + .col-sm-8.col-sm-offset-2(ng-cloak, ng-show="nonprofitForm.message.$invalid && nonprofitForm.message.$error.required && !nonprofitForm.message.$pristine") alert(type='danger') span.ion-close-circled(id='#message-error') | Your message is required. diff --git a/views/layout.jade b/views/layout.jade index dfddef33b4..1d9332ec8c 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -2,7 +2,7 @@ doctype html html(ng-app='profileValidation', lang='en') head script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js") + script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') From 3b8b19511022bc49100ad7bbf66a040832320b29 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 13:43:41 -0800 Subject: [PATCH 05/23] update the angular CDN and remove the optimizely cdn which was hanging. Improve angular notifications on email signup page --- views/account/account.jade | 8 ++++---- views/account/email-signup.jade | 14 +++++++++++--- views/layout-wide.jade | 5 ++--- views/layout.jade | 5 ++--- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/views/account/account.jade b/views/account/account.jade index 3a4e22b825..64237b9b46 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -50,7 +50,7 @@ block content .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.unique && !profileForm.username.$pristine && $scope.storedUsername !== user.profile.username") alert(type='danger') span.ion-close-circled - | That username is already taken. + | That username is already in use. .form-group label.col-sm-3.col-sm-offset-2.control-label(for='email') Email * @@ -65,9 +65,9 @@ block content span.ion-close-circled | Please enter a valid email format. .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.email.$error.unique && !profileForm.email.$pristine") - alert(type='danger') - span.ion-close-circled - | That email is already taken. + alert(type='danger') + span.ion-close-circled + | That email is already in use. .form-group label.col-sm-3.col-sm-offset-2.control-label(for='location') Location diff --git a/views/account/email-signup.jade b/views/account/email-signup.jade index 67a36fdf52..3d734f2a9b 100644 --- a/views/account/email-signup.jade +++ b/views/account/email-signup.jade @@ -7,14 +7,22 @@ block content .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='email', ng-model='email', ng-keypress='', name='email', id='email', placeholder='email', autofocus, required, autocomplete="off", unique-email='') + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.email.$error.required && !signupForm.email.$pristine") + alert(type='danger') + span.ion-close-circled + | Your email address is required. + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.$error.email && !signupForm.email.$pristine") + alert(type='danger') + span.ion-close-circled + | Please enter a valid email format. .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="signupForm.email.$error.unique && !signupForm.email.$pristine") alert(type='danger') span.ion-close-circled - | This email is taken. + | That email address is already in use. .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='text', name='username', ng-keypress='', autocomplete="off", id='username', placeholder='username', ng-model='username', unique-username='', required, ng-minlength=5, ng-maxlength=20, ng-pattern="/^[A-z0-9_]+$/") - .col-sm-4.col-sm-offset-5(ng-cloak, ng-show="profileForm.username.$error.pattern && !signupForm.username.$pristine") + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="profileForm.username.$error.pattern && !signupForm.username.$pristine") alert(type='danger') span.ion-close-circled | Your username should only contain letters, numbers and underscores (az10_). @@ -46,7 +54,7 @@ block content | Passwords must match. .form-group .col-sm-offset-3.col-sm-6 - button.btn.btn-success(type='submit') + button.btn.btn-success(type='submit', ng-disabled='signupForm.$invalid') span.ion-person-add | Signup br diff --git a/views/layout-wide.jade b/views/layout-wide.jade index 0bed8cac5f..33873b2bf2 100644 --- a/views/layout-wide.jade +++ b/views/layout-wide.jade @@ -2,7 +2,7 @@ doctype html html(ng-app='profileValidation', lang='en') head script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js") + script(src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.11/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') @@ -29,5 +29,4 @@ script. })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-55446531-1', 'auto'); ga('require', 'displayfeatures'); - ga('send', 'pageview'); -script(src="//cdn.optimizely.com/js/999692993.js") \ No newline at end of file + ga('send', 'pageview'); \ No newline at end of file diff --git a/views/layout.jade b/views/layout.jade index 1d9332ec8c..d9cbb7bd0a 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -2,7 +2,7 @@ doctype html html(ng-app='profileValidation', lang='en') head script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js") + script(src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.11/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') @@ -30,5 +30,4 @@ script. })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-55446531-1', 'auto'); ga('require', 'displayfeatures'); - ga('send', 'pageview'); -script(src="//cdn.optimizely.com/js/999692993.js") \ No newline at end of file + ga('send', 'pageview'); \ No newline at end of file From 027d1a61d48fb738ea744fb2ea5c1e74b4893f1a Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 14:01:54 -0800 Subject: [PATCH 06/23] improve size of landing icons --- public/css/main.less | 3 ++- views/home.jade | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/public/css/main.less b/public/css/main.less index b140ab74f2..d111912352 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -154,7 +154,8 @@ ul { } .landing-icon { - font-size: 150px; + height: 200px; + width: 200px; } .responsive-container { position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden; } diff --git a/views/home.jade b/views/home.jade index cddac23ee8..650b1048f1 100644 --- a/views/home.jade +++ b/views/home.jade @@ -7,19 +7,19 @@ block content .row .col-xs-12.col-sm-12.col-md-3 h3.nowrap Get Connected - img.img-responsive(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_connect.svg', title='Get great references and connections to help you get a job') + img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_connect.svg', title='Get great references and connections to help you get a job') p.landing-p Join a community of busy, motivated professionals. .col-xs-12.col-sm-12.col-md-3 h3.nowrap Learn JavaScript - img.img-responsive(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_learn.svg', title='Learn to code') + img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_learn.svg', title='Learn to code') p.landing-p Work together on Full Stack JavaScript coding challenges. .col-xs-12.col-sm-12.col-md-3 h3.nowrap Build your Portfolio - img.img-responsive(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_portfolio.svg', title='Build a portfolio of apps for nonprofits') + img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_portfolio.svg', title='Build a portfolio of apps for nonprofits') p.landing-p Build apps that solve real problems for real people. .col-xs-12.col-sm-12.col-md-3 h3.nowrap Help Nonprofits - img.img-responsive(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_nonprofits.svg', title='Help nonprofits') + img.img-responsive.landing-icon.img-center(src= 'https://s3.amazonaws.com/freecodecamp/landingIcons_nonprofits.svg', title='Help nonprofits') p.landing-p Give nonprofits a boost by empowering them with code. .big-break a.btn.btn-cta.signup-btn(href="/login") Start learning to code (it's free) From 68df7b218eaa350c710234228156e9ed790241d3 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 17:27:24 -0800 Subject: [PATCH 07/23] update URL on regex match if incomplete url --- controllers/bonfire.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/controllers/bonfire.js b/controllers/bonfire.js index 3b98c1bef8..19599d3eab 100644 --- a/controllers/bonfire.js +++ b/controllers/bonfire.js @@ -94,6 +94,10 @@ exports.returnIndividualBonfire = function(req, res, next) { if (err) { next(err); } + var dashedNameFull = bonfire[bonfireNumber].name.toLowerCase().replace(/\s/g, '-'); + if (dashedNameFull != dashedName) { + return res.redirect('/bonfires/' + dashedNameFull); + } if (bonfire.length < 1) { req.flash('errors', { msg: "404: We couldn't find a bonfire with that name. Please double check the name." From e7da57401e6ad92e87f9b91e3fdced28d2ca9353 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 17:42:17 -0800 Subject: [PATCH 08/23] fix the icons after an accidental breaking change on completion modals --- public/css/main.less | 4 ++++ views/bonfire/show.jade | 2 +- views/challenges/show.jade | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/public/css/main.less b/public/css/main.less index d111912352..ca77373c7b 100644 --- a/public/css/main.less +++ b/public/css/main.less @@ -158,6 +158,10 @@ ul { width: 200px; } +.completion-icon{ + font-size: 150px; +} + .responsive-container { position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden; } .responsive-container iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } diff --git a/views/bonfire/show.jade b/views/bonfire/show.jade index 4732bb15b6..f494e2d4f5 100644 --- a/views/bonfire/show.jade +++ b/views/bonfire/show.jade @@ -108,7 +108,7 @@ block content .text-center .animated.zoomInDown.delay-half - span.landing-icon.ion-checkmark-circled.text-primary + span.completion-icon.ion-checkmark-circled.text-primary - if (cc) form.form-horizontal(novalidate='novalidate', name='completedWithForm') .form-group.text-center diff --git a/views/challenges/show.jade b/views/challenges/show.jade index 79f75342cf..19a4718cba 100644 --- a/views/challenges/show.jade +++ b/views/challenges/show.jade @@ -24,7 +24,7 @@ block content .modal-body .text-center .animated.zoomInDown.delay-half - span.landing-icon.ion-checkmark-circled.text-primary + span.completion-icon.ion-checkmark-circled.text-primary - if (cc) a.animated.fadeIn.btn.btn-lg.btn-primary.btn-block.next-challenge-button(name='_csrf', value=_csrf, aria-hidden='true') Take me to my next challenge - if (points && points > 2) From 7b0b12d3488117a28f2f20a0c30d06528d640003 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Fri, 30 Jan 2015 23:59:21 -0800 Subject: [PATCH 09/23] start process of updating youtube videos on live-pair-programming --- controllers/resources.js | 4 +- controllers/resources.json | 311 +++++++++++++-------- views/resources/live-pair-programming.jade | 273 ++++++++++++++++-- 3 files changed, 440 insertions(+), 148 deletions(-) diff --git a/controllers/resources.js b/controllers/resources.js index aefafe02c0..7b81d3e96f 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -2,6 +2,7 @@ var User = require('../models/User'), resources = require('./resources.json'), questions = resources.questions, steps = resources.steps, + youtubes = resources.youtubes, secrets = require('./../config/secrets'), Challenge = require('./../models/Challenge'), bonfires = require('../seed_data/bonfires.json'); @@ -86,7 +87,8 @@ module.exports = { livePairProgramming: function(req, res) { res.render('resources/live-pair-programming', { - title: 'Live Pair Programming' + title: 'Live Pair Programming', + youtubes: youtubes }); }, diff --git a/controllers/resources.json b/controllers/resources.json index 21171ca4b3..82436f2274 100644 --- a/controllers/resources.json +++ b/controllers/resources.json @@ -1,122 +1,162 @@ { - "questions": [{ - "question": "Time Complexity of Accessing Array Index (int a = ARR[5];)", - "answer": "O(1)" - }, { - "question": "Time Complexity of Inserting a node in Linked List", - "answer": "O(1)" - }, { - "question": "Time Complexity of Pushing and Popping on Stack", - "answer": "O(1)" - }, { - "question": "Time Complexity of Insertion and Removal from Queue", - "answer": "O(1)" - }, { - "question": "Time Complexity of Finding out the parent or left/right child of a node in a tree stored in Array", - "answer": "O(1)" - }, { - "question": "Time Complexity of Jumping to Next/Previous element in Doubly Linked List", - "answer": "O(1)" - }, { - "question": "Time Complexity of Traversing an array", - "answer": "O(n)" - }, { - "question": "Time Complexity of Traversing a linked list", - "answer": "O(n)" - }, { - "question": "Time Complexity of Linear Search", - "answer": "O(n)" - }, { - "question": "Time Complexity of Deletion of a specific element in a Linked List (Not sorted)", - "answer": "O(n)" - }, { - "question": "Time Complexity of Comparing two strings", - "answer": "O(n)" - }, { - "question": "Time Complexity of Checking for Palindrome", - "answer": "O(n)" - }, { - "question": "Time Complexity of Counting/Bucket Sort", - "answer": "O(n)" - }, { - "question": "Time Complexity of Binary Search", - "answer": "O(log n)" - }, { - "question": "Time Complexity of Finding largest/smallest number in a binary search tree", - "answer": "O(log n)" - }, { - "question": "Time Complexity of Certain Divide and Conquer Algorithms based on Linear functionality", - "answer": "O(log n)" - }, { - "question": "Time Complexity of Calculating Fibonacci Numbers - Best Method", - "answer": "O(log n)" - }, { - "question": "Time Complexity of Merge Sort", - "answer": "O(nlogn)" - }, { - "question": "Time Complexity of Heap Sort", - "answer": "O(nlogn)" - }, { - "question": "Time Complexity of Quick Sort", - "answer": "O(nlogn)" - }, { - "question": "Time Complexity of Certain Divide and Conquer Algorithms based on optimizing O(n^2) algorithms", - "answer": "O(nlogn)" - }, { - "question": "Time Complexity of Bubble Sort", - "answer": "O(n^2)" - }, { - "question": "Time Complexity of Insertion Sort", - "answer": "O(n^2)" - }, { - "question": "Time Complexity of Selection Sort", - "answer": "O(n^2)" - }, { - "question": "Time Complexity of Traversing a simple 2D array", - "answer": "O(n^2)" - }, { - "question": "Latency of L1 cache reference", - "answer": "0.5 nanoseconds" - }, { - "question": "Latency of Branch mispredict", - "answer": "5 nanoseconds" - }, { - "question": "Latency of L2 cache reference", - "answer": "7 nanoseconds" - }, { - "question": "Latency of Mutex lock/unlock", - "answer": "25 nanoseconds" - }, { - "question": "Latency of Main memory reference", - "answer": "100 nanoseconds" - }, { - "question": "Latency of Compressing 1K bytes with Zippy", - "answer": "3,000 nanoseconds" - }, { - "question": "Latency of Sending 1K bytes over a 1 Gbps network", - "answer": "10,000 nanoseconds" - }, { - "question": "Latency of Reading 4K randomly from SSD", - "answer": "150,000 nanoseconds" - }, { - "question": "Latency of Reading 1 MB sequentially from memory", - "answer": "250,000 nanoseconds" - }, { - "question": "Latency of a Round trip within the same datacenter", - "answer": "500,000 nanoseconds" - }, { - "question": "Latency of Reading 1 MB sequentially from SSD", - "answer": "1,000,000 nanoseconds" - }, { - "question": "Latency of Disk seek", - "answer": "10,000,000 nanoseconds" - }, { - "question": "Latency of Reading 1 MB sequentially from disk", - "answer": "20,000,000 nanoseconds" - }, { - "question": "Latency of Sending a packet from California to the Netherlands and back", - "answer": "150,000,000 nanoseconds" - }], + "questions": [ + { + "question": "Time Complexity of Accessing Array Index (int a = ARR[5];)", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Inserting a node in Linked List", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Pushing and Popping on Stack", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Insertion and Removal from Queue", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Finding out the parent or left/right child of a node in a tree stored in Array", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Jumping to Next/Previous element in Doubly Linked List", + "answer": "O(1)" + }, + { + "question": "Time Complexity of Traversing an array", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Traversing a linked list", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Linear Search", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Deletion of a specific element in a Linked List (Not sorted)", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Comparing two strings", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Checking for Palindrome", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Counting/Bucket Sort", + "answer": "O(n)" + }, + { + "question": "Time Complexity of Binary Search", + "answer": "O(log n)" + }, + { + "question": "Time Complexity of Finding largest/smallest number in a binary search tree", + "answer": "O(log n)" + }, + { + "question": "Time Complexity of Certain Divide and Conquer Algorithms based on Linear functionality", + "answer": "O(log n)" + }, + { + "question": "Time Complexity of Calculating Fibonacci Numbers - Best Method", + "answer": "O(log n)" + }, + { + "question": "Time Complexity of Merge Sort", + "answer": "O(nlogn)" + }, + { + "question": "Time Complexity of Heap Sort", + "answer": "O(nlogn)" + }, + { + "question": "Time Complexity of Quick Sort", + "answer": "O(nlogn)" + }, + { + "question": "Time Complexity of Certain Divide and Conquer Algorithms based on optimizing O(n^2) algorithms", + "answer": "O(nlogn)" + }, + { + "question": "Time Complexity of Bubble Sort", + "answer": "O(n^2)" + }, + { + "question": "Time Complexity of Insertion Sort", + "answer": "O(n^2)" + }, + { + "question": "Time Complexity of Selection Sort", + "answer": "O(n^2)" + }, + { + "question": "Time Complexity of Traversing a simple 2D array", + "answer": "O(n^2)" + }, + { + "question": "Latency of L1 cache reference", + "answer": "0.5 nanoseconds" + }, + { + "question": "Latency of Branch mispredict", + "answer": "5 nanoseconds" + }, + { + "question": "Latency of L2 cache reference", + "answer": "7 nanoseconds" + }, + { + "question": "Latency of Mutex lock/unlock", + "answer": "25 nanoseconds" + }, + { + "question": "Latency of Main memory reference", + "answer": "100 nanoseconds" + }, + { + "question": "Latency of Compressing 1K bytes with Zippy", + "answer": "3,000 nanoseconds" + }, + { + "question": "Latency of Sending 1K bytes over a 1 Gbps network", + "answer": "10,000 nanoseconds" + }, + { + "question": "Latency of Reading 4K randomly from SSD", + "answer": "150,000 nanoseconds" + }, + { + "question": "Latency of Reading 1 MB sequentially from memory", + "answer": "250,000 nanoseconds" + }, + { + "question": "Latency of a Round trip within the same datacenter", + "answer": "500,000 nanoseconds" + }, + { + "question": "Latency of Reading 1 MB sequentially from SSD", + "answer": "1,000,000 nanoseconds" + }, + { + "question": "Latency of Disk seek", + "answer": "10,000,000 nanoseconds" + }, + { + "question": "Latency of Reading 1 MB sequentially from disk", + "answer": "20,000,000 nanoseconds" + }, + { + "question": "Latency of Sending a packet from California to the Netherlands and back", + "answer": "150,000,000 nanoseconds" + } + ], "steps": [ "In the spirit of keeping Free Code Camp 100% free, we've created directions for using a totally free pair programming tool called Team Viewer. It's not as user-friendly as Screen Hero, but it gets the job done (and works on Linux!).", "Go to http://www.teamviewer.com/en/index.aspx and download Team Viewer. Be sure not to download the beta version, which isn't compatible with the current stable version everyone else will be using.", @@ -220,7 +260,8 @@ "Most triumphant!", "One loop to rule them all!", "Ain't got time to bleed!", - "By the power of Grayskull!" + "By the power of Grayskull!", + "Cowabunga!" ], "phrases": [ "Shout it from on top of a mountain", @@ -234,5 +275,37 @@ "Prove to mom that computers aren't just for games", "With coding power comes sharing responsibility", "Have you told your friends of your coding powers?" + ], + "youtubes": [ + [ + "CoderByte: Simple Mode", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "_BErpDdmBOw" + ], + [ + "CoderByte: Letter Count", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "Fn9HMn79KH0" + ], + [ + "CoderByte: Caesar Cipher", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "S7iRBZJwOAs" + ], + [ + "CoderByte: Arith Geo II", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "BHNRg39ZblE" + ], + [ + "CoderByte: First Reverse", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "YDfkHlDmehA" + ], + [ + "CoderByte: Array Addition", + "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", + "EK3r9CTkUTo" + ] ] } \ No newline at end of file diff --git a/views/resources/live-pair-programming.jade b/views/resources/live-pair-programming.jade index 5952776328..ff285fa4bb 100644 --- a/views/resources/live-pair-programming.jade +++ b/views/resources/live-pair-programming.jade @@ -10,32 +10,249 @@ block content .col-md-8.col-xs-12 .embed-responsive.embed-responsive-16by9 iframe(src='http://www.twitch.tv/freecodecamp/embed', frameborder='0', scrolling='no') + br h1 Previous Live Pair Programming Sessions - .col-xs-12 - .embed-responsive.embed-responsive-16by9.big-break - iframe.embed-responsive-item(src='//www.youtube.com/embed/_BErpDdmBOw') - h3.wrappable link:   - a(href="http://www.youtube.com/watch/_BErpDdmBOw") http://www.youtube.com/watch/_BErpDdmBOw - .embed-responsive.embed-responsive-16by9.big-break - iframe.embed-responsive-item(src='//www.youtube.com/embed/Fn9HMn79KH0') - h3.wrappable link:   - a(href="http://www.youtube.com/watch/Fn9HMn79KH0") http://www.youtube.com/watch/Fn9HMn79KH0 - .embed-responsive.embed-responsive-16by9.big-break - iframe.embed-responsive-item(src='//www.youtube.com/embed/S7iRBZJwOAs') - h3.wrappable link:   - a(href="http://www.youtube.com/watch/S7iRBZJwOAs") http://www.youtube.com/watch/S7iRBZJwOAs - .embed-responsive.embed-responsive-16by9.big-break - iframe.embed-responsive-item(src='//www.youtube.com/embed/BHNRg39ZblE') - h3.wrappable link:   - a(href="http://www.youtube.com/watch/BHNRg39ZblE") http://www.youtube.com/watch/BHNRg39ZblE - .embed-responsive.embed-responsive-16by9.big-break - iframe.embed-responsive-item(src='//www.youtube.com/embed/YDfkHlDmehA') - h3.wrappable link:   - a(href="http://www.youtube.com/watch/YDfkHlDmehA") http://www.youtube.com/watch/YDfkHlDmehA - h3 Got 3 minutes? Learn to code with us! - a.btn.btn-cta.signup-btn.btn-primary(href="/login") Start learning to code (it's free) - br - br - br - br - br + link(href='http://fonts.googleapis.com/css?family=Raleway:400,800,500,600', rel='stylesheet', type='text/css') + style. + @font-face { + font-weight: normal; + font-style: normal; + font-family: 'codropsicons'; + src: url('../fonts/codropsicons/codropsicons.eot'); + src: url('../fonts/codropsicons/codropsicons.eot?#iefix') format('embedded-opentype'), + url('../fonts/codropsicons/codropsicons.woff') format('woff'), + url('../fonts/codropsicons/codropsicons.ttf') format('truetype'), + url('../fonts/codropsicons/codropsicons.svg#codropsicons') format('svg'); + } + + *, *:after, *:before { + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + + .clearfix:before, .clearfix:after { + display: table; + content: ''; + } + + .clearfix:after { + clear: both; + } + + a { + outline: none; + color: #3498db; + text-decoration: none; + } + + a:hover, a:focus { + color: #528cb3; + } + + section { + padding: 1em; + text-align: center; + } + + .content { + margin: 0 auto; + /*max-width: 1000px;*/ + } + + .content > h2 { + text-align: center; + clear: both; + margin: 0; + padding: 4em 1% 0; + color: #eee; + background-color: #215f1e; + font-weight: 800; + font-size: 1.5em; + } + + .content > h2:first-child { + padding-top: 0em; + } + + @media screen and (max-width: 25em) { + .codrops-header { + font-size: 75%; + } + + .codrops-icon span { + display: none; + } + } + + .grid { + position: relative; + clear: both; + margin: 0 auto; + padding: 1em 0 4em; + /*max-width: 1000px;*/ + list-style: none; + text-align: center; + } + + /* Common style */ + .grid figure { + position: relative; + float: left; + overflow: hidden; + margin: 10px 1%; + /*min-width: 320px;*/ + /*max-width: 480px;*/ + max-height: 360px; + /*width: 48%;*/ + height: auto; + background: #3085a3; + text-align: center; + cursor: pointer; + } + + .grid figure img { + position: relative; + display: block; + min-height: 100%; + max-width: 100%; + opacity: 0.8; + } + + .grid figure figcaption { + padding: 2em; + color: #fff; + text-transform: uppercase; + font-size: 1.25em; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + } + + .grid figure figcaption::before, + .grid figure figcaption::after { + pointer-events: none; + } + + .grid figure figcaption, + .grid figure figcaption > a { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + /* Anchor will cover the whole item by default */ + /* For some effects it will show as a button */ + .grid figure figcaption > a { + z-index: 1000; + text-indent: 200%; + white-space: nowrap; + font-size: 0; + opacity: 0; + } + + .grid figure h2 { + /*word-spacing: -0.15em;*/ + font-weight: 300; + } + + .grid figure h2 span { + font-weight: 800; + } + + .grid figure h2, + .grid figure p { + margin: -13px 0 0 0; + } + + .grid figure p { + /*letter-spacing: 1px;*/ + font-size: 68.5%; + } + + /* Individual effects */ + /*---------------*/ + /***** magnify *****/ + /*---------------*/ + figure.effect-magnify { + background: -webkit-linear-gradient(-45deg, #34495e 0%, #cc6055 100%); + background: linear-gradient(-45deg, #34495e 0%, #cc6055 100%); + } + + figure.effect-magnify img, + figure.effect-magnify p { + -webkit-transition: opacity 0.35s, -webkit-transform 0.35s; + transition: opacity 0.35s, transform 0.35s; + } + + figure.effect-magnify:hover img { + opacity: 0.1; + -webkit-transform: scale3d(2, 2, 1); + transform: scale3d(2, 2, 1); + } + + figure.effect-magnify h2 { + -webkit-transition: -webkit-transform 0.35s; + transition: transform 0.35s; + -webkit-transform: scale3d(0.8, 0.8, 1); + transform: scale3d(0.8, 0.8, 1); + -webkit-transform-origin: 50% 100%; + transform-origin: 50% 100%; + } + + figure.effect-magnify p { + position: absolute; + bottom: 0; + left: 0; + margin: 20px; + padding: 30px; + border: 2px solid #fff; + text-transform: none; + font-size: 90%; + opacity: 0; + -webkit-transform: scale3d(0.8, 0.8, 1); + transform: scale3d(0.8, 0.8, 1); + -webkit-transform-origin: 50% -100%; + transform-origin: 50% -100%; + } + + figure.effect-magnify:hover h2, + figure.effect-magnify:hover p { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } + + /* Media queries */ + @media screen and (max-width: 50em) { + .content { + padding: 0 10px; + text-align: center; + } + + .grid figure { + display: inline-block; + float: none; + margin: 10px auto; + width: 100%; + } + } + + .container + .content + .grid + for youtube in youtubes + figure.effect-magnify + img(src='https://s3.amazonaws.com/freecodecamp/logo-animation-youtube.jpg', alt='fcc-logo') + figcaption + h2= youtube[0] + p= youtube[1] + .modal(tabindex='-1') + .modal-dialog.animated.zoomIn.fast-animation + .modal-content + .modal-header.challenge-list-header= youtube[0] + a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × + .modal-body + iframe.embed-responsive-item(src="//www.youtube.com/embed/#{youtube[2]") + br + From a660e832b8059450556fff0e600e06d4a0bcda46 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 00:04:35 -0800 Subject: [PATCH 10/23] add welcome mailer for email signups and fix an issue with the angular validations --- controllers/user.js | 36 ++++++++++++++++++++++----------- views/account/email-signup.jade | 10 ++++----- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index 7c4a9dc77a..54d6c2d552 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -93,18 +93,12 @@ exports.getEmailSignup = function(req, res) { */ exports.postEmailSignup = function(req, res, next) { - console.log('post email signup called'); - req.assert('email', 'Email is not valid').isEmail(); - req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match') - .equals(req.body.password); - var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); return res.redirect('/email-signup'); - console.log(errors); + debug(errors); } var user = new User({ @@ -132,6 +126,29 @@ exports.postEmailSignup = function(req, res, next) { res.redirect('/email-signup'); }); }); + var transporter = nodemailer.createTransport({ + service: 'Mandrill', + auth: { + user: secrets.mandrill.user, + pass: secrets.mandrill.password + } + }); + var mailOptions = { + to: user.email, + from: 'Team@freecodecamp.com', + subject: 'Welcome to Free Code Camp!', + text: [ + 'Greetings from San Francisco!\n\n', + 'Thank you for joining our community.\n', + 'Feel free to email us at this address if you have any questions about Free Code Camp.\n', + "And if you have a moment, check out our blog: blog.freecodecamp.com.\n", + 'Good luck with the challenges!\n\n', + '- the Volunteer Camp Counselor Team' + ].join('') + }; + transporter.sendMail(mailOptions, function(err) { + if (err) { return err; } + }); }); }; @@ -456,9 +473,6 @@ exports.getReset = function(req, res) { */ exports.postReset = function(req, res, next) { - req.assert('password', 'Password must be at least 4 characters long.').len(4); - req.assert('confirm', 'Passwords must match.').equals(req.body.password); - var errors = req.validationErrors(); if (errors) { @@ -547,8 +561,6 @@ exports.getForgot = function(req, res) { */ exports.postForgot = function(req, res, next) { - req.assert('email', 'Please enter a valid email address.').isEmail(); - var errors = req.validationErrors(); if (errors) { diff --git a/views/account/email-signup.jade b/views/account/email-signup.jade index 3d734f2a9b..0a5f2f4687 100644 --- a/views/account/email-signup.jade +++ b/views/account/email-signup.jade @@ -48,12 +48,12 @@ block content .form-group .col-sm-6.col-sm-offset-3 input.form-control(type='password', ng-model='confirmPassword', name='confirmPassword', id='confirmPassword', placeholder='confirm password', required, ng-minlength=5) - .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="(confirmPassword !== password) && !signupForm.confirmPassword.$pristine") - alert(type='danger') - span.ion-close-circled - | Passwords must match. + .col-sm-6.col-sm-offset-3(ng-cloak, ng-show="(confirmPassword !== password) && !signupForm.confirmPassword.$pristine") + alert(type='danger') + span.ion-close-circled + | Passwords must match. .form-group - .col-sm-offset-3.col-sm-6 + .col-sm-6.col-sm-offset-3 button.btn.btn-success(type='submit', ng-disabled='signupForm.$invalid') span.ion-person-add | Signup From 4d49875b8ec6852f9239f04d19b07e19fa3cf439 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 00:07:05 -0800 Subject: [PATCH 11/23] Revert "start process of updating youtube videos on live-pair-programming" This reverts commit 7b0b12d3488117a28f2f20a0c30d06528d640003. --- controllers/resources.js | 4 +- controllers/resources.json | 311 ++++++++------------- views/resources/live-pair-programming.jade | 273 ++---------------- 3 files changed, 148 insertions(+), 440 deletions(-) diff --git a/controllers/resources.js b/controllers/resources.js index 7b81d3e96f..aefafe02c0 100644 --- a/controllers/resources.js +++ b/controllers/resources.js @@ -2,7 +2,6 @@ var User = require('../models/User'), resources = require('./resources.json'), questions = resources.questions, steps = resources.steps, - youtubes = resources.youtubes, secrets = require('./../config/secrets'), Challenge = require('./../models/Challenge'), bonfires = require('../seed_data/bonfires.json'); @@ -87,8 +86,7 @@ module.exports = { livePairProgramming: function(req, res) { res.render('resources/live-pair-programming', { - title: 'Live Pair Programming', - youtubes: youtubes + title: 'Live Pair Programming' }); }, diff --git a/controllers/resources.json b/controllers/resources.json index 82436f2274..21171ca4b3 100644 --- a/controllers/resources.json +++ b/controllers/resources.json @@ -1,162 +1,122 @@ { - "questions": [ - { - "question": "Time Complexity of Accessing Array Index (int a = ARR[5];)", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Inserting a node in Linked List", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Pushing and Popping on Stack", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Insertion and Removal from Queue", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Finding out the parent or left/right child of a node in a tree stored in Array", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Jumping to Next/Previous element in Doubly Linked List", - "answer": "O(1)" - }, - { - "question": "Time Complexity of Traversing an array", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Traversing a linked list", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Linear Search", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Deletion of a specific element in a Linked List (Not sorted)", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Comparing two strings", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Checking for Palindrome", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Counting/Bucket Sort", - "answer": "O(n)" - }, - { - "question": "Time Complexity of Binary Search", - "answer": "O(log n)" - }, - { - "question": "Time Complexity of Finding largest/smallest number in a binary search tree", - "answer": "O(log n)" - }, - { - "question": "Time Complexity of Certain Divide and Conquer Algorithms based on Linear functionality", - "answer": "O(log n)" - }, - { - "question": "Time Complexity of Calculating Fibonacci Numbers - Best Method", - "answer": "O(log n)" - }, - { - "question": "Time Complexity of Merge Sort", - "answer": "O(nlogn)" - }, - { - "question": "Time Complexity of Heap Sort", - "answer": "O(nlogn)" - }, - { - "question": "Time Complexity of Quick Sort", - "answer": "O(nlogn)" - }, - { - "question": "Time Complexity of Certain Divide and Conquer Algorithms based on optimizing O(n^2) algorithms", - "answer": "O(nlogn)" - }, - { - "question": "Time Complexity of Bubble Sort", - "answer": "O(n^2)" - }, - { - "question": "Time Complexity of Insertion Sort", - "answer": "O(n^2)" - }, - { - "question": "Time Complexity of Selection Sort", - "answer": "O(n^2)" - }, - { - "question": "Time Complexity of Traversing a simple 2D array", - "answer": "O(n^2)" - }, - { - "question": "Latency of L1 cache reference", - "answer": "0.5 nanoseconds" - }, - { - "question": "Latency of Branch mispredict", - "answer": "5 nanoseconds" - }, - { - "question": "Latency of L2 cache reference", - "answer": "7 nanoseconds" - }, - { - "question": "Latency of Mutex lock/unlock", - "answer": "25 nanoseconds" - }, - { - "question": "Latency of Main memory reference", - "answer": "100 nanoseconds" - }, - { - "question": "Latency of Compressing 1K bytes with Zippy", - "answer": "3,000 nanoseconds" - }, - { - "question": "Latency of Sending 1K bytes over a 1 Gbps network", - "answer": "10,000 nanoseconds" - }, - { - "question": "Latency of Reading 4K randomly from SSD", - "answer": "150,000 nanoseconds" - }, - { - "question": "Latency of Reading 1 MB sequentially from memory", - "answer": "250,000 nanoseconds" - }, - { - "question": "Latency of a Round trip within the same datacenter", - "answer": "500,000 nanoseconds" - }, - { - "question": "Latency of Reading 1 MB sequentially from SSD", - "answer": "1,000,000 nanoseconds" - }, - { - "question": "Latency of Disk seek", - "answer": "10,000,000 nanoseconds" - }, - { - "question": "Latency of Reading 1 MB sequentially from disk", - "answer": "20,000,000 nanoseconds" - }, - { - "question": "Latency of Sending a packet from California to the Netherlands and back", - "answer": "150,000,000 nanoseconds" - } - ], + "questions": [{ + "question": "Time Complexity of Accessing Array Index (int a = ARR[5];)", + "answer": "O(1)" + }, { + "question": "Time Complexity of Inserting a node in Linked List", + "answer": "O(1)" + }, { + "question": "Time Complexity of Pushing and Popping on Stack", + "answer": "O(1)" + }, { + "question": "Time Complexity of Insertion and Removal from Queue", + "answer": "O(1)" + }, { + "question": "Time Complexity of Finding out the parent or left/right child of a node in a tree stored in Array", + "answer": "O(1)" + }, { + "question": "Time Complexity of Jumping to Next/Previous element in Doubly Linked List", + "answer": "O(1)" + }, { + "question": "Time Complexity of Traversing an array", + "answer": "O(n)" + }, { + "question": "Time Complexity of Traversing a linked list", + "answer": "O(n)" + }, { + "question": "Time Complexity of Linear Search", + "answer": "O(n)" + }, { + "question": "Time Complexity of Deletion of a specific element in a Linked List (Not sorted)", + "answer": "O(n)" + }, { + "question": "Time Complexity of Comparing two strings", + "answer": "O(n)" + }, { + "question": "Time Complexity of Checking for Palindrome", + "answer": "O(n)" + }, { + "question": "Time Complexity of Counting/Bucket Sort", + "answer": "O(n)" + }, { + "question": "Time Complexity of Binary Search", + "answer": "O(log n)" + }, { + "question": "Time Complexity of Finding largest/smallest number in a binary search tree", + "answer": "O(log n)" + }, { + "question": "Time Complexity of Certain Divide and Conquer Algorithms based on Linear functionality", + "answer": "O(log n)" + }, { + "question": "Time Complexity of Calculating Fibonacci Numbers - Best Method", + "answer": "O(log n)" + }, { + "question": "Time Complexity of Merge Sort", + "answer": "O(nlogn)" + }, { + "question": "Time Complexity of Heap Sort", + "answer": "O(nlogn)" + }, { + "question": "Time Complexity of Quick Sort", + "answer": "O(nlogn)" + }, { + "question": "Time Complexity of Certain Divide and Conquer Algorithms based on optimizing O(n^2) algorithms", + "answer": "O(nlogn)" + }, { + "question": "Time Complexity of Bubble Sort", + "answer": "O(n^2)" + }, { + "question": "Time Complexity of Insertion Sort", + "answer": "O(n^2)" + }, { + "question": "Time Complexity of Selection Sort", + "answer": "O(n^2)" + }, { + "question": "Time Complexity of Traversing a simple 2D array", + "answer": "O(n^2)" + }, { + "question": "Latency of L1 cache reference", + "answer": "0.5 nanoseconds" + }, { + "question": "Latency of Branch mispredict", + "answer": "5 nanoseconds" + }, { + "question": "Latency of L2 cache reference", + "answer": "7 nanoseconds" + }, { + "question": "Latency of Mutex lock/unlock", + "answer": "25 nanoseconds" + }, { + "question": "Latency of Main memory reference", + "answer": "100 nanoseconds" + }, { + "question": "Latency of Compressing 1K bytes with Zippy", + "answer": "3,000 nanoseconds" + }, { + "question": "Latency of Sending 1K bytes over a 1 Gbps network", + "answer": "10,000 nanoseconds" + }, { + "question": "Latency of Reading 4K randomly from SSD", + "answer": "150,000 nanoseconds" + }, { + "question": "Latency of Reading 1 MB sequentially from memory", + "answer": "250,000 nanoseconds" + }, { + "question": "Latency of a Round trip within the same datacenter", + "answer": "500,000 nanoseconds" + }, { + "question": "Latency of Reading 1 MB sequentially from SSD", + "answer": "1,000,000 nanoseconds" + }, { + "question": "Latency of Disk seek", + "answer": "10,000,000 nanoseconds" + }, { + "question": "Latency of Reading 1 MB sequentially from disk", + "answer": "20,000,000 nanoseconds" + }, { + "question": "Latency of Sending a packet from California to the Netherlands and back", + "answer": "150,000,000 nanoseconds" + }], "steps": [ "In the spirit of keeping Free Code Camp 100% free, we've created directions for using a totally free pair programming tool called Team Viewer. It's not as user-friendly as Screen Hero, but it gets the job done (and works on Linux!).", "Go to http://www.teamviewer.com/en/index.aspx and download Team Viewer. Be sure not to download the beta version, which isn't compatible with the current stable version everyone else will be using.", @@ -260,8 +220,7 @@ "Most triumphant!", "One loop to rule them all!", "Ain't got time to bleed!", - "By the power of Grayskull!", - "Cowabunga!" + "By the power of Grayskull!" ], "phrases": [ "Shout it from on top of a mountain", @@ -275,37 +234,5 @@ "Prove to mom that computers aren't just for games", "With coding power comes sharing responsibility", "Have you told your friends of your coding powers?" - ], - "youtubes": [ - [ - "CoderByte: Simple Mode", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "_BErpDdmBOw" - ], - [ - "CoderByte: Letter Count", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "Fn9HMn79KH0" - ], - [ - "CoderByte: Caesar Cipher", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "S7iRBZJwOAs" - ], - [ - "CoderByte: Arith Geo II", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "BHNRg39ZblE" - ], - [ - "CoderByte: First Reverse", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "YDfkHlDmehA" - ], - [ - "CoderByte: Array Addition", - "Live Pair Programming session with @terakilobyte and @Rybar from 01/16/2015.", - "EK3r9CTkUTo" - ] ] } \ No newline at end of file diff --git a/views/resources/live-pair-programming.jade b/views/resources/live-pair-programming.jade index ff285fa4bb..5952776328 100644 --- a/views/resources/live-pair-programming.jade +++ b/views/resources/live-pair-programming.jade @@ -10,249 +10,32 @@ block content .col-md-8.col-xs-12 .embed-responsive.embed-responsive-16by9 iframe(src='http://www.twitch.tv/freecodecamp/embed', frameborder='0', scrolling='no') - br h1 Previous Live Pair Programming Sessions - link(href='http://fonts.googleapis.com/css?family=Raleway:400,800,500,600', rel='stylesheet', type='text/css') - style. - @font-face { - font-weight: normal; - font-style: normal; - font-family: 'codropsicons'; - src: url('../fonts/codropsicons/codropsicons.eot'); - src: url('../fonts/codropsicons/codropsicons.eot?#iefix') format('embedded-opentype'), - url('../fonts/codropsicons/codropsicons.woff') format('woff'), - url('../fonts/codropsicons/codropsicons.ttf') format('truetype'), - url('../fonts/codropsicons/codropsicons.svg#codropsicons') format('svg'); - } - - *, *:after, *:before { - -webkit-box-sizing: border-box; - box-sizing: border-box; - } - - .clearfix:before, .clearfix:after { - display: table; - content: ''; - } - - .clearfix:after { - clear: both; - } - - a { - outline: none; - color: #3498db; - text-decoration: none; - } - - a:hover, a:focus { - color: #528cb3; - } - - section { - padding: 1em; - text-align: center; - } - - .content { - margin: 0 auto; - /*max-width: 1000px;*/ - } - - .content > h2 { - text-align: center; - clear: both; - margin: 0; - padding: 4em 1% 0; - color: #eee; - background-color: #215f1e; - font-weight: 800; - font-size: 1.5em; - } - - .content > h2:first-child { - padding-top: 0em; - } - - @media screen and (max-width: 25em) { - .codrops-header { - font-size: 75%; - } - - .codrops-icon span { - display: none; - } - } - - .grid { - position: relative; - clear: both; - margin: 0 auto; - padding: 1em 0 4em; - /*max-width: 1000px;*/ - list-style: none; - text-align: center; - } - - /* Common style */ - .grid figure { - position: relative; - float: left; - overflow: hidden; - margin: 10px 1%; - /*min-width: 320px;*/ - /*max-width: 480px;*/ - max-height: 360px; - /*width: 48%;*/ - height: auto; - background: #3085a3; - text-align: center; - cursor: pointer; - } - - .grid figure img { - position: relative; - display: block; - min-height: 100%; - max-width: 100%; - opacity: 0.8; - } - - .grid figure figcaption { - padding: 2em; - color: #fff; - text-transform: uppercase; - font-size: 1.25em; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - } - - .grid figure figcaption::before, - .grid figure figcaption::after { - pointer-events: none; - } - - .grid figure figcaption, - .grid figure figcaption > a { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } - - /* Anchor will cover the whole item by default */ - /* For some effects it will show as a button */ - .grid figure figcaption > a { - z-index: 1000; - text-indent: 200%; - white-space: nowrap; - font-size: 0; - opacity: 0; - } - - .grid figure h2 { - /*word-spacing: -0.15em;*/ - font-weight: 300; - } - - .grid figure h2 span { - font-weight: 800; - } - - .grid figure h2, - .grid figure p { - margin: -13px 0 0 0; - } - - .grid figure p { - /*letter-spacing: 1px;*/ - font-size: 68.5%; - } - - /* Individual effects */ - /*---------------*/ - /***** magnify *****/ - /*---------------*/ - figure.effect-magnify { - background: -webkit-linear-gradient(-45deg, #34495e 0%, #cc6055 100%); - background: linear-gradient(-45deg, #34495e 0%, #cc6055 100%); - } - - figure.effect-magnify img, - figure.effect-magnify p { - -webkit-transition: opacity 0.35s, -webkit-transform 0.35s; - transition: opacity 0.35s, transform 0.35s; - } - - figure.effect-magnify:hover img { - opacity: 0.1; - -webkit-transform: scale3d(2, 2, 1); - transform: scale3d(2, 2, 1); - } - - figure.effect-magnify h2 { - -webkit-transition: -webkit-transform 0.35s; - transition: transform 0.35s; - -webkit-transform: scale3d(0.8, 0.8, 1); - transform: scale3d(0.8, 0.8, 1); - -webkit-transform-origin: 50% 100%; - transform-origin: 50% 100%; - } - - figure.effect-magnify p { - position: absolute; - bottom: 0; - left: 0; - margin: 20px; - padding: 30px; - border: 2px solid #fff; - text-transform: none; - font-size: 90%; - opacity: 0; - -webkit-transform: scale3d(0.8, 0.8, 1); - transform: scale3d(0.8, 0.8, 1); - -webkit-transform-origin: 50% -100%; - transform-origin: 50% -100%; - } - - figure.effect-magnify:hover h2, - figure.effect-magnify:hover p { - opacity: 1; - -webkit-transform: scale3d(1, 1, 1); - transform: scale3d(1, 1, 1); - } - - /* Media queries */ - @media screen and (max-width: 50em) { - .content { - padding: 0 10px; - text-align: center; - } - - .grid figure { - display: inline-block; - float: none; - margin: 10px auto; - width: 100%; - } - } - - .container - .content - .grid - for youtube in youtubes - figure.effect-magnify - img(src='https://s3.amazonaws.com/freecodecamp/logo-animation-youtube.jpg', alt='fcc-logo') - figcaption - h2= youtube[0] - p= youtube[1] - .modal(tabindex='-1') - .modal-dialog.animated.zoomIn.fast-animation - .modal-content - .modal-header.challenge-list-header= youtube[0] - a.close.closing-x(href='#', data-dismiss='modal', aria-hidden='true') × - .modal-body - iframe.embed-responsive-item(src="//www.youtube.com/embed/#{youtube[2]") - br - + .col-xs-12 + .embed-responsive.embed-responsive-16by9.big-break + iframe.embed-responsive-item(src='//www.youtube.com/embed/_BErpDdmBOw') + h3.wrappable link:   + a(href="http://www.youtube.com/watch/_BErpDdmBOw") http://www.youtube.com/watch/_BErpDdmBOw + .embed-responsive.embed-responsive-16by9.big-break + iframe.embed-responsive-item(src='//www.youtube.com/embed/Fn9HMn79KH0') + h3.wrappable link:   + a(href="http://www.youtube.com/watch/Fn9HMn79KH0") http://www.youtube.com/watch/Fn9HMn79KH0 + .embed-responsive.embed-responsive-16by9.big-break + iframe.embed-responsive-item(src='//www.youtube.com/embed/S7iRBZJwOAs') + h3.wrappable link:   + a(href="http://www.youtube.com/watch/S7iRBZJwOAs") http://www.youtube.com/watch/S7iRBZJwOAs + .embed-responsive.embed-responsive-16by9.big-break + iframe.embed-responsive-item(src='//www.youtube.com/embed/BHNRg39ZblE') + h3.wrappable link:   + a(href="http://www.youtube.com/watch/BHNRg39ZblE") http://www.youtube.com/watch/BHNRg39ZblE + .embed-responsive.embed-responsive-16by9.big-break + iframe.embed-responsive-item(src='//www.youtube.com/embed/YDfkHlDmehA') + h3.wrappable link:   + a(href="http://www.youtube.com/watch/YDfkHlDmehA") http://www.youtube.com/watch/YDfkHlDmehA + h3 Got 3 minutes? Learn to code with us! + a.btn.btn-cta.signup-btn.btn-primary(href="/login") Start learning to code (it's free) + br + br + br + br + br From 613f332bb84e7289bb65ea4f87ca50b770a1f48f Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 00:12:09 -0800 Subject: [PATCH 12/23] add back in twitch chat that was somehow dropped from view (probably my fault) --- views/resources/live-pair-programming.jade | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/views/resources/live-pair-programming.jade b/views/resources/live-pair-programming.jade index 5952776328..b18baf2216 100644 --- a/views/resources/live-pair-programming.jade +++ b/views/resources/live-pair-programming.jade @@ -10,6 +10,13 @@ block content .col-md-8.col-xs-12 .embed-responsive.embed-responsive-16by9 iframe(src='http://www.twitch.tv/freecodecamp/embed', frameborder='0', scrolling='no') + .col-md-4.col-xs-12 + .visible-sm.visible-xs + .embed-responsive.embed-responsive-16by9 + iframe(src='http://www.twitch.tv/freecodecamp/chat?popout=', frameborder='0', scrolling='no') + .visible-md.visible-lg + .embed-responsive.embed-responsive-twitch-chat + iframe(src='http://www.twitch.tv/freecodecamp/chat?popout=', frameborder='0', scrolling='no') h1 Previous Live Pair Programming Sessions .col-xs-12 .embed-responsive.embed-responsive-16by9.big-break From d26a4efea48c3da85daf73d7193a8d6815a96de6 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 16:41:33 -0800 Subject: [PATCH 13/23] improve angular validation on images and trim input so trailing whitespace is ignored on save --- controllers/user.js | 49 +++++++++++++++++--------------------- views/account/account.jade | 49 +++++++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index 7c4a9dc77a..ae8f2289d1 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -93,11 +93,6 @@ exports.getEmailSignup = function(req, res) { */ exports.postEmailSignup = function(req, res, next) { - console.log('post email signup called'); - req.assert('email', 'Email is not valid').isEmail(); - req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match') - .equals(req.body.password); var errors = req.validationErrors(); @@ -108,10 +103,10 @@ exports.postEmailSignup = function(req, res, next) { } var user = new User({ - email: req.body.email, + email: req.body.email.trim(), password: req.body.password, profile : { - username: req.body.username + username: req.body.username.trim() } }); @@ -322,26 +317,26 @@ exports.postUpdateProfile = function(req, res, next) { return res.redirect('/account'); } var user = req.user; - user.email = req.body.email || ''; - user.profile.name = req.body.name || ''; - user.profile.username = req.body.username || ''; - user.profile.location = req.body.location || ''; - user.profile.githubProfile = req.body.githubProfile || ''; - user.profile.coderbyteProfile = req.body.coderbyteProfile || ''; - user.profile.linkedinProfile = req.body.linkedinProfile || ''; - user.profile.codepenProfile = req.body.codepenProfile || ''; - user.profile.twitterHandle = req.body.twitterHandle || ''; - user.profile.bio = req.body.bio || ''; - user.profile.picture = req.body.picture || ''; - user.portfolio.website1Title = req.body.website1Title || ''; - user.portfolio.website1Link = req.body.website1Link || ''; - user.portfolio.website1Image = req.body.website1Image || ''; - user.portfolio.website2Title = req.body.website2Title || ''; - user.portfolio.website2Link = req.body.website2Link || ''; - user.portfolio.website2Image = req.body.website2Image || ''; - user.portfolio.website3Title = req.body.website3Title || ''; - user.portfolio.website3Link = req.body.website3Link || ''; - user.portfolio.website3Image = req.body.website3Image || ''; + user.email = req.body.email.trim() || ''; + user.profile.name = req.body.name.trim() || ''; + user.profile.username = req.body.username.trim() || ''; + user.profile.location = req.body.location.trim() || ''; + user.profile.githubProfile = req.body.githubProfile.trim() || ''; + user.profile.coderbyteProfile = req.body.coderbyteProfile.trim() || ''; + user.profile.linkedinProfile = req.body.linkedinProfile.trim() || ''; + user.profile.codepenProfile = req.body.codepenProfile.trim() || ''; + user.profile.twitterHandle = req.body.twitterHandle.trim() || ''; + user.profile.bio = req.body.bio.trim() || ''; + user.profile.picture = req.body.picture.trim() || ''; + user.portfolio.website1Title = req.body.website1Title.trim() || ''; + user.portfolio.website1Link = req.body.website1Link.trim() || ''; + user.portfolio.website1Image = req.body.website1Image.trim() || ''; + user.portfolio.website2Title = req.body.website2Title.trim() || ''; + user.portfolio.website2Link = req.body.website2Link.trim() || ''; + user.portfolio.website2Image = req.body.website2Image.trim() || ''; + user.portfolio.website3Title = req.body.website3Title.trim() || ''; + user.portfolio.website3Link = req.body.website3Link.trim() || ''; + user.portfolio.website3Image = req.body.website3Image.trim() || ''; user.save(function (err) { diff --git a/views/account/account.jade b/views/account/account.jade index 2612dfe818..149598b1f0 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -77,12 +77,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='email') Link to Profile Photo (1:1 ratio) .col-sm-4 - input.form-control(type='url', name='picture', id='picture', ng-model='user.profile.picture', placeholder='http://') + input.form-control(type='url', name='picture', id='picture', ng-model='user.profile.picture', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") .col-sm-4.col-sm-offset-5(ng-show="profileForm.picture.$error.url && !profileForm.picture.$pristine") alert(type='danger') span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). - + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.picture.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .form-group label.col-sm-3.col-sm-offset-2.control-label(for='bio') Bio (140 characters) .col-sm-4 @@ -184,11 +187,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website1Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website1Image', id='website1Image', autocomplete="off", ng-model='user.portfolio.website1Image', placeholder='http://') + input.form-control(type='url', name='website1Image', id='website1Image', autocomplete="off", ng-model='user.portfolio.website1Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Image.$error.url && !profileForm.website1Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website1Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .col-sm-4.col-sm-offset-5.flat-top h3 Second Portfolio Project @@ -213,11 +220,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website2Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website2Image', id='website2Image', autocomplete="off", ng-model='user.portfolio.website2Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + input.form-control(type='url', name='website2Image', id='website2Image', autocomplete="off", ng-model='user.portfolio.website2Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)\s?$/") + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.url && !profileForm.website2Image.$pristine") + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website2Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .col-sm-4.col-sm-offset-5.flat-top h3 Third Portfolio Project @@ -243,11 +254,15 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website3Image') Image Link (4:3 ratio) .col-sm-4 - input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://') - .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") - alert(type='danger') - span.ion-close-circled - | Please enter a valid URL format (http://www.example.com). + input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)?$/") + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") + alert(type='danger') + span.ion-close-circled + | Please enter a valid URL format (http://www.example.com/image.jpg). + .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.pattern") + alert(type='danger') + span.ion-close-circled + | The image URL must end in .jpg, .png, .jpeg or .gif. .form-group .col-sm-offset-5.col-sm-4 From 4c8c346a7741a87ecc66ae19afa61ec9591162fc Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 16:56:23 -0800 Subject: [PATCH 14/23] Revert "first commit with working iframe pulling data from code editor" This reverts commit d7d4727c0f7acb7122769faf5b51be05677b1447. --- app.js | 1 - controllers/bonfire.js | 5 ---- views/bonfire/bonfire.jade | 45 ++++++++++++++++++++++++++++ views/courseware/show.jade | 60 -------------------------------------- 4 files changed, 45 insertions(+), 66 deletions(-) create mode 100644 views/bonfire/bonfire.jade delete mode 100644 views/courseware/show.jade diff --git a/app.js b/app.js index 7bd551524d..cfc2d71966 100644 --- a/app.js +++ b/app.js @@ -270,7 +270,6 @@ app.get('/account/api', userController.getAccountAngular); */ app.get('/playground', bonfireController.index); app.get('/bonfires', bonfireController.returnNextBonfire); -app.get('/courseware', bonfireController.courseware); app.get('/bonfire-json-generator', bonfireController.returnGenerator); app.post('/bonfire-json-generator', bonfireController.generateChallenge); app.get('/bonfire-challenge-generator', bonfireController.publicGenerator); diff --git a/controllers/bonfire.js b/controllers/bonfire.js index 07289986d1..3b98c1bef8 100644 --- a/controllers/bonfire.js +++ b/controllers/bonfire.js @@ -8,11 +8,6 @@ var _ = require('lodash'), * Bonfire controller */ -exports.courseware = function(req, res) { - res.render('courseware/show.jade', { - }); -}; - var highestBonfireNumber = resources.numberOfBonfires(); exports.index = function(req, res) { diff --git a/views/bonfire/bonfire.jade b/views/bonfire/bonfire.jade new file mode 100644 index 0000000000..498f7d3a23 --- /dev/null +++ b/views/bonfire/bonfire.jade @@ -0,0 +1,45 @@ +extends ../layout-wide +block content + script(src='/js/lib/codemirror/lib/codemirror.js') + script(src='/js/lib/codemirror/addon/edit/closebrackets.js') + script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') + script(src='/js/lib/codemirror/addon/lint/lint.js') + script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') + script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') + script(src='/js/lib/chai/chai.js') + link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') + link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') + link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') + link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") + script(src='/js/lib/codemirror/mode/javascript/javascript.js') + script(src='/js/lib/jailed/jailed.js') + script(src='/js/lib/bonfire/bonfireInit.js') + .row + script(type="text/javascript"). + var tests = !{JSON.stringify(tests)}; + var challengeSeed = !{JSON.stringify(challengeSeed)}; + var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)}; + var title = !{JSON.stringify(title)}; + + #mainEditorPanel.col-sm-12.col-md-7.col-xs-12 + .panel.panel-primary.panel-bonfire + .panel-heading.text-center Playground + .panel.panel-body + form.code + .form-group.codeMirrorView + textarea#codeEditor(autofocus=true) + + + #testCreatePanel.col-sm-12.col-md-5.col-xs-12 + .panel.panel-primary.panel-bonfire + .panel-heading.text-center Output + .panel.panel-body + #submitButton.btn.btn-primary.btn-big.btn-block Run code (ctrl + enter) + br + form.code + .form-group.codeMirrorView + textarea#codeOutput + br + ul#testSuite.list-group + br + script(src='/js/lib/bonfire/bonfireFramework.js') \ No newline at end of file diff --git a/views/courseware/show.jade b/views/courseware/show.jade deleted file mode 100644 index bf1d6212d6..0000000000 --- a/views/courseware/show.jade +++ /dev/null @@ -1,60 +0,0 @@ -extends ../layout-wide -block content - script(src='/js/lib/codemirror/lib/codemirror.js') - script(src='/js/lib/codemirror/addon/edit/closebrackets.js') - script(src='/js/lib/codemirror/addon/edit/matchbrackets.js') - script(src='/js/lib/codemirror/addon/lint/lint.js') - script(src='/js/lib/codemirror/addon/lint/javascript-lint.js') - script(src='//ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js') - script(src='/js/lib/chai/chai.js') - link(rel='stylesheet', href='/js/lib/codemirror/lib/codemirror.css') - link(rel='stylesheet', href='/js/lib/codemirror/addon/lint/lint.css') - link(rel='stylesheet', href='/js/lib/codemirror/theme/monokai.css') - link(rel="stylesheet", href="http://fonts.googleapis.com/css?family=Ubuntu+Mono") - script(src='/js/lib/codemirror/mode/javascript/javascript.js') - script(src='/js/lib/jailed/jailed.js') - script(src='/js/lib/bonfire/bonfireInit.js') - script(src='/js/lib/codemirror/mode/xml/xml.js') - script(src='/js/lib/codemirror/mode/css/css.js') - script(src='/js/lib/codemirror/mode/htmlmixed/htmlmixed.js') - style(type='text/css'). - style. - .CodeMirror { - float: left; - width: 50%; - border: 1px solid black; - } - iframe { - width: 49%; - float: left; - height: 300px; - border: 1px solid black; - border-left: 0px; - } - - textarea#code(name='code') - - - iframe#preview - script(src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js") - style(src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css") - script. - var delay; - // Initialize CodeMirror editor with a nice html5 canvas demo. - var editor = CodeMirror.fromTextArea(document.getElementById('code'), { - mode: 'text/html' - }); - editor.on("change", function () { - clearTimeout(delay); - delay = setTimeout(updatePreview, 300); - }); - function updatePreview() { - var previewFrame = document.getElementById('preview'); - var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; - preview.open(); - preview.write(editor.getValue()); - preview.close(); - } - setTimeout(updatePreview, 300); - \ No newline at end of file From 258515014a6e737eb7218610fbc5946b04b1d665 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sat, 31 Jan 2015 17:32:43 -0800 Subject: [PATCH 15/23] edit profile button if logged in and looking at own profile, and update a CDN --- views/account/account.jade | 3 +-- views/account/show.jade | 3 +++ views/layout.jade | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/views/account/account.jade b/views/account/account.jade index 465c4fcb15..05d68eb9b0 100644 --- a/views/account/account.jade +++ b/views/account/account.jade @@ -254,8 +254,7 @@ block content .form-group label.col-sm-3.col-sm-offset-2.control-label(for='website3Image') Image Link (4:3 ratio) .col-sm-4 -<<<<<<< HEAD - input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://www.example.com/image.jpg', ng-pattern="/[\.](jpg|png|jpeg|gif)?$/") + input.form-control(type='url', name='website3Image', id='website3Image', autocomplete="off", ng-model='user.portfolio.website3Image', placeholder='http://www.example.com/image.jpg', ng-pattern='/[\.](jpg|png|jpeg|gif)(\s+)?$/') .col-sm-4.col-sm-offset-5(ng-show="profileForm.website3Image.$error.url && !profileForm.website3Image.$pristine") alert(type='danger') span.ion-close-circled diff --git a/views/account/show.jade b/views/account/show.jade index ff5c9e3ffe..cae103557f 100644 --- a/views/account/show.jade +++ b/views/account/show.jade @@ -33,6 +33,9 @@ block content h3.flat-top.bolded.wrappable= location h4.flat-top.wrappable= bio .col-xs-12.col-sm-12.col-md-3.text-center + if (user && user.profile.username === username) + a.btn.btn-warning(href="/account") Edit my Profile + .background-svg.img-center .points-on-top = "[ " + points + " ]" diff --git a/views/layout.jade b/views/layout.jade index d9cbb7bd0a..83ef4770e8 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -2,7 +2,7 @@ doctype html html(ng-app='profileValidation', lang='en') head script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") - script(src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.11/angular.min.js") + script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') From c85c2689e60aac5517ab7206202ac3019e4366a3 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sun, 1 Feb 2015 10:25:04 -0800 Subject: [PATCH 16/23] add Patrick Ly to our team --- views/partials/about.jade | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/views/partials/about.jade b/views/partials/about.jade index 44a99213a6..26ca70c763 100644 --- a/views/partials/about.jade +++ b/views/partials/about.jade @@ -125,4 +125,10 @@ h4.negative-10.text-nowrap JavaScript Engineer img.profile-image(src='https://s3.amazonaws.com/freecodecamp/kamal-sharif.jpg' alt="Kamal Sharif's picture") h4.text-nowrap Dhaka, Bangladesh - p.negative-10 "I build applications that help other people improve their own lives." \ No newline at end of file + p.negative-10 "I build applications that help other people improve their own lives." + .col-xs-12.col-sm-4.col-md-3.team-member + h3.negative-10.text-nowrap Patrick Ly + h4.negative-10.text-nowrap Community Builder + img.profile-image(src='https://s3.amazonaws.com/freecodecamp/patrick-ly.jpg' alt="Patrick Ly's picture") + h4.text-nowrap Los Angeles, California + p.negative-10 "I'm a student and self-taught Hip Hop dancer. Just using the web isn't enough for me. I want to create and maintain web apps, too" \ No newline at end of file From 6ece608f01f90a083c16656f598a57b759ce59a1 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Sun, 1 Feb 2015 22:00:19 -0800 Subject: [PATCH 17/23] update compliments --- controllers/resources.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/controllers/resources.json b/controllers/resources.json index 21171ca4b3..1b4ed4f72b 100644 --- a/controllers/resources.json +++ b/controllers/resources.json @@ -220,7 +220,26 @@ "Most triumphant!", "One loop to rule them all!", "Ain't got time to bleed!", - "By the power of Grayskull!" + "By the power of Grayskull!", + "You did it!", + "Storm that castle!", + "Cue face-melting guitar Solo!", + "Fireworks explode above you!", + "Raise a toast to your code!", + "High five!", + "Dance like nobody's watching!", + "Lean, mean coding machine!", + "Domo Arigatou Mr. Roboto!", + "Windmill jam dunk!", + "Done and done!", + "Drop the mic and march!", + "Outta sight!", + "Flawless victory!", + "Warp 9. Engage!", + "Attack hug!", + "Google 'do a barrel roll'", + "You ate that for breakfast!", + "Show those tests who's boss!" ], "phrases": [ "Shout it from on top of a mountain", From 9944f1b68563cd9873259fdee7ac939857839130 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Mon, 2 Feb 2015 15:27:12 -0800 Subject: [PATCH 18/23] start adding new favicons and make the seed task run with each push to heroku --- package.json | 13 ++--------- public/favicon.ico | Bin 0 -> 7406 bytes seed_data/bonfires.json | 2 +- views/layout.jade | 1 - views/partials/meta.jade | 48 +++++++++++++++++++++++---------------- 5 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 public/favicon.ico diff --git a/package.json b/package.json index 0f57729220..0c40e74a12 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "scripts": { "start": "node app.js", - "test": "mocha" + "test": "mocha", + "prepublish": "node seed_data/seed.js" }, "dependencies": { "async": "^0.9.0", @@ -32,12 +33,9 @@ "express-flash": "^0.0.2", "express-session": "^1.9.2", "express-validator": "^2.8.0", - "fbgraph": "^0.3.0", "github-api": "^0.7.0", "helmet": "^0.5.3", - "instagram-node": "^0.5.1", "jade": "^1.8.0", - "lastfm": "^0.9.2", "less": "^1.7.5", "lodash": "^2.4.1", "lusca": "^1.0.2", @@ -47,25 +45,18 @@ "morgan": "^1.5.0", "newrelic": "^1.13.3", "node": "0.0.0", - "node-foursquare": "^0.2.1", - "node-linkedin": "^0.3.4", "node-rest-client": "^1.4.3", "nodemailer": "^1.3.0", "passport": "^0.2.1", "passport-facebook": "^1.0.3", "passport-github": "^0.1.5", "passport-google-oauth": "^0.1.5", - "passport-instagram": "^0.1.2", "passport-linkedin-oauth2": "^1.2.1", "passport-local": "^1.0.0", "passport-oauth": "^1.0.0", "passport-twitter": "^1.0.2", "request": "^2.49.0", "sitemap": "^0.7.4", - "stripe": "^3.0.2", - "tumblr.js": "^0.0.4", - "twilio": "^1.9.0", - "twit": "^1.1.18", "uglify-js": "^2.4.15", "validator": "^3.22.1", "yui": "^3.18.1" diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3ec62dd50c2c8d41f224547395abfc9d7b1831e6 GIT binary patch literal 7406 zcmeHLOQ;?-6h1RaCYem;k<2U=E*7e^3boo|kzy6Rmm*@7yC{NfMSP*Oq97=R3L?@) z1zl7q;^MmSv9${kicl03D+)dqDiw4g!u7E#Zp!r}nM~%t_rJXh7cJ!v%;cPW-+AQZ zpZu8tNPs}o0QLf&U;sM-U~bOq?+JjnactYRUatV=@wx#yXaY!ccGy`VwqCyGmVMCO zxEJo(|0F#3((ADQ(dS{u!a-R6>mS&(eF3Vuop9#t=U}!hz>yb^!y`wIL3{lk*mC=Q z@Wof(!W(bB3ooBI1!mJOxbC*a=zk{7Dln_S6<>kGx6<@&m1?Xm2h^Z0ArY=|Ym&%T zGgV+yN;$nyWl9yLDc4Mxq;0q`s^X~-X(5bc+L)?N(}o)>I-TcvT~}5tCGw4+Sxyp3 zixR^X%9L%bFi^uJ>KIQl1yU-7s?7)RhC*w#QFG`>pDO;}1+x3>9A10yviq}Z)OYUQ z@3Yt5bQhfa`a3xM!mDt{zQ^G7$7kW^Uw(sEUOVOX*aJ@;g^L$2!q(l3@X4oN!t$Sg z!_xa7Lc4V@>^txb%?Xf4`dOJ% zUxVridXteI=?M*Jj8p6OOh<~W(cCDpe5V4aM-+p#`suxVtFuJ(TPtG_IwJ*VI+ zA{@eNIH%;Ogw~%^R#sNr`{0R_OK{=BzwT_ZdDs1L7~lQuJK)j>r{UP~lQ4JlJpBI0 zGTeIigYeV&U*XON9*1u8ZaDPxQCNKVS@`J8XK?PD@7=Q{S5=O zalu^-$LCei#uR0qDoibpvy^QS6wl8f9lX_|bYK?iNYf#_&qsg`e42rA4@@mu)=#t6 zAbQd9aY7+pCymGO;0L*PQe(c}hhJaL$}*%+RRK1ix?;Ky#1pQ{FhA>`t2kZD2cxJa zX$qxHh$CTeSO@;_jLR06xJBnJ20}j4Bj3>{{CCtHY8p+fnRN7l;OWjhl%nex1|XTS zKO|9G@94iGcD_9w2Mie&yrT^PQbK76(Vm`gw?2{1<9gT$y01bxD^lm&-t78BdWh$j z#8w+K(v4ujy(&sJqT}Z-L&5^vlraE)ehc&j!>1GUgg4=tuyl?kGLrY+F*<&{3ra{4 zp9#AJt{~`-WCMXS1Nor!e0&~B7U)$$;#4^kV20F!dkk8V%$HlHLMPE-3T+j&Xn^}k sRHDT2bK(@b{gJSNH5S;~WIQ|+WXwiCQ@u}eX4=(K0lN*%+U2Xje*{S6K>z>% literal 0 HcmV?d00001 diff --git a/seed_data/bonfires.json b/seed_data/bonfires.json index 369ee60fd6..0b0eff3b17 100644 --- a/seed_data/bonfires.json +++ b/seed_data/bonfires.json @@ -1,7 +1,7 @@ [ { "_id" : "ad7123c8c441eddfaeb5bdef", - "name": "Meet Bonfire", + "name": "Meet Bonfire!", "difficulty": "0", "description": [ "Click the button below for further instructions.", diff --git a/views/layout.jade b/views/layout.jade index 83ef4770e8..9e3cd24e03 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -4,7 +4,6 @@ html(ng-app='profileValidation', lang='en') script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") - link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css') link(rel='stylesheet', href='//code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css') diff --git a/views/partials/meta.jade b/views/partials/meta.jade index 08b6c1cc1f..c0620d17ca 100644 --- a/views/partials/meta.jade +++ b/views/partials/meta.jade @@ -4,24 +4,34 @@ meta(http-equiv='X-UA-Compatible', content='IE=edge') meta(name='viewport', content='width=device-width, initial-scale=1.0') meta(name='csrf-token', content=_csrf) meta(name='keywords', content='learn to code, learn how to code, code, coding, software engineer, software developer, mean stack, pair programming, node.js, angular.js, express.js, mongoDB, coding bootcamp') -meta(content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.", property="og:title") -meta(content="FreeCodeCamp", property="og:site_name") +meta(property="og:title", content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.") +meta(property="og:site_name", content="FreeCodeCamp") meta(name='twitter:widgets:csp', content='on') meta(name='p:domain_verify', content='d0bc047a482c03c24f1168004c2a216a') -meta(content="http://www.freecodecamp.com", property="og:url") -meta(content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.", property="og:description") -meta(content="https://pbs.twimg.com/profile_images/522961310212833280/XE6vGAaO.jpeg", property="og:image") -meta(content="article", property="og:type") -meta(content="https://www.facebook.com/freecodecamp", property="article:publisher") -meta(content="Responsive", property="article:section") -link(href="https://plus.google.com/+Freecodecamp", rel="publisher") -link(href="https://plus.google.com/+Freecodecamp", rel="author") -meta(content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.", name="description") -meta(content="@freecodecamp", name="twitter:creator") -meta(content="http://www.freecodecamp.com", name="twitter:url") -meta(content="@freecodecamp", name="twitter:site") -meta(content="summary_large_image", name="twitter:card") -meta(content="https://s3.amazonaws.com/freecodecamp/challenges.png", name="twitter:image:src") -meta(content="Free Code Camp: a community of busy people learning to code", name="twitter:title") -meta(content="We're a community of busy people learning to code by collaborating on projects for nonprofits. Learn Full-stack JavaScript, build a portfolio, and get great references with our online coding bootcamp.", name="twitter:description") -meta(content="a40ee5d5dba3bb091ad783ebd2b1383f", name="p:domain_verify") \ No newline at end of file +meta(property="og:url", content="http://www.freecodecamp.com") +meta(property="og:description", content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.") +meta(property="og:image", content="https://pbs.twimg.com/profile_images/522961310212833280/XE6vGAaO.jpeg") +meta(property="og:type", content="article") +meta(property="article:publisher", content="https://www.facebook.com/freecodecamp") +meta(property="article:section", content="Responsive") +link(rel="publisher", href="https://plus.google.com/+Freecodecamp") +link(rel="author", href="https://plus.google.com/+Freecodecamp") +meta(name="description", content="Free Code Camp is a community of busy people who learn to code by collaborating on projects for nonprofits. Build your full stack JavaScript Portfolio today.") +meta(name="twitter:creator", content="@freecodecamp") +meta(name="twitter:url", content="http://www.freecodecamp.com") +meta(name="twitter:site", content="@freecodecamp") +meta(name="twitter:card", content="summary_large_image") +meta(name="twitter:image:src", content="https://s3.amazonaws.com/freecodecamp/challenges.png") +meta(name="twitter:title", content="Free Code Camp: a community of busy people learning to code") +meta(name="twitter:description", content="We're a community of busy people learning to code by collaborating on projects for nonprofits. Learn Full-stack JavaScript, build a portfolio, and get great references with our online coding bootcamp.") +meta(content="a40ee5d5dba3bb091ad783ebd2b1383f", name="p:domain_verify") +meta(name="msapplication-TileColor", content="#FFFFFF") +meta(name="msapplication-TileImage", content="/") +link(rel="apple-touch-icon-precomposed", href="path/to/favicon-152.png") +link(rel="apple-touch-icon-precomposed", sizes="152x152" href="/path/to/favicon-152.png") +link(rel="apple-touch-icon-precomposed", sizes="144x144" href="/path/to/favicon-144.png") +link(rel="apple-touch-icon-precomposed", sizes="120x120" href="/path/to/favicon-120.png") +link(rel="apple-touch-icon-precomposed", sizes="114x114" href="/path/to/favicon-114.png") +link(rel="apple-touch-icon-precomposed", sizes="72x72" href="/path/to/favicon-72.png") +link(rel="apple-touch-icon-precomposed", href="/path/to/favicon-57.png") +link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicons/favicon.ico') \ No newline at end of file From 36bcc5fea7549d548ec7da4702b0c8f8035573ce Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Mon, 2 Feb 2015 16:23:24 -0800 Subject: [PATCH 19/23] update the favicons and add recommended items to public folder --- public/browserconfig.xml | 12 ++++++++++++ public/favicons.html | 17 +++++++++++++++++ views/partials/meta.jade | 34 +++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 public/browserconfig.xml create mode 100644 public/favicons.html diff --git a/public/browserconfig.xml b/public/browserconfig.xml new file mode 100644 index 0000000000..761c736987 --- /dev/null +++ b/public/browserconfig.xml @@ -0,0 +1,12 @@ + + + + + + + + + #492c14 + + + diff --git a/public/favicons.html b/public/favicons.html new file mode 100644 index 0000000000..ba348ed7db --- /dev/null +++ b/public/favicons.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/views/partials/meta.jade b/views/partials/meta.jade index c0620d17ca..31a92ee4dc 100644 --- a/views/partials/meta.jade +++ b/views/partials/meta.jade @@ -27,11 +27,31 @@ meta(name="twitter:description", content="We're a community of busy people learn meta(content="a40ee5d5dba3bb091ad783ebd2b1383f", name="p:domain_verify") meta(name="msapplication-TileColor", content="#FFFFFF") meta(name="msapplication-TileImage", content="/") -link(rel="apple-touch-icon-precomposed", href="path/to/favicon-152.png") -link(rel="apple-touch-icon-precomposed", sizes="152x152" href="/path/to/favicon-152.png") -link(rel="apple-touch-icon-precomposed", sizes="144x144" href="/path/to/favicon-144.png") -link(rel="apple-touch-icon-precomposed", sizes="120x120" href="/path/to/favicon-120.png") -link(rel="apple-touch-icon-precomposed", sizes="114x114" href="/path/to/favicon-114.png") -link(rel="apple-touch-icon-precomposed", sizes="72x72" href="/path/to/favicon-72.png") -link(rel="apple-touch-icon-precomposed", href="/path/to/favicon-57.png") +link(rel="android-chrome", sizes="144x144" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-144x144.png") +link(rel="android-chrome", sizes="192x192" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-192x192.png") +link(rel="android-chrome", sizes="36x36" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-36x36.png") +link(rel="android-chrome", sizes="48x48" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-48x48.png") +link(rel="android-chrome", sizes="72x72" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-72x72.png") +link(rel="android-chrome", sizes="96x96" href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-96x96.png") +link(rel="android-chrome-manifest", href="https://s3.amazonaws.com/freecodecamp/favicons/android-chrome-manifest.json") +link(rel="apple-touch-icon", sizes="114x114", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-114x114.png") +link(rel="apple-touch-icon", sizes="120x120", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-120x120.png") +link(rel="apple-touch-icon", sizes="144x144", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-144x144.png") +link(rel="apple-touch-icon", sizes="152x152", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-152x152.png") +link(rel="apple-touch-icon", sizes="180x180", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-180x180.png") +link(rel="apple-touch-icon", sizes="57x57", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-57x57.png") +link(rel="apple-touch-icon", sizes="60x60", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-60x60.png") +link(rel="apple-touch-icon", sizes="72x72", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-72x72.png") +link(rel="apple-touch-icon", sizes="76x76", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-76x76.png") +link(rel="apple-touch-icon-precomposed", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon-precomposed.png") +link(rel="apple-touch-icon", href="https://s3.amazonaws.com/freecodecamp/favicons/apple-touch-icon.png") +link(rel="favicon", sizes="16x16", href="https://s3.amazonaws.com/freecodecamp/favicons/favicon-16x16.png") +link(rel="favicon", sizes="32x32", href="https://s3.amazonaws.com/freecodecamp/favicons/favicon-32x32.png") +link(rel="favicon", sizes="96x96", href="https://s3.amazonaws.com/freecodecamp/favicons/favicon-96x96.png") +link(rel="mstile", sizes="144x144", href="https://s3.amazonaws.com/freecodecamp/favicons/mstile-144x144.png") +link(rel="mstile", sizes="150x150", href="https://s3.amazonaws.com/freecodecamp/favicons/mstile-150x150.png") +link(rel="mstile", sizes="310x310", href="https://s3.amazonaws.com/freecodecamp/favicons/mstile-310x310.png") +link(rel="mstile", sizes="310x150", href="https://s3.amazonaws.com/freecodecamp/favicons/mstile-310x150.png") +link(rel="mstile", sizes="70x70", href="https://s3.amazonaws.com/freecodecamp/favicons/mstile-70x70.png") +link(rel="favicon", href="https://s3.amazonaws.com/freecodecamp/favicons/favicon.ico") link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicons/favicon.ico') \ No newline at end of file From 43234825cfef2051a680ea41365772c0891d6e70 Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Tue, 3 Feb 2015 01:00:12 -0500 Subject: [PATCH 20/23] Removing needless CDN call, optimizing account view for slow page loads --- controllers/user.js | 17 +---------------- views/layout.jade | 2 -- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/controllers/user.js b/controllers/user.js index 48e8ee4bf0..98236391a2 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -158,18 +158,9 @@ exports.postEmailSignup = function(req, res, next) { */ exports.getAccount = function(req, res) { - Challenge.find({}, null, { sort: { challengeNumber: 1 } }, function(err, c) { - if (err) { - console.error('Challenge err: ', err); - next(err); - } res.render('account/account', { - title: 'Manage your Free Code Camp Account', - challenges: c, - ch: req.user.challengesHash, - moment: moment + title: 'Manage your Free Code Camp Account' }); - }); }; /** @@ -177,15 +168,9 @@ exports.getAccount = function(req, res) { */ exports.getAccountAngular = function(req, res) { - Challenge.find({}, null, { sort: { challengeNumber: 1 } }, function(err, c) { - if (err) { - console.error('Challenge err: ', err); - next(err); - } res.json({ user: req.user }); - }); }; /** diff --git a/views/layout.jade b/views/layout.jade index 83ef4770e8..6e5cadeefd 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -4,10 +4,8 @@ html(ng-app='profileValidation', lang='en') script(src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js") script(src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js") script(src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js") - link(rel='shortcut icon', href='//s3.amazonaws.com/freecodecamp/favicon.ico') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css') link(rel='stylesheet', href='//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css') - link(rel='stylesheet', href='//code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css') include partials/meta title #{title} | Free Code Camp meta(charset='utf-8') From c3926423af788a90fba778949d5f5246d549a057 Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Tue, 3 Feb 2015 01:57:35 -0500 Subject: [PATCH 21/23] Adding analytics to bonfire --- public/js/lib/bonfire/bonfireFramework.js | 12 +++++++++++- public/js/main.js | 11 ++++++++++- views/bonfire/show.jade | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/public/js/lib/bonfire/bonfireFramework.js b/public/js/lib/bonfire/bonfireFramework.js index 83a8742b5c..965dca2968 100644 --- a/public/js/lib/bonfire/bonfireFramework.js +++ b/public/js/lib/bonfire/bonfireFramework.js @@ -22,6 +22,11 @@ var editor = myCodeMirror; editor.setSize("100%", "auto"); +var attempts = 0; +if (attempts) { + attempts = 0; +} + // Default value for editor if one isn't provided in (i.e. a challenge) var nonChallengeValue = '/*Welcome to Bonfire, Free Code Camp\'s future CoderByte replacement.\n' + 'Please feel free to use Bonfire as an in-browser playground and linting tool.\n' + @@ -100,15 +105,18 @@ $('#submitButton').on('click', function () { }); function bonfireExecute() { + attempts++; + ga('send', 'event', 'Bonfire', 'ran-code', bonfireName); userTests= null; $('#codeOutput').empty(); var userJavaScript = myCodeMirror.getValue(); userJavaScript = removeComments(userJavaScript); userJavaScript = scrapeTests(userJavaScript); // simple fix in case the user forgets to invoke their function - if (challengeEntryPoint) { + if (challengeEntryPoint && challengeSeed) { userJavaScript = challengeEntryPoint + ' ' + userJavaScript; } + console.log(userJavaScript); submit(userJavaScript, function(cls, message) { if (cls) { codeOutput.setValue(message.error); @@ -224,5 +232,7 @@ var runTests = function(err, data) { }; function showCompletion() { + + ga('send', 'event', 'Bonfire', 'solved', bonfireName + ', Time: ' + (Math.floor(Date.now() / 1000) - started) +', Attempts: ' + attempts); $('#complete-bonfire-dialog').modal('show'); } \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index 8c9b83aa31..7ba0af65d3 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,4 +1,7 @@ $(document).ready(function() { + if (bonfireName !== undefined) { + ga('send', 'event', 'Bonfire', 'load', bonfireName + ':' + Math.floor(Date.now() / 1000)); + } var CSRF_HEADER = 'X-CSRF-Token'; @@ -61,7 +64,6 @@ $(document).ready(function() { var bonfireSolution = myCodeMirror.getValue(); var thisBonfireHash = passedBonfireHash || null; var didCompleteWith = $('#completed-with').val() || null; - completedBonfire(didCompleteWith, bonfireSolution, thisBonfireHash); }); @@ -83,6 +85,7 @@ $(document).ready(function() { // Bonfire instructions functions $('#more-info').on('click', function() { + ga('send', 'event', 'Bonfire', 'more-info', bonfireName); $('#brief-instructions').hide(); $('#long-instructions').show().removeClass('hide'); @@ -91,6 +94,12 @@ $(document).ready(function() { $('#brief-instructions').show(); $('#long-instructions').hide(); }); + + // Bonfire analytics + $('#submitButton').on('click', function() { + attempts++; + ga('send', 'event', 'Bonfire', 'ran-code', bonfireName); + }) }); var profileValidation = angular.module('profileValidation',['ui.bootstrap']); diff --git a/views/bonfire/show.jade b/views/bonfire/show.jade index 259634d536..98d06ca127 100644 --- a/views/bonfire/show.jade +++ b/views/bonfire/show.jade @@ -90,6 +90,8 @@ block content var challengeSeed = !{JSON.stringify(challengeSeed)}; var challengeEntryPoint = !{JSON.stringify(challengeEntryPoint)}; var passedBonfireHash = !{JSON.stringify(bonfireHash)}; + var bonfireName = !{JSON.stringify(name)}; + var started = Math.floor(Date.now() / 1000); .col-xs-12.col-sm-12.col-md-8 #mainEditorPanel form.code From 040d687f20db42d50d875d3581d8d1935df0f735 Mon Sep 17 00:00:00 2001 From: Nathan Leniz Date: Tue, 3 Feb 2015 01:59:19 -0500 Subject: [PATCH 22/23] Removing duplicate analytics call --- public/js/main.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/public/js/main.js b/public/js/main.js index 7ba0af65d3..e31855baf9 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -94,12 +94,6 @@ $(document).ready(function() { $('#brief-instructions').show(); $('#long-instructions').hide(); }); - - // Bonfire analytics - $('#submitButton').on('click', function() { - attempts++; - ga('send', 'event', 'Bonfire', 'ran-code', bonfireName); - }) }); var profileValidation = angular.module('profileValidation',['ui.bootstrap']); From 78e473b4d26df7365f8cc2a9773351ce71c59eb4 Mon Sep 17 00:00:00 2001 From: Michael Q Larson Date: Mon, 2 Feb 2015 23:03:50 -0800 Subject: [PATCH 23/23] another minor change to compliments --- controllers/resources.json | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/controllers/resources.json b/controllers/resources.json index 1b4ed4f72b..fab538f2ff 100644 --- a/controllers/resources.json +++ b/controllers/resources.json @@ -223,23 +223,7 @@ "By the power of Grayskull!", "You did it!", "Storm that castle!", - "Cue face-melting guitar Solo!", - "Fireworks explode above you!", - "Raise a toast to your code!", - "High five!", - "Dance like nobody's watching!", - "Lean, mean coding machine!", - "Domo Arigatou Mr. Roboto!", - "Windmill jam dunk!", - "Done and done!", - "Drop the mic and march!", - "Outta sight!", - "Flawless victory!", - "Warp 9. Engage!", - "Attack hug!", - "Google 'do a barrel roll'", - "You ate that for breakfast!", - "Show those tests who's boss!" + "Face-melting guitar Solo!" ], "phrases": [ "Shout it from on top of a mountain",