diff --git a/aestimia.js b/aestimia.js index f0c1623..4f7dd8d 100644 --- a/aestimia.js +++ b/aestimia.js @@ -169,10 +169,11 @@ aestimia.defaultOptions = { }; module.exports = aestimia; -module.exports.healthCheck = function(cb) { +module.exports.healthCheck = function(meta, cb) { // A random email should guarantee we bust through any caches. var email = 'healthCheck_test_' + Math.floor(Math.random() * 100000) + '@mozilla.org'; + meta.notes = ENDPOINT; aestimia.get('/submissions?learner=' + encodeURIComponent(email), cb); }; diff --git a/controllers/health-check.js b/controllers/health-check.js index f82d03f..12423a7 100644 --- a/controllers/health-check.js +++ b/controllers/health-check.js @@ -6,31 +6,42 @@ var colors = require('colors'); const CHECKMARK = "\u2713"; function checker(fn) { + var meta = {}; + var result = function(obj) { + Object.keys(obj).forEach(function(prop) { + meta[prop] = obj[prop]; + }); + return meta; + }; + return function check(cb) { var timeout = setTimeout(function() { timeout = null; - cb(null, {status: "FAILED", reason: "TIMEOUT"}); + cb(null, result({status: "FAILED", reason: "TIMEOUT"})); }, module.exports.TIMEOUT); try { - fn(function(err) { + fn(meta, function(err) { if (timeout === null) return; clearTimeout(timeout); timeout = null; if (err) - return cb(null, {status: "FAILED", reason: err.toString()}); - cb(null, {status: "OK"}); + return cb(null, result({ + status: "FAILED", + reason: err.toString() + })); + cb(null, result({status: "OK"})); }); } catch (e) { clearTimeout(timeout); timeout = null; - cb(null, {status: "FAILED", reason: e.toString()}); + cb(null, result({status: "FAILED", reason: e.toString()})); } }; } function sessionStorageChecker(sessionStore) { - return checker(function checkSessionStorage(cb) { + return checker(function checkSessionStorage(meta, cb) { var randomNumber = Math.floor(Math.random() * 10000000); var sid = "healthCheck_sessionStorage_" + randomNumber; var session = { @@ -79,10 +90,12 @@ function resultsToConsoleString(results) { var info = results[name]; if (info && typeof(info) == "object" && info.status) { + var fullName = name; + if (info.notes) fullName += " (" + info.notes + ")"; if (info.status == "OK") { - lines.push(CHECKMARK.green + " " + name.grey); + lines.push(CHECKMARK.green + " " + fullName.grey); } else { - lines.push("x".red + " " + name.grey + " " + + lines.push("x".red + " " + fullName.grey + " " + (info.reason ? info.reason : "")); } } diff --git a/db.js b/db.js index b9376e7..42b3d86 100644 --- a/db.js +++ b/db.js @@ -97,7 +97,7 @@ db.model = function(name) { } db.type = Sequelize; -db.healthCheck = function(cb) { +db.healthCheck = function(meta, cb) { var conn = require('mysql').createConnection({ host: DB_HOST, port: DB_PORT, @@ -105,6 +105,8 @@ db.healthCheck = function(cb) { user: USERNAME, password: PASSWORD, }); + meta.notes = 'mysql://' + USERNAME + "@" + (DB_HOST || "localhost") + + ':' + (DB_PORT || '3306') + '/' + DB_NAME; conn.connect(); conn.query('SHOW TABLES', cb); conn.end(); diff --git a/mandrill.js b/mandrill.js index 340172c..78aba0e 100644 --- a/mandrill.js +++ b/mandrill.js @@ -115,14 +115,18 @@ module.exports = { } }; -module.exports.healthCheck = function(cb) { - if (FAKE_EMAIL) return cb(null); +module.exports.healthCheck = function(meta, cb) { + if (FAKE_EMAIL) { + meta.notes = "fake email"; + return cb(null); + } var opts = { url: url.resolve(ENDPOINT, 'users/ping.json'), json: { key: KEY } }; + meta.notes = ENDPOINT; request.post(opts, function(err, response, body) { if (err) return cb(err); diff --git a/openbadger.js b/openbadger.js index bc27e33..fa6ccd6 100644 --- a/openbadger.js +++ b/openbadger.js @@ -385,12 +385,13 @@ module.exports.getFilters = function getFilters () { }; } module.exports.updateOrgs = updateOrgs; -module.exports.healthCheck = function(cb) { +module.exports.healthCheck = function(meta, cb) { // Use a privileged API call to ensure we're testing the JWT secret. // A random email should guarantee we bust through any caches. var email = 'healthCheck_test_' + Math.floor(Math.random() * 100000) + '@mozilla.org'; + meta.notes = ENDPOINT; openbadger.getUserBadges({ session: {user: {email: email}} }, cb); diff --git a/package.json b/package.json index b4e0ace..61737ec 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "knox": "~0.8.2", "mime": "~1.2.9", "mysql": "~2.0.0-alpha7", - "nunjucks": "~0.1.8a", + "nunjucks": "~0.1.9", "request": "~2.21.0", "sequelize": "~1.6.0", "tap": "~0.4.1", diff --git a/s3.js b/s3.js index ab4d1b4..da2ed29 100644 --- a/s3.js +++ b/s3.js @@ -5,9 +5,9 @@ const S3_REQUIRED_ENV_VARS = [ "CSOL_AWS_SECRET", "CSOL_AWS_BUCKET" ]; - -if (process.env['NODE_ENV'] == 'development' && - process.env["CSOL_AWS_FAKE_S3_DIR"]) { +const USE_FAKE_S3 = process.env['NODE_ENV'] == 'development' && + process.env["CSOL_AWS_FAKE_S3_DIR"]; +if (USE_FAKE_S3) { var FakeS3 = require('./s3-fake'); s3 = new FakeS3(process.env["CSOL_AWS_FAKE_S3_DIR"]); } else { @@ -25,11 +25,16 @@ if (process.env['NODE_ENV'] == 'development' && }); } -s3.healthCheck = function(cb) { +s3.healthCheck = function(meta, cb) { var async = require('async'); var rnd = Math.floor(Math.random() * 100000).toString(); var url = '/healthChecker_test_' + rnd; + if (USE_FAKE_S3) + meta.notes = 'fake s3'; + else + meta.notes = process.env["CSOL_AWS_BUCKET"] + '.s3.amazonaws.com'; + async.series([ s3.putBuffer.bind(s3, new Buffer(rnd), url, { 'Content-Type': 'text/plain' diff --git a/static/media/css/core.css b/static/media/css/core.css index 816b514..e5af784 100644 --- a/static/media/css/core.css +++ b/static/media/css/core.css @@ -3,10 +3,18 @@ html, body { height: 100%; - font-family: 'Open Sans', sans-serif; font-weight: 300; line-height: 18px; } +html, +body, +h1, +h2, +h3, +h4, +p { + font-family: 'Open Sans', sans-serif; +} body { margin: 0px; padding: 0px; @@ -125,6 +133,11 @@ ol { .navbar .nav-wrap ul.nav > li > a:hover { color: #c0c0c0; } +.navbar .nav-wrap ul.nav > li.active a, +.navbar .nav-wrap ul.nav > li.active a:hover { + border-left: none; + border-right: none; +} .navbar .nav-wrap ul.nav > li:last-child { border-right: none; } @@ -241,7 +254,7 @@ nav.pagination ul li a { overflow: hidden; } /*mobile*/ -@media only screen and (min-width: 320px) and (max-width: 599px) { +@media only screen and (max-width: 599px) { .container p, .container h1, .container h2, @@ -251,15 +264,16 @@ nav.pagination ul li a { #main { padding-top: 15px; } + #main .navbar-form select { + margin: 0 auto; + display: block; + } .form-search label, .form-inline label, .form-search .btn-group, .form-inline .btn-group { display: block; } - .filter label { - display: none; - } .navbar .nav-wrap, .container, .navbar-static-top .container, @@ -272,6 +286,14 @@ nav.pagination ul li a { margin-left: auto; margin-right: auto; } + .navbar .brand { + background-image: url('../img/csol_logo_sm.png'); + height: 150px; + background-position: top center; + } + .navbar-inner > .container { + width: 100%; + } .form-horizontal .control-label { text-align: left; float: none; @@ -293,16 +315,41 @@ nav.pagination ul li a { .navbar .nav-wrap { width: 90%; margin: 0 auto; + border-radius: 5px; } - .navbar .nav-wrap ul.nav li { + .navbar .nav-wrap ul.nav li, + .navbar .nav-wrap #dynWrap li, + .navbar .nav-wrap ul.nav li.active, + .navbar .nav-wrap #dynWrap li.active { display: block; } - .navbar .nav-wrap ul.nav li a { - padding: 5px 0; + .navbar .nav-wrap ul.nav li a, + .navbar .nav-wrap #dynWrap li a, + .navbar .nav-wrap ul.nav li.active a, + .navbar .nav-wrap #dynWrap li.active a, + .navbar .nav-wrap ul.nav li a:visited, + .navbar .nav-wrap #dynWrap li a:visited, + .navbar .nav-wrap ul.nav li.active a:visited, + .navbar .nav-wrap #dynWrap li.active a:visited, + .navbar .nav-wrap ul.nav li a:hover, + .navbar .nav-wrap #dynWrap li a:hover, + .navbar .nav-wrap ul.nav li.active a:hover, + .navbar .nav-wrap #dynWrap li.active a:hover { + font-size: 14px; + padding: 7px 0; + text-transform: capitalize; + line-height: 16px; + color: #000; + text-decoration: none; + display: block; + font-weight: 400; } .navbar .nav-wrap ul.nav li:nth-child(even), + .navbar .nav-wrap #dynWrap li:nth-child(even), .navbar .nav-wrap ul.nav > .active > a, - .navbar .nav-wrap ul.nav > .active > a:hover { + .navbar .nav-wrap #dynWrap > .active > a, + .navbar .nav-wrap ul.nav > .active > a:hover, + .navbar .nav-wrap #dynWrap > .active > a:hover { border-left: none; border-right: none; } @@ -601,26 +648,51 @@ input[type="password"].metered:focus:invalid:focus + .password-meter { border-color: #e9322d; } /* ------------------------------ */ -/* Mobile : width > iphone ------ */ -/* ------------------------------ */ -@media only screen and (min-width: 321px) and (max-width: 940px) { - .navbar .brand { - background-image: url('../img/csol_logo_480.png'); - height: 166px; - } -} -/* ------------------------------ */ -/* Mobile : width <= iphone ----- */ -/* ------------------------------ */ -@media only screen and (max-width: 320px) { - .navbar .brand { - background-image: url('../img/csol_logo_320.png'); - height: 116px; - } -} -/* ------------------------------ */ /* CSOL-site SPECIFIC ----------- */ /* ------------------------------ */ +body .navbar.filter label, +body .navbar.filter select, +body .navbar.filter input { + display: block; + float: left; +} +body .navbar.filter select { + margin-right: 25px; +} +body .navbar.filter label { + background: url('../img/icon-sprite.png') no-repeat top left; + width: 30px; + height: 30px; + text-indent: -9000px; + margin-bottom: 0px; + margin-top: 5px; +} +body .navbar.filter label.filter-age { + background-position: 0 -160px; +} +body .navbar.filter label.filter-category { + background-position: 0 -640px; +} +body .navbar.filter label.filter-org { + background-position: 0 -480px; +} +body .navbar.filter label.filter-activity { + background-position: 0 -720px; +} +/* ------------------------------ */ +/* Mobile : general ------------ */ +/* ------------------------------ */ +@media only screen and (max-width: 599px) { + body .navbar.filter .selectWrapper, + body .navbar.filter input { + clear: left; + margin: auto; + text-align: center; + width: 180px; + display: block; + float: none; + } +} /* ------------------------------ */ /* Mobile : width <= iphone ---- */ /* ------------------------------ */ @@ -906,7 +978,7 @@ body.home .navbar .nav-wrap ul.nav > li:nth-child(even) { /* ------------------------------ */ /* Landing page : mobile -------- */ /* ------------------------------ */ -@media only screen and (min-width: 320px) and (max-width: 599px) { +@media only screen and (max-width: 599px) { body.home { background-image: url('../img/chalkboard_bg.jpg'); } @@ -953,3 +1025,56 @@ body.home .navbar .nav-wrap ul.nav > li:nth-child(even) { margin: 0 auto; } } +/* ------------------------------ */ +/* Filter sprite positions ------ */ +/* ------------------------------ */ +.sprite-activitylines { + background-position: 0 0; + width: 30px; + height: 30px; +} +.sprite-activitytype { + background-position: 0 -80px; + width: 30px; + height: 30px; +} +.sprite-age { + background-position: 0 -160px; + width: 30px; + height: 30px; +} +.sprite-badgetype { + background-position: 0 -240px; + width: 30px; + height: 30px; +} +.sprite-date { + background-position: 0 -320px; + width: 30px; + height: 30px; +} +.sprite-location { + background-position: 0 -400px; + width: 30px; + height: 30px; +} +.sprite-organization { + background-position: 0 -480px; + width: 30px; + height: 30px; +} +.sprite-search { + background-position: 0 -560px; + width: 30px; + height: 30px; +} +.sprite-topic { + background-position: 0 -640px; + width: 30px; + height: 30px; +} +.sprite-type { + background-position: 0 -720px; + width: 30px; + height: 30px; +} diff --git a/static/media/img/chi.png b/static/media/img/chi.png index cf61745..529b6f0 100644 Binary files a/static/media/img/chi.png and b/static/media/img/chi.png differ diff --git a/static/media/img/icon-sprite.png b/static/media/img/icon-sprite.png new file mode 100644 index 0000000..197b91e Binary files /dev/null and b/static/media/img/icon-sprite.png differ diff --git a/static/media/img/mac.png b/static/media/img/mac.png index 00769a9..1d39780 100644 Binary files a/static/media/img/mac.png and b/static/media/img/mac.png differ diff --git a/static/media/img/moz.png b/static/media/img/moz.png index e0b2cd2..ad101e8 100644 Binary files a/static/media/img/moz.png and b/static/media/img/moz.png differ diff --git a/static/media/js/custom_logic.js b/static/media/js/custom_logic.js index 9e75c08..9eb4e62 100644 --- a/static/media/js/custom_logic.js +++ b/static/media/js/custom_logic.js @@ -5,8 +5,21 @@ var mob = 0; if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) mob = 1 $('.show-tooltip').tooltip(); + + /*move filter labels into the selectors*/ + if($('.navbar.filter').length != 0) { + $('.navbar.filter form label').each(function(){ + var selectID = ($(this).attr('for')); + var selectEle = $('#' + selectID); + $('#' + selectID + ' option:first').text($(this).text()); + var selectWrap = $('
').append(this,selectEle); + $('.navbar.filter form').prepend(selectWrap); + + }); + } + + /*landing page overrides*/ if($('body.home').length != 0) { - var vidLink = $('watch video').click(function(){ if($('#i_vid').length == 0) { var bkgFade = $(''); @@ -30,6 +43,7 @@ if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) mob $('

This summer Mayor Rahm Emanuel is challenging all Chicago youth to participate in the Summer of Learning. School stops for the summer, but learning never should.

').prependTo('.footer .upper'); $('
join the conversation on Facebook.share stories
').appendTo('.footer .upper'); + /*landing page mobile overrides*/ if(mob) { vidLink = 'watch video'; } @@ -43,5 +57,24 @@ if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) mob $('li.badges a').append(' Badges &'); $('li.about a').append(' the program') $('li.challenges a').append(' your future.'); + } else { + /*non-landing page overrides*/ + if(mob) { + var dynWrap = $(''); + var dynList = $('
  • '); + var dynLink = $('Menu').click(function(){ + $('#dynWrap').slideToggle(); + return false; + }); + + $('ul.nav').prepend(dynList.append(dynLink), dynWrap); + //dynLink.appendTo(dynWrap.prependTo()); + + $('ul.nav li').each(function(){ + if ($(this).attr("id") != "dyn") { + $(this).appendTo("#dynWrap"); + } + }); + } } }); \ No newline at end of file diff --git a/static/media/less/core.less b/static/media/less/core.less index 8791b54..558c5e7 100644 --- a/static/media/less/core.less +++ b/static/media/less/core.less @@ -6,10 +6,12 @@ /*general*/ html, body { height:100%; - font-family:'Open Sans', sans-serif; font-weight:300; line-height:18px; } +html, body, h1, h2, h3, h4, p { + font-family:'Open Sans', sans-serif; +} body { margin:0px; padding:0px; @@ -129,6 +131,12 @@ ol { & > a:focus, & > a:hover { color:#c0c0c0; } + &.active { + a, a:hover { + border-left:none; + border-right:none; + } + } } & > li:last-child { border-right:none; @@ -271,20 +279,22 @@ nav.pagination { /*mobile*/ @media only screen -and (min-width : 320px) and (max-width : 599px) { .container p, .container h1, .container h2, .footer .upper p { width:inherit; } #main { padding-top:15px; + .navbar-form { + select { + margin:0 auto; + display:block; + } + } } .form-search label, .form-inline label, .form-search .btn-group, .form-inline .btn-group { display:block; } - .filter label { - display:none; - } .navbar .nav-wrap, .container, .navbar-static-top .container, @@ -297,6 +307,14 @@ and (max-width : 599px) { margin-left:auto; margin-right:auto; } + .navbar .brand { + background-image:url('../img/csol_logo_sm.png'); + height:150px; + background-position:top center; + } + .navbar-inner > .container { + width:100%; + } .form-horizontal { .control-label { text-align:left; @@ -323,11 +341,19 @@ and (max-width : 599px) { .nav-wrap { width:90%; margin:0 auto; - ul.nav { - li { + border-radius:5px; + ul.nav, #dynWrap { + li, li.active { display:block; - a { - padding: 5px 0; + a, a:visited, a:hover { + font-size:14px; + padding: 7px 0; + text-transform:capitalize; + line-height:16px; + color:#000; + text-decoration:none; + display:block; + font-weight:400; } } li:nth-child(even), @@ -707,32 +733,59 @@ input[type="password"].metered { } } -/* ------------------------------ */ -/* Mobile : width > iphone ------ */ -/* ------------------------------ */ -@media only screen -and (min-width : 321px) -and (max-width : 940px ) { - .navbar .brand { - background-image: url('../img/csol_logo_480.png'); - height:166px; - } -} - -/* ------------------------------ */ -/* Mobile : width <= iphone ----- */ -/* ------------------------------ */ -@media only screen -and (max-width : 320px) { - .navbar .brand { - background-image: url('../img/csol_logo_320.png'); - height:116px; - } -} - /* ------------------------------ */ /* CSOL-site SPECIFIC ----------- */ /* ------------------------------ */ +body { + .navbar.filter { + label, select, input { + display:block; + float:left; + } + select { + margin-right:25px; + } + label { + background: url('../img/icon-sprite.png') no-repeat top left; + width:30px; + height:30px; + text-indent:-9000px; + margin-bottom:0px; + margin-top:5px; + &.filter-age { + background-position: 0 -160px; + } + &.filter-category { + background-position: 0 -640px; + } + &.filter-org { + background-position: 0 -480px; + } + &.filter-activity { + background-position: 0 -720px; + } + } + } +} + +/* ------------------------------ */ +/* Mobile : general ------------ */ +/* ------------------------------ */ +@media only screen +and (max-width : 599px) { +body { + .navbar.filter { + .selectWrapper, input { + clear:left; + margin:auto; + text-align:center; + width:180px; + display:block; + float:none; + } + } +} +} /* ------------------------------ */ /* Mobile : width <= iphone ---- */ @@ -1053,7 +1106,6 @@ body.home { /* Landing page : mobile -------- */ /* ------------------------------ */ @media only screen -and (min-width : 320px) and (max-width : 599px) { body.home { background-image:url('../img/chalkboard_bg.jpg'); @@ -1105,3 +1157,17 @@ and (max-width : 599px) { } } } + +/* ------------------------------ */ +/* Filter sprite positions ------ */ +/* ------------------------------ */ +.sprite-activitylines{ background-position: 0 0; width: 30px; height: 30px; } +.sprite-activitytype{ background-position: 0 -80px; width: 30px; height: 30px; } +.sprite-age{ background-position: 0 -160px; width: 30px; height: 30px; } +.sprite-badgetype{ background-position: 0 -240px; width: 30px; height: 30px; } +.sprite-date{ background-position: 0 -320px; width: 30px; height: 30px; } +.sprite-location{ background-position: 0 -400px; width: 30px; height: 30px; } +.sprite-organization{ background-position: 0 -480px; width: 30px; height: 30px; } +.sprite-search{ background-position: 0 -560px; width: 30px; height: 30px; } +.sprite-topic{ background-position: 0 -640px; width: 30px; height: 30px; } +.sprite-type{ background-position: 0 -720px; width: 30px; height: 30px; } diff --git a/views/badges/single.html b/views/badges/single.html index 53a132e..d27d2f8 100644 --- a/views/badges/single.html +++ b/views/badges/single.html @@ -2,7 +2,7 @@ {% set pageTitle = badge.name %} {% block content %} -
    +
    @@ -10,15 +10,17 @@

    What is this badge about?

    {{ badge.description }}

    -

    How can you earn it?

    + {% if not user or user.type == 'learner' %} +

    How can you earn it?

    -

    - {% if badge.activityType == 'offline' %} - Claim this badge - {% else %} - Apply - {% endif %} -

    +

    + {% if badge.activityType == 'offline' %} + Claim this badge + {% else %} + Apply + {% endif %} +

    + {% endif %}