Merge remote-tracking branch 'origin/master'

This commit is contained in:
Chris McAvoy 2013-06-04 14:18:50 -05:00
Родитель 5d11dcd0f1 3beab786f2
Коммит 346cdde9f6
15 изменённых файлов: 341 добавлений и 89 удалений

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -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 : ""));
}
}

4
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();

Просмотреть файл

@ -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);

Просмотреть файл

@ -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);

Просмотреть файл

@ -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",

13
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'

Просмотреть файл

@ -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;
}

Двоичные данные
static/media/img/chi.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 15 KiB

После

Ширина:  |  Высота:  |  Размер: 20 KiB

Двоичные данные
static/media/img/icon-sprite.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
static/media/img/mac.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.8 KiB

После

Ширина:  |  Высота:  |  Размер: 4.7 KiB

Двоичные данные
static/media/img/moz.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 743 B

После

Ширина:  |  Высота:  |  Размер: 2.3 KiB

Просмотреть файл

@ -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 = $('<div class="selectWrapper"></div>').append(this,selectEle);
$('.navbar.filter form').prepend(selectWrap);
});
}
/*landing page overrides*/
if($('body.home').length != 0) {
var vidLink = $('<a href="#">watch video</a>').click(function(){
if($('#i_vid').length == 0) {
var bkgFade = $('<div id="bkg_fade" style="display:none;"></div>');
@ -30,6 +43,7 @@ if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) mob
$('<p id="rahm">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.</p>').prependTo('.footer .upper');
$('<div id="bubbles"><span class="lt">join the conversation on <a href="#">Facebook</a>.</span><span class="rt">share stories</span></div>').appendTo('.footer .upper');
/*landing page mobile overrides*/
if(mob) {
vidLink = '<a href="http://www.youtube.com/v/6WwpwtYNsNk">watch video</a>';
}
@ -43,5 +57,24 @@ if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) mob
$('li.badges a').append('<span> Badges &</span>');
$('li.about a').append('<span> the program</span>')
$('li.challenges a').append('<span> your future.</span>');
} else {
/*non-landing page overrides*/
if(mob) {
var dynWrap = $('<div id="dynWrap" style="display:none;"></div>');
var dynList = $('<li id="dyn"></li>');
var dynLink = $('<a href="#" title="">Menu</a>').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");
}
});
}
}
});

Просмотреть файл

@ -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; }

Просмотреть файл

@ -2,7 +2,7 @@
{% set pageTitle = badge.name %}
{% block content %}
<div class="row">
<div class="row-fluid">
<div class="span4">
<img src="{{ badge.image }}">
</div>
@ -10,15 +10,17 @@
<h3>What is this badge about?</h3>
<p>{{ badge.description }}</p>
<h3>How can you earn it?</h3>
{% if not user or user.type == 'learner' %}
<h3>How can you earn it?</h3>
<p class="text-right">
{% if badge.activityType == 'offline' %}
<a href="/claim" class="btn">Claim this badge</a>
{% else %}
<a href="{{ badge.url }}/apply" class="btn">Apply</a>
{% endif %}
</p>
<p class="text-right">
{% if badge.activityType == 'offline' %}
<a href="/claim" class="btn">Claim this badge</a>
{% else %}
<a href="{{ badge.url }}/apply" class="btn">Apply</a>
{% endif %}
</p>
{% endif %}
</div>
</div>