зеркало из https://github.com/mozilla/CSOL-site.git
Merge branch 'master' of https://github.com/mozilla/CSOL-site
Conflicts: static/media/css/core.css static/media/less/core.less
This commit is contained in:
Коммит
2db47aa9bb
24
README.md
24
README.md
|
@ -4,14 +4,18 @@ The website for the Chicago Summer of Learning, developed by Ocupop and Mozilla.
|
|||
|
||||
## Environment
|
||||
|
||||
Property | Default | Description
|
||||
----------------|----------|-------------------------
|
||||
`CSOL_DB_NAME` | `"csol"` | Name of the database.
|
||||
`CSOL_DB_USER` | `"root"` | Database username.
|
||||
`CSOL_DB_PASS` | `null` | Database password.
|
||||
`CSOL_DB_HOST` | `null` | Database host.
|
||||
`CSOL_DB_PORT` | `null` | Database port.
|
||||
`CSOL_HOST` | `null` | Canonical CSOL host (eg chicagosummeroflearning.org)
|
||||
`COOKIE_SECRET` | `null` | Seed for session cookie.
|
||||
`CSOL_OPENBADGER_URL` | `null` | Openbadger API Location, http://obr.com/v2/
|
||||
Property | Default | Description
|
||||
------------------|----------|-------------------------
|
||||
`CSOL_DB_NAME` | `"csol"` | Name of the database.
|
||||
`CSOL_DB_USER` | `"root"` | Database username.
|
||||
`CSOL_DB_PASS` | `null` | Database password.
|
||||
`CSOL_DB_HOST` | `null` | Database host.
|
||||
`CSOL_DB_PORT` | `null` | Database port.
|
||||
`CSOL_AWS_KEY` | `null` | AWS key (for storing uploads)
|
||||
`CSOL_AWS_SECRET` | `null` | AWS secret
|
||||
`CSOL_AWS_REGION` | `null` | AWS region (optional)
|
||||
`CSOL_AWS_BUCKET` | `null` | AWS bucket
|
||||
`CSOL_HOST` | `null` | Canonical CSOL host (eg chicagosummeroflearning.org)
|
||||
`COOKIE_SECRET` | `null` | Seed for session cookie.
|
||||
`CSOL_OPENBADGER_URL` | `null` | Openbadger API Location, http://obr.com/v2/
|
||||
`CSOL_OPENBADGER_SECRET` | `null` | A shared secret with Open Badger. Should match the OPENBADGER_JWT_SECRET variable on open badger
|
||||
|
|
|
@ -266,8 +266,33 @@ function processStandardLearnerSignup (req, res, next) {
|
|||
module.exports = function (app) {
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.locals.user = req.session.user;
|
||||
next();
|
||||
if (!req.session.user) {
|
||||
res.locals.user = undefined;
|
||||
return next();
|
||||
}
|
||||
|
||||
var user = req.session.user,
|
||||
model = db.model(user.type);
|
||||
|
||||
model.find(user.id)
|
||||
.complete(function (err, dbUser) {
|
||||
if (err)
|
||||
console.log('Error loading user:', err);
|
||||
|
||||
if (!dbUser) {
|
||||
console.log('Could not find user "' + user.name + '" in database');
|
||||
clearUser(req, res);
|
||||
return next();
|
||||
}
|
||||
|
||||
_.functions(dbUser).forEach(function(method) {
|
||||
if (/^(get|set|add|remove|has)[A-Z]/.test(method))
|
||||
user[method] = dbUser[method].bind(dbUser);
|
||||
});
|
||||
|
||||
res.locals.user = user;
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/login', function (req, res, next) {
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
var async = require('async');
|
||||
var badger = require('../openbadger');
|
||||
var db = require('../db');
|
||||
var errors = require('../lib/errors');
|
||||
var mime = require('mime');
|
||||
var _ = require('underscore');
|
||||
|
||||
var applications = db.model('Application');
|
||||
var evidence = db.model('Evidence');
|
||||
|
||||
module.exports = function (app) {
|
||||
|
||||
|
@ -132,6 +140,114 @@ module.exports = function (app) {
|
|||
return res.redirect('/login', 303);
|
||||
});
|
||||
|
||||
app.param('evidenceSlug', function (req, res, next, slug) {
|
||||
var parts = /^([a-z0-9]+?)(?:_(thumb))?$/.exec(slug);
|
||||
var shouldAuthenticate = (req.method !== 'GET');
|
||||
|
||||
if (!parts)
|
||||
return next(new errors.NotFound());
|
||||
|
||||
if (shouldAuthenticate && !req.session.user)
|
||||
return next(new errors.Forbidden());
|
||||
|
||||
var key = parts[1],
|
||||
thumb = !!parts[2];
|
||||
|
||||
evidence.find({where: {key: key}})
|
||||
.complete(function (err, instance) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!instance)
|
||||
return next(new errors.NotFound());
|
||||
|
||||
req.params.evidence = instance;
|
||||
req.params.thumb = thumb;
|
||||
|
||||
instance.getApplication()
|
||||
.complete(function (err, application) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
req.params.application = application;
|
||||
|
||||
// We'll need to decide how to authenticate external services
|
||||
// like, for example, Aestimia. For now, restrict access to either
|
||||
// the learner who uploaded it, or their guardian
|
||||
|
||||
if (!shouldAuthenticate)
|
||||
return next();
|
||||
|
||||
application.getLearner()
|
||||
.complete(function (err, learner) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (learner.id === req.session.user.id)
|
||||
return next();
|
||||
|
||||
learner.getGuardian()
|
||||
.complete(function (err, guardian) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
if (!guardian || guardian.id !== req.session.user.id)
|
||||
return next(new errors.Forbidden());
|
||||
|
||||
return next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/evidence/:evidenceSlug', function (req, res, next) {
|
||||
var evidence = req.params.evidence,
|
||||
thumb = req.params.thumb;
|
||||
|
||||
res.type(evidence.mediaType);
|
||||
res.header('Vary', 'Cookie');
|
||||
res.header('Cache-Control', 'max-age=2419200'); // 4 weeks
|
||||
res.header('Last-Modified', evidence.updatedAt);
|
||||
|
||||
evidence[thumb ? 'fetchThumb' : 'fetch'](function (remote) {
|
||||
remote
|
||||
.on('response', function(proxy) {
|
||||
proxy.pipe(res);
|
||||
})
|
||||
.end();
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/evidence/:evidenceSlug', function (req, res, next) {
|
||||
var evidence = req.params.evidence,
|
||||
application = req.params.application,
|
||||
thumb = req.params.thumb;
|
||||
|
||||
if (thumb)
|
||||
return next(new errors.NotAllowed());
|
||||
|
||||
if (!req.body.action || req.body.action !== 'delete')
|
||||
return next(new errors.NotAllowed());
|
||||
|
||||
if (application.state !== 'open')
|
||||
return next(new errors.NotAllowed());
|
||||
|
||||
evidence.destroy()
|
||||
.complete(function (err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
evidence.getApplication()
|
||||
.complete(function (err, application) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
return res.redirect('/earn/' + application.badgeId + '/apply');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
app.param('badgeName', function (req, res, next, badgeName) {
|
||||
badger.getBadge(badgeName, function(err, data) {
|
||||
if (err)
|
||||
|
@ -159,6 +275,99 @@ module.exports = function (app) {
|
|||
});
|
||||
});
|
||||
|
||||
app.get('/earn/:badgeName/apply', function (req, res, next) {
|
||||
var badge = req.params.badge;
|
||||
|
||||
if (!req.session.user)
|
||||
return res.redirect('/login');
|
||||
|
||||
applications.findOrCreate({
|
||||
badgeId: badge.id,
|
||||
LearnerId: req.session.user.id
|
||||
})
|
||||
.complete(function(err, application) {
|
||||
if (err || !application)
|
||||
return next(err || new Error('There was a problem loading your application'));
|
||||
|
||||
application.getEvidence()
|
||||
.complete(function(err, evidence) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
var state = evidence.length ? application.state : 'new';
|
||||
|
||||
res.render('applications/' + state + '.html', {
|
||||
evidence: evidence,
|
||||
application: application,
|
||||
badge: badge
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/earn/:badgeName/apply', function (req, res, next) {
|
||||
var badge = req.params.badge;
|
||||
|
||||
if (!req.session.user)
|
||||
return res.redirect(badge.url);
|
||||
|
||||
function finish (err, evidence) {
|
||||
if (req.xhr) {
|
||||
return res.json({
|
||||
status: err ? 'failed' : 'ok',
|
||||
message: err || null,
|
||||
evidence: evidence || []
|
||||
});
|
||||
}
|
||||
|
||||
if (err)
|
||||
req.flash('error', err);
|
||||
|
||||
res.redirect(badge.url + '/apply');
|
||||
}
|
||||
|
||||
applications.find({where: {
|
||||
badgeId: badge.id,
|
||||
LearnerId: req.session.user.id
|
||||
}})
|
||||
.complete(function(err, application) {
|
||||
if (err || !application)
|
||||
return finish(err);
|
||||
|
||||
if (req.body.action === 'apply')
|
||||
return application.submit(finish);
|
||||
|
||||
if ('description' in req.body) {
|
||||
application.updateAttributes({
|
||||
description: req.body.description
|
||||
});
|
||||
}
|
||||
|
||||
var files = (req.files||{}).media;
|
||||
|
||||
if (!files)
|
||||
return finish();
|
||||
|
||||
if (!_.isArray(files))
|
||||
files = [files];
|
||||
|
||||
async.map(files, function (file, callback) {
|
||||
application.process(file, function (err, item) {
|
||||
if (err || !item)
|
||||
return callback(err);
|
||||
|
||||
callback(null, {
|
||||
type: item.mediaType,
|
||||
thumbnail: item.getThumbnailUrl(),
|
||||
location: item.getLocationUrl(),
|
||||
original: item.original
|
||||
});
|
||||
});
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/earn/:badgeName/claim', function (req, res, next) {
|
||||
res.render('badges/claim.html');
|
||||
});
|
||||
|
|
7
db.js
7
db.js
|
@ -63,10 +63,12 @@ db.model = function(name) {
|
|||
|
||||
var definition = require(path.join(MODEL_PATH, normalized)),
|
||||
properties = definition.properties,
|
||||
relationships = definition.relationships;
|
||||
relationships = definition.relationships,
|
||||
setup = definition.setup;
|
||||
|
||||
delete definition.properties;
|
||||
delete definition.relationships;
|
||||
delete definition.setup;
|
||||
|
||||
var model = db.define(name, properties, definition);
|
||||
// We need to cache the model before resolving any relationships, so that it
|
||||
|
@ -86,6 +88,9 @@ db.model = function(name) {
|
|||
model[type](relatedModel, relationship);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof setup === 'function')
|
||||
setup(model);
|
||||
}
|
||||
|
||||
return modelCache[key];
|
||||
|
|
|
@ -89,7 +89,9 @@ var BadRequest = createExceptionType('BadRequest', 400);
|
|||
var Unauthorized = createExceptionType('Unauthorized', 401);
|
||||
var Forbidden = createExceptionType('Forbidden', 403);
|
||||
var NotFound = createExceptionType('NotFound', 404);
|
||||
var NotAllowed = createExceptionType('MethodNotAllowed', 405);
|
||||
var Conflict = createExceptionType('Conflict', 409);
|
||||
var Unsupported = createExceptionType('UnsupportedMediaType', 415);
|
||||
var Unknown = createExceptionType('Internal', 500);
|
||||
var NotImplemented = createExceptionType('NotImplemented', 501);
|
||||
var BadGateway = createExceptionType('BadGateway', 502);
|
||||
|
@ -98,6 +100,9 @@ module.exports.BadRequest = BadRequest;
|
|||
module.exports.Unauthorized = Unauthorized;
|
||||
module.exports.Forbidden = Forbidden;
|
||||
module.exports.NotFound = NotFound;
|
||||
module.exports.NotAllowed = NotAllowed;
|
||||
module.exports.Conflict = Conflict;
|
||||
module.exports.Unsupported = Unsupported;
|
||||
module.exports.Unknown = Unknown;
|
||||
module.exports.NotImplemented = NotImplemented;
|
||||
module.exports.BadGateway = BadGateway;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
var exec = require('child_process').exec;
|
||||
var im = require('imagemagick');
|
||||
var path = require('path');
|
||||
|
||||
var imageThumb = function (input, output, format, width, height, callback) {
|
||||
if (typeof height === 'function') {
|
||||
callback = height;
|
||||
height = null;
|
||||
}
|
||||
|
||||
return im.crop({
|
||||
srcPath: input,
|
||||
dstPath: output,
|
||||
width: width,
|
||||
height: height,
|
||||
format: format
|
||||
}, callback);
|
||||
}
|
||||
|
||||
var videoThumb = function (input, output, format, width, height, callback) {
|
||||
if (typeof height === 'function') {
|
||||
callback = height;
|
||||
height = '?';
|
||||
}
|
||||
|
||||
function escapePath (str) {
|
||||
return '"' + path.normalize(str.replace(/(["\s'$`\\])/g,'\\$1')) + '"';
|
||||
}
|
||||
|
||||
if (output)
|
||||
output = escapePath(output);
|
||||
else
|
||||
output = 'pipe:' + format;
|
||||
|
||||
// Ideally, we'd be doing this via some library, but I'm yet to find one
|
||||
// that seems to allow for buffer output, rather than saving to file.
|
||||
|
||||
var args = [
|
||||
'-loglevel', 0, // Turn off output
|
||||
'-i', escapePath(input), // Use input file
|
||||
'-vframes', 1, // Use only one frame
|
||||
'-ss', '00:00:02', // Taken from two seconds in
|
||||
'-s', width + 'x' + height, // Thumbnail dimensions
|
||||
'-f', 'image2', // Set commands file
|
||||
output // Output
|
||||
];
|
||||
|
||||
var cmd = 'ffmpeg ' + args.join(' ');
|
||||
|
||||
return exec(cmd, {encoding: 'binary'}, callback);
|
||||
}
|
||||
|
||||
module.exports.image = imageThumb;
|
||||
module.exports.video = videoThumb;
|
|
@ -0,0 +1,173 @@
|
|||
var async = require('async');
|
||||
var errors = require('../lib/errors');
|
||||
var db = require('../db');
|
||||
var mime = require('mime');
|
||||
var path = require('path');
|
||||
var s3 = require('../s3');
|
||||
var thumbs = require('../lib/thumbs');
|
||||
|
||||
// We'll set this when we're done
|
||||
var evidence;
|
||||
|
||||
var ALLOWED_TYPES = ['image', 'video'];
|
||||
|
||||
module.exports = {
|
||||
setup: function () {
|
||||
evidence = db.model('Evidence');
|
||||
},
|
||||
properties: {
|
||||
id: {
|
||||
type: db.type.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
badgeId: {
|
||||
type: db.type.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
description: {
|
||||
type: db.type.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
state: {
|
||||
type: db.type.ENUM,
|
||||
values: [
|
||||
'open', // This application is being worked on
|
||||
'waiting', // This application is waiting for guardian approval (where applicable)
|
||||
'submitted', // This application has been submitted for review
|
||||
'rejected', // This application has been rejected
|
||||
'accepted' // This application has been accepted
|
||||
],
|
||||
defaultValue: 'open',
|
||||
allowNull: false
|
||||
},
|
||||
submissionId: {
|
||||
type: db.type.STRING,
|
||||
allowNull: true
|
||||
}
|
||||
},
|
||||
relationships: [
|
||||
{
|
||||
model: 'Learner',
|
||||
type: 'belongsTo'
|
||||
},
|
||||
{
|
||||
model: 'Evidence',
|
||||
type: 'hasMany',
|
||||
as: 'Evidence'
|
||||
}
|
||||
],
|
||||
instanceMethods: {
|
||||
submit: function (force, callback) {
|
||||
if (typeof force === 'function') {
|
||||
callback = force;
|
||||
force = false;
|
||||
}
|
||||
|
||||
var application = this;
|
||||
|
||||
application.getEvidence().complete(function (err, items) {
|
||||
if (err || !items || !items.length)
|
||||
return callback(err);
|
||||
|
||||
application.getLearner().complete(function (err, learner) {
|
||||
if (err || !learner)
|
||||
return callback(err);
|
||||
|
||||
if (learner.underage && !force) {
|
||||
return application.updateAttributes({
|
||||
state: 'waiting'
|
||||
}).complete(callback);
|
||||
}
|
||||
|
||||
// TO DO - call aestimia service
|
||||
|
||||
application.updateAttributes({
|
||||
state: 'submitted'
|
||||
}).complete(callback);
|
||||
});
|
||||
});
|
||||
},
|
||||
process: function (file, callback) {
|
||||
if (!file || !file.size)
|
||||
return callback();
|
||||
|
||||
var application = this,
|
||||
type = file.type.split('/')[0].toLowerCase();
|
||||
|
||||
if (ALLOWED_TYPES.indexOf(type) < 0)
|
||||
return callback(new errors.Unsupported(file.name + ' is not of a supported file type'));
|
||||
|
||||
function saveFile (path, callback) {
|
||||
s3.putFile(file.path, path, {
|
||||
'Content-Type': file.type
|
||||
}, function (err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function saveThumbnail (path, callback) {
|
||||
thumbs[type](file.path, null, 'png', 150, 150, function (err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
s3.putBuffer(new Buffer(data, 'binary'), path, {
|
||||
'Content-Type': 'image/png'
|
||||
}, function (err, data) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
application.getLearner().complete(function(err, learner) {
|
||||
if (err || !learner)
|
||||
return callback(err);
|
||||
|
||||
var key = file.path.split('/').pop(),
|
||||
prefix = learner.username,
|
||||
format = mime.extension(file.type) || path.extname(file.name).substr(1),
|
||||
filePath = '/' + prefix + '/' + key + '.' + format,
|
||||
thumbPath = '/' + prefix + '/' + key + '_thumb.png';
|
||||
|
||||
evidence.create({
|
||||
key: key,
|
||||
mediaType: file.type,
|
||||
location: filePath,
|
||||
thumbnail: thumbPath,
|
||||
original: file.name
|
||||
}).complete(function (err, instance) {
|
||||
if (err || !instance)
|
||||
return callback(err);
|
||||
|
||||
saveThumbnail(thumbPath, function (err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
application.addEvidence(instance)
|
||||
.complete(function (err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
callback(null, instance);
|
||||
});
|
||||
});
|
||||
|
||||
saveFile(filePath, function (err) {
|
||||
if (err)
|
||||
return;
|
||||
|
||||
instance.updateAttributes({
|
||||
saved: true
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
var db = require('../db');
|
||||
var s3 = require('../s3');
|
||||
|
||||
module.exports = {
|
||||
properties: {
|
||||
id: {
|
||||
type: db.type.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
key: {
|
||||
type: db.type.STRING,
|
||||
allowNull: false,
|
||||
unique: true
|
||||
},
|
||||
mediaType: {
|
||||
type: db.type.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
location: {
|
||||
type: db.type.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
thumbnail: {
|
||||
type: db.type.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
original: {
|
||||
type: db.type.STRING,
|
||||
allowNull: true
|
||||
},
|
||||
saved: {
|
||||
type: db.type.BOOLEAN,
|
||||
defaultValue: false
|
||||
}
|
||||
},
|
||||
relationships: [
|
||||
{
|
||||
model: 'Application',
|
||||
type: 'belongsTo'
|
||||
}
|
||||
],
|
||||
instanceMethods: {
|
||||
fetch: function (callback) {
|
||||
// Returns an HTTP(S) request
|
||||
callback(s3.get(this.location));
|
||||
},
|
||||
fetchThumb: function (callback) {
|
||||
// Returns an HTTP(S) request
|
||||
callback(s3.get(this.thumbnail));
|
||||
},
|
||||
getLocationUrl: function () {
|
||||
return '/evidence/' + this.key;
|
||||
},
|
||||
getThumbnailUrl: function () {
|
||||
return '/evidence/' + this.key + '_thumb';
|
||||
}
|
||||
}
|
||||
};
|
|
@ -42,6 +42,10 @@ module.exports = {
|
|||
{
|
||||
model: 'Guardian',
|
||||
type: 'belongsTo'
|
||||
},
|
||||
{
|
||||
model: 'Application',
|
||||
type: 'hasMany'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
"bcrypt": "~0.7.5",
|
||||
"connect-flash": "~0.1.1",
|
||||
"express": "~3.1.0",
|
||||
"imagemagick": "~0.1.3",
|
||||
"knox": "~0.8.2",
|
||||
"mime": "~1.2.9",
|
||||
"mysql": "~2.0.0-alpha7",
|
||||
"nunjucks": "~0.1.8a",
|
||||
"request": "~2.21.0",
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
var knox = require('knox');
|
||||
|
||||
var s3 = knox.createClient({
|
||||
key: process.env["CSOL_AWS_KEY"],
|
||||
secret: process.env["CSOL_AWS_SECRET"],
|
||||
region: process.env["CSOL_AWS_REGION"],
|
||||
bucket: process.env["CSOL_AWS_BUCKET"]
|
||||
});
|
||||
|
||||
module.exports = s3;
|
|
@ -39,6 +39,11 @@ ol {
|
|||
padding: 0 0 0 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
ul,
|
||||
ol {
|
||||
padding: 0 0 0 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
.row,
|
||||
[class*="span"] {
|
||||
margin-left: 0px;
|
||||
|
@ -189,11 +194,11 @@ ol {
|
|||
.footer ul li:first-child a {
|
||||
margin-left: 0px;
|
||||
}
|
||||
.footer ul li.nth-child(even) {
|
||||
.footer ul li:nth-child(even) {
|
||||
border-left: 1px solid #fff;
|
||||
border-right: 1px solid #fff;
|
||||
}
|
||||
.footer ul li.last-child {
|
||||
.footer ul li:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
/*sticky footer*/
|
||||
|
@ -227,6 +232,7 @@ ol {
|
|||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
figure.thumbnail {
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
@ -244,6 +250,169 @@ figure.thumbnail .caption p:first-child {
|
|||
color: #000;
|
||||
border-left: inherit;
|
||||
border-right: inherit;
|
||||
=======
|
||||
/*Evidence uploading / application*/
|
||||
#application-review .well {
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
#application-review .rubric {
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
#application-review .rubric li {
|
||||
white-space: pre-line;
|
||||
list-style: none;
|
||||
border-left: solid 5px #DDD;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#application-review .rubric li.required {
|
||||
border-color: #BBB;
|
||||
}
|
||||
#application-review .rubric li.required .note {
|
||||
font-style: italic;
|
||||
}
|
||||
#edit-application {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#edit-application .items {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
border: solid 1px #CCC;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
#edit-application .item {
|
||||
padding: 9.5px;
|
||||
position: relative;
|
||||
border-top: solid 1px #DDD;
|
||||
margin: 0;
|
||||
background: #F5F5F5;
|
||||
}
|
||||
#edit-application .item:first-child {
|
||||
border-top: none;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
#edit-application .item:nth-child(even) {
|
||||
background: #F0F0F0;
|
||||
}
|
||||
#edit-application .item input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
#edit-application .item label {
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#edit-application .item .description span {
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#edit-application .item .description span em {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#edit-application .item .filename {
|
||||
padding: 5px 30px 5px 5px;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#edit-application .item .remove {
|
||||
position: absolute;
|
||||
top: 9.5px;
|
||||
right: 9.5px;
|
||||
padding: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
#edit-application .item .progress {
|
||||
margin: 0;
|
||||
height: 10px;
|
||||
}
|
||||
#edit-application .buttons {
|
||||
border: solid 1px #DDD;
|
||||
border-top-color: #CCC;
|
||||
padding: 9.5px;
|
||||
margin: 0;
|
||||
border-radius: 0 0 4px 4px;
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
box-shadow: inset 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
#edit-application .buttons .btn {
|
||||
margin-left: 9.5px;
|
||||
}
|
||||
#edit-application.advanced .item input {
|
||||
position: absolute;
|
||||
right: 200%;
|
||||
opacity: 0;
|
||||
}
|
||||
#evidence .item {
|
||||
position: relative;
|
||||
}
|
||||
#evidence .thumbnail {
|
||||
background: #FFF;
|
||||
}
|
||||
#evidence .processing::after {
|
||||
content: "Processing";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
padding: 2px 5px;
|
||||
background: #FFF;
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
text-align: center;
|
||||
border-bottom: solid 1px #999;
|
||||
}
|
||||
#evidence img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 150px;
|
||||
min-height: 150px;
|
||||
margin: 0;
|
||||
}
|
||||
#evidence form {
|
||||
margin: 0;
|
||||
}
|
||||
#evidence label {
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
right: -6px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: url('../images/delete.png') 50% 50% no-repeat;
|
||||
text-indent: -999em;
|
||||
margin: 0;
|
||||
}
|
||||
.upload-list {
|
||||
list-style: none;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.upload-list li {
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
.upload-list .details {
|
||||
position: relative;
|
||||
}
|
||||
.upload-list .details .meta {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
.upload-list .details .filename {
|
||||
font-weight: bold;
|
||||
}
|
||||
.upload-list .details .progress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.upload-list .details .progress .bar {
|
||||
opacity: 0.5;
|
||||
>>>>>>> 6d558fac85b71c2f1a353963a78431eb0ecc73c0
|
||||
}
|
||||
/*landing page specific*/
|
||||
body.home {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300);
|
||||
html,body{height:100%;font-family:'Open Sans',sans-serif;font-weight:300;line-height:18px;}
|
||||
body{margin:0px;padding:0px;}body .container>br{display:none;}
|
||||
#main{padding-top:45px;padding-bottom:25px;}#main>h1:first-child,#main>h2:first-child,#main>h3:first-child,#main>h4:first-child,#main>p:first-child{margin-top:0px;padding-top:0px;}
|
||||
#main>div>h1:first-child,#main>div>h2:first-child,#main>div>h3:first-child,#main>div>h4:first-child,#main>div>p:first-child{margin-top:0px;padding-top:0px;}
|
||||
ul,ol{padding:0 0 0 0;margin:0 0 0 0;}
|
||||
ul,ol{padding:0 0 0 0;margin:0 0 0 0;}
|
||||
.row,[class*="span"]{margin-left:0px;}
|
||||
.navbar .nav{float:none;}.navbar .nav>li.dropdown.open>.dropdown-toggle{background-color:inherit;text-decoration:underline;}
|
||||
.navbar .nav>li>a{border-left:none;border-right:none;}
|
||||
.navbar .nav>li>a:hover,.navbar .nav>li>a:focus{background-color:inherit;border-left:none;border-right:none;}
|
||||
.navbar .nav>li:nth-child(even){border-left:1px solid #c0c0c0;border-right:1px solid #c0c0c0;}
|
||||
.navbar .nav>.navbar .nav>li:last-child{border-right:none;}
|
||||
.navbar .nav .active a,.navbar .nav .active a:hover,.navbar .nav .active a:focus{background-color:white;box-shadow:none;}
|
||||
.navbar .navbar-inner{background-image:url('../img/chalkboard_bg.jpg');-webkit-box-shadow:inset 0px -10px 20px 0px rgba(0, 0, 0, 0.25);-moz-box-shadow:inset 0px -10px 20px 0px rgba(0, 0, 0, 0.25);box-shadow:inset 0px -10px 20px 0px rgba(0, 0, 0, 0.25);padding-top:25px;}
|
||||
.navbar .nav-wrap{width:100%;padding:0 0 0 0;margin:0 0 0 0;width:940px;margin-bottom:-24px;-webkit-box-shadow:0 0 8px 3px rgba(0, 0, 0, 0.25);-moz-box-shadow:0 0 8px 3px rgba(0, 0, 0, 0.25);box-shadow:0 0 8px 3px rgba(0, 0, 0, 0.25);background:white;text-align:center;}.navbar .nav-wrap ul{display:inline-block;margin:0 0 0 0;}.navbar .nav-wrap ul>li{float:none;display:inline-block;}.navbar .nav-wrap ul>li>a{text-shadow:none;color:#333333;text-transform:uppercase;}
|
||||
.navbar .nav-wrap ul>li>a:focus,.navbar .nav-wrap ul>li>a:hover{color:#c0c0c0;}
|
||||
.navbar .nav-wrap ul>li:last-child{border-right:none;}
|
||||
.navbar .brand{display:block;width:671px;height:220px;background-image:url('../img/csol_logo.png');background-repeat:no-repeat;margin:0 auto;float:none;text-indent:-9000px;}
|
||||
.footer a{color:#fff;}
|
||||
.footer a.logo{text-indent:-9000px;width:82px;height:82px;display:block;background-position:center center;background-repeat:no-repeat;}
|
||||
.footer a.logo.chi{background-image:url('../img/chi.png');}
|
||||
.footer a.logo.mac{background-image:url('../img/mac.png');}
|
||||
.footer a.logo.moz{background-image:url('../img/moz.png');}
|
||||
.footer a:hover{color:#c0c0c0;text-decoration:none;}
|
||||
.footer .upper{padding:50px 0 0 0;}.footer .upper p{background-image:url('../img/csol_logo_sm.png');padding-left:209px;background-repeat:no-repeat;background-position:top left;width:400px;min-height:131px;margin-bottom:20px;}
|
||||
.footer .upper li{border-left:none;border-right:none;}
|
||||
.footer .lower{border-top:1px solid white;padding:25px 0 0 0;}
|
||||
.footer ul li{display:inline-block;}.footer ul li>a,.footer ul li>span{margin:10px;}
|
||||
.footer ul li:first-child a{margin-left:0px;}
|
||||
.footer ul li:nth-child(even){border-left:1px solid #fff;border-right:1px solid #fff;}
|
||||
.footer ul li:last-child{border-right:none;}
|
||||
.wrapper{width:100%;}.wrapper .inner-wrapper{width:100%;}
|
||||
.wrapper.primary{min-height:100%;height:auto !important;height:100%;margin:0px 0px -250px 0px;}.wrapper.primary .inner-wrapper{padding:0px 0px 250px 0px;}
|
||||
.wrapper.secondary{position:relative;color:#fff;height:250px;background-image:url('../img/background-chalkboard-green.jpg');background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/background-chalkboard-green.jpg', sizingMethod='scale');-ms-filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/background-chalkboard-green.jpg', sizingMethod='scale')";overflow:visible;}
|
||||
.poster a,.poster img{display:block;margin-left:auto;margin-right:auto;}
|
||||
#menu-login-form{padding:10px;text-align:left;}
|
||||
#application-review .well{margin-left:-20px;margin-right:-20px;}
|
||||
#application-review .rubric{margin:0 0 20px;}#application-review .rubric li{white-space:pre-line;list-style:none;border-left:solid 5px #DDD;padding-left:10px;margin-bottom:20px;}#application-review .rubric li.required{border-color:#BBB;}#application-review .rubric li.required .note{font-style:italic;}
|
||||
#edit-application{margin-bottom:20px;}#edit-application .items{list-style:none;margin:0;border:solid 1px #CCC;border-radius:4px 4px 0 0;}
|
||||
#edit-application .item{padding:9.5px;position:relative;border-top:solid 1px #DDD;margin:0;background:#F5F5F5;}#edit-application .item:first-child{border-top:none;border-radius:4px 4px 0 0;}
|
||||
#edit-application .item:nth-child(even){background:#F0F0F0;}
|
||||
#edit-application .item input{display:block;width:100%;}
|
||||
#edit-application .item label{display:block;margin-bottom:0;}
|
||||
#edit-application .item .description span{text-align:center;display:block;margin-bottom:10px;}#edit-application .item .description span em{display:block;margin-top:5px;}
|
||||
#edit-application .item .filename{padding:5px 30px 5px 5px;white-space:pre;overflow:hidden;text-overflow:ellipsis;}
|
||||
#edit-application .item .remove{position:absolute;top:9.5px;right:9.5px;padding:0;width:20px;height:20px;}
|
||||
#edit-application .item .progress{margin:0;height:10px;}
|
||||
#edit-application .buttons{border:solid 1px #DDD;border-top-color:#CCC;padding:9.5px;margin:0;border-radius:0 0 4px 4px;background:rgba(255, 255, 255, 0.25);box-shadow:inset 1px 1px 2px rgba(0, 0, 0, 0.1);}#edit-application .buttons .btn{margin-left:9.5px;}
|
||||
#edit-application.advanced .item input{position:absolute;right:200%;opacity:0;}
|
||||
#evidence .item{position:relative;}
|
||||
#evidence .thumbnail{background:#FFF;}
|
||||
#evidence .processing::after{content:"Processing";position:absolute;top:4px;left:4px;right:4px;padding:2px 5px;background:#FFF;background:rgba(255, 255, 255, 0.75);text-align:center;border-bottom:solid 1px #999;}
|
||||
#evidence img{display:block;width:100%;min-width:150px;min-height:150px;margin:0;}
|
||||
#evidence form{margin:0;}
|
||||
#evidence label{position:absolute;bottom:-6px;right:-6px;width:32px;height:32px;background:url('../images/delete.png') 50% 50% no-repeat;text-indent:-999em;margin:0;}
|
||||
.upload-list{list-style:none;margin:20px 0;}.upload-list li{margin:5px 0 0;}
|
||||
.upload-list .details{position:relative;}.upload-list .details .meta{position:relative;z-index:1;padding:3px 10px;}
|
||||
.upload-list .details .filename{font-weight:bold;}
|
||||
.upload-list .details .progress{position:absolute;top:0;left:0;right:0;height:100%;}.upload-list .details .progress .bar{opacity:0.5;}
|
||||
body.home{background-image:url('../img/chalkboard_bg.jpg');}body.home .container{width:960px;}
|
||||
body.home .navbar .navbar-inner{background-image:url('../img/spacedimg.jpg');background-repeat:no-repeat;background-position:top center;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;padding-top:0px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/spacedimg.png', sizingMethod='scale');-ms-filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/spacedimg.png', sizingMethod='scale')";overflow:visible;max-height:515px;}body.home .navbar .navbar-inner>.container{background-image:url('../img/home_drawing.png');background-position:top center;background-repeat:no-repeat;}
|
||||
body.home .navbar .brand{background-image:url('../img/csol_logo_sm.png');position:absolute;left:50%;margin-left:-102px;z-index:2;top:50px;width:189px;height:131px;padding:0 0 0 0;}
|
||||
body.home .navbar .nav-wrap{width:inherit;margin-bottom:0px;height:600px;width:310px;margin:0 auto;background:none;background-image:url('../img/banner300.png');background-position:top center;background-repeat:no-repeat;position:relative;z-index:1;box-shadow:none;}body.home .navbar .nav-wrap ul{padding-top:200px;left:-6px;}body.home .navbar .nav-wrap ul>li{text-align:left;display:block;line-height:9px;}body.home .navbar .nav-wrap ul>li>a{text-transform:inherit;font-size:22px;color:#f4fc00;text-transform:lowercase;}
|
||||
body.home .navbar .nav-wrap ul>li.learn>a:first-letter{text-transform:capitalize;}
|
||||
body.home .navbar .nav-wrap ul>li.log-in>a{font-size:18px;color:#fff;text-transform:lowercase;text-align:center;line-height:24px;}
|
||||
body.home .navbar .nav-wrap ul>li.video{margin-top:35px;}body.home .navbar .nav-wrap ul>li.video a{color:#fff;border-radius:7px;margin:auto;display:block;width:140px;text-align:center;line-height:20px;background:#e82202;background:-moz-linear-gradient(top, #e82202 0%, #e5381d 44%, #e56854 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #e82202), color-stop(44%, #e5381d), color-stop(100%, #e56854));background:-webkit-linear-gradient(top, #e82202 0%, #e5381d 44%, #e56854 100%);background:-o-linear-gradient(top, #e82202 0%, #e5381d 44%, #e56854 100%);background:-ms-linear-gradient(top, #e82202 0%, #e5381d 44%, #e56854 100%);background:linear-gradient(to bottom, #e82202 0%, #e5381d 44%, #e56854 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e82202', endColorstr='#e56854', GradientType=0);}
|
||||
body.home .navbar .nav-wrap ul>li span{color:#fff;}
|
||||
body.home .navbar .nav-wrap ul>li:nth-child(even){border-left:none;border-right:none;}
|
||||
body.home #main{padding:0 0 0 0;display:none;}
|
||||
body.home .navbar-static-top .container{width:inherit;}
|
||||
body.home .secondary .upper{padding-top:15px;position:relative;}body.home .secondary .upper>p.pull-left{display:none;}
|
||||
body.home .secondary .upper>.pull-right{float:left;text-align:center;width:340px;padding-top:55px;}
|
||||
body.home .secondary .lower{border-top:none;}body.home .secondary .lower .pull-right li:first-child{display:none;}
|
||||
body.home .secondary .lower .pull-right li:nth-child(3){border-left:1px solid #fff;border-right:1px solid #fff;}
|
||||
body.home .secondary .lower .pull-left li:first-child{border-right:1px solid #fff;}
|
||||
body.home .footer{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
||||
body.home #rahm{position:relative;width:210px;padding-left:100px;padding-top:15px;background-image:url('../img/rahm.png');background-repeat:no-repeat;background-position:center left;float:left;-webkit-hyphens:none;-moz-hyphens:none;hyphens:none;}
|
||||
body.home #bubbles{float:left;background-image:url('../img/bubbles.png');width:310px;height:140px;background-repeat:no-repeat;background-position:18px 0px;margin-top:15px;}body.home #bubbles span{color:#000;display:block;width:100px;}body.home #bubbles span.lt{float:left;margin-left:34px;margin-top:12px;}body.home #bubbles span.lt a{color:#3B5998;}
|
||||
body.home #bubbles span.rt{margin-top:52px;margin-right:7px;float:right;font-size:24px;line-height:20px;}
|
|
@ -0,0 +1,249 @@
|
|||
/*! fancyBox v2.1.4 fancyapps.com | fancyapps.com/fancybox/#license */
|
||||
.fancybox-wrap,
|
||||
.fancybox-skin,
|
||||
.fancybox-outer,
|
||||
.fancybox-inner,
|
||||
.fancybox-image,
|
||||
.fancybox-wrap iframe,
|
||||
.fancybox-wrap object,
|
||||
.fancybox-nav,
|
||||
.fancybox-nav span,
|
||||
.fancybox-tmp
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
outline: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.fancybox-wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 8020;
|
||||
}
|
||||
|
||||
.fancybox-skin {
|
||||
position: relative;
|
||||
background: #f9f9f9;
|
||||
color: #444;
|
||||
text-shadow: none;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.fancybox-opened {
|
||||
z-index: 8030;
|
||||
}
|
||||
|
||||
.fancybox-opened .fancybox-skin {
|
||||
-webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.fancybox-outer, .fancybox-inner {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fancybox-inner {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fancybox-type-iframe .fancybox-inner {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.fancybox-error {
|
||||
color: #444;
|
||||
font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.fancybox-image, .fancybox-iframe {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.fancybox-image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
#fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
|
||||
background-image: url('../images/fancybox_sprite.png');
|
||||
}
|
||||
|
||||
#fancybox-loading {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -22px;
|
||||
margin-left: -22px;
|
||||
background-position: 0 -108px;
|
||||
opacity: 0.8;
|
||||
cursor: pointer;
|
||||
z-index: 8060;
|
||||
}
|
||||
|
||||
#fancybox-loading div {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: url('../images/fancybox_loading.gif') center center no-repeat;
|
||||
}
|
||||
|
||||
.fancybox-close {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: -18px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
z-index: 8040;
|
||||
}
|
||||
|
||||
.fancybox-nav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 40%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
background: transparent url('../images/blank.gif'); /* helps IE */
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
z-index: 8040;
|
||||
}
|
||||
|
||||
.fancybox-prev {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.fancybox-next {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.fancybox-nav span {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 36px;
|
||||
height: 34px;
|
||||
margin-top: -18px;
|
||||
cursor: pointer;
|
||||
z-index: 8040;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.fancybox-prev span {
|
||||
left: 10px;
|
||||
background-position: 0 -36px;
|
||||
}
|
||||
|
||||
.fancybox-next span {
|
||||
right: 10px;
|
||||
background-position: 0 -72px;
|
||||
}
|
||||
|
||||
.fancybox-nav:hover span {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.fancybox-tmp {
|
||||
position: absolute;
|
||||
top: -99999px;
|
||||
left: -99999px;
|
||||
visibility: hidden;
|
||||
max-width: 99999px;
|
||||
max-height: 99999px;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
/* Overlay helper */
|
||||
|
||||
.fancybox-lock {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fancybox-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
z-index: 8010;
|
||||
background: url('../images/fancybox_overlay.png');
|
||||
}
|
||||
|
||||
.fancybox-overlay-fixed {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.fancybox-lock .fancybox-overlay {
|
||||
overflow: auto;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/* Title helper */
|
||||
|
||||
.fancybox-title {
|
||||
visibility: hidden;
|
||||
font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
position: relative;
|
||||
text-shadow: none;
|
||||
z-index: 8050;
|
||||
}
|
||||
|
||||
.fancybox-opened .fancybox-title {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.fancybox-title-float-wrap {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 50%;
|
||||
margin-bottom: -35px;
|
||||
z-index: 8050;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.fancybox-title-float-wrap .child {
|
||||
display: inline-block;
|
||||
margin-right: -100%;
|
||||
padding: 2px 20px;
|
||||
background: transparent; /* Fallback for web browsers that doesn't support RGBa */
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
-webkit-border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
text-shadow: 0 1px 2px #222;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.fancybox-title-outside-wrap {
|
||||
position: relative;
|
||||
margin-top: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fancybox-title-inside-wrap {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.fancybox-title-over-wrap {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
background: #000;
|
||||
background: rgba(0, 0, 0, .8);
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 43 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.9 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.8 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1003 B |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 1.3 KiB |
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,390 @@
|
|||
(function($, undefined) {
|
||||
if (typeof $ === "undefined" || $ === null)
|
||||
return;
|
||||
|
||||
var oldXHR = $.ajaxSettings.xhr;
|
||||
|
||||
$.ajaxSettings.xhr = function() {
|
||||
var xhr = oldXHR();
|
||||
|
||||
if(xhr instanceof window.XMLHttpRequest) {
|
||||
xhr.addEventListener('progress', this.progress, false);
|
||||
}
|
||||
|
||||
if(xhr.upload) {
|
||||
xhr.upload.addEventListener('progress', this.progress, false);
|
||||
}
|
||||
|
||||
return xhr;
|
||||
};
|
||||
|
||||
function initializeBasic (form, options) {
|
||||
var $form = $(form),
|
||||
$wrapper = $(options.itemWrapper),
|
||||
$template = $(options.template),
|
||||
$buttons = $(options.buttonContainer),
|
||||
$addButton = $(document.createElement('input')),
|
||||
itemSelector = '.' + $template[0].className.replace(/\s+/g, '.');
|
||||
|
||||
$form.addClass('basic');
|
||||
|
||||
$addButton
|
||||
.val('Add')
|
||||
.addClass('btn')
|
||||
.attr('type', 'button')
|
||||
.attr('title', 'Add another file')
|
||||
.click(addRow)
|
||||
.prependTo($buttons);
|
||||
|
||||
function addRow () {
|
||||
$template.clone().appendTo($wrapper);
|
||||
|
||||
var $items = $wrapper.find(itemSelector);
|
||||
|
||||
if ($items.length <= 1)
|
||||
return;
|
||||
|
||||
var $remove = $(document.createElement('button'));
|
||||
|
||||
$remove
|
||||
.addClass('btn remove')
|
||||
.attr('title', 'Remove')
|
||||
.text('✕')
|
||||
.click(function () {
|
||||
removeRow($(this).parent(itemSelector));
|
||||
return false;
|
||||
});
|
||||
|
||||
$items.append($remove);
|
||||
}
|
||||
|
||||
function removeRow (row) {
|
||||
$(row).remove();
|
||||
|
||||
if ($wrapper.find(itemSelector).length <= 1)
|
||||
$wrapper.find('.remove').remove();
|
||||
}
|
||||
}
|
||||
|
||||
function initializeAdvanced (form, options) {
|
||||
var $form = $(form),
|
||||
$wrapper = $(options.itemWrapper),
|
||||
$template = $(options.template),
|
||||
$buttons = $(options.buttonContainer),
|
||||
$description = $(document.createElement('div')),
|
||||
$label = $(document.createElement('label')),
|
||||
itemSelector = '.' + $template[0].className.replace(/\s+/g, '.'),
|
||||
itemCount = 0,
|
||||
xhr = (window.XMLHttpRequest && new XMLHttpRequest()) || {};
|
||||
|
||||
$form.addClass('advanced');
|
||||
|
||||
$template.remove();
|
||||
|
||||
$description
|
||||
.addClass('description')
|
||||
.html('<span><strong>Drop photos and videos here</strong> <em>or</em></span>')
|
||||
.prependTo($template);
|
||||
|
||||
$label
|
||||
.addClass('btn')
|
||||
.text('Choose photos and videos to upload')
|
||||
.appendTo($description);
|
||||
|
||||
if (xhr.upload && window.FormData) {
|
||||
goAsync();
|
||||
} else {
|
||||
goStandard();
|
||||
}
|
||||
|
||||
addRow();
|
||||
|
||||
function blockEvent (e) {
|
||||
e = e || window.event;
|
||||
|
||||
e.stopPropagation();
|
||||
if (e.preventDefault) {
|
||||
return e.preventDefault();
|
||||
} else {
|
||||
return e.returnValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
function addRow (append) {
|
||||
var $item = $template.clone(true),
|
||||
id = 'upload-item-' + (++itemCount);
|
||||
|
||||
$item
|
||||
.find('label')
|
||||
.attr('for', id)
|
||||
.end()
|
||||
.find('input[type="file"]')
|
||||
.attr('id', id)
|
||||
.end();
|
||||
|
||||
if (append) {
|
||||
$item.insertAfter($wrapper.find(itemSelector).first());
|
||||
} else {
|
||||
$wrapper.prepend($item);
|
||||
}
|
||||
|
||||
if ($wrapper.find(itemSelector).length <= 1)
|
||||
return;
|
||||
|
||||
$wrapper.find('.remove').remove();
|
||||
|
||||
var $remove = $(document.createElement('button'));
|
||||
|
||||
$remove
|
||||
.addClass('btn remove')
|
||||
.attr('title', 'Remove')
|
||||
.text('✕')
|
||||
.click(function () {
|
||||
removeRow($(this).parent(itemSelector));
|
||||
return false;
|
||||
});
|
||||
|
||||
var $items = $wrapper.find(itemSelector).append($remove);
|
||||
|
||||
if (append) {
|
||||
$items.first().find('.remove').remove();
|
||||
} else {
|
||||
$item.find('.remove').remove();
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
function removeRow (row) {
|
||||
$(row)
|
||||
.trigger('remove')
|
||||
.remove();
|
||||
|
||||
if ($wrapper.find(itemSelector).length <= 1)
|
||||
$wrapper.find('.remove').remove();
|
||||
}
|
||||
|
||||
function goAsync () {
|
||||
$buttons
|
||||
.find('.btn')
|
||||
.text('Done');
|
||||
|
||||
function upload (e) {
|
||||
blockEvent(e);
|
||||
|
||||
var e = e.originalEvent || e,
|
||||
files = (e.dataTransfer||this).files,
|
||||
$field = $(this),
|
||||
$item = $field.parent(itemSelector);
|
||||
|
||||
if ($field[0] !== $form[0])
|
||||
$field.remove();
|
||||
|
||||
if (!$item.length)
|
||||
$item = addRow(true);
|
||||
|
||||
$.each(files, function (index) {
|
||||
var $description = $item.find('.description'),
|
||||
$filename = $(document.createElement('div')),
|
||||
$icon = $(document.createElement('span')),
|
||||
$progress = $(document.createElement('div')),
|
||||
form = new FormData(),
|
||||
xhr = new XMLHttpRequest(),
|
||||
file = this,
|
||||
key = e.timeStamp + '-' + index,
|
||||
mediaType = file.type.split('/')[0],
|
||||
display = file.name;
|
||||
|
||||
switch (mediaType) {
|
||||
case 'image': $icon.addClass('icon-picture'); break;
|
||||
case 'video': $icon.addClass('icon-facetime-video'); break;
|
||||
default: $icon.addClass('icon-file');
|
||||
}
|
||||
|
||||
$filename
|
||||
.addClass('filename')
|
||||
.insertBefore($description)
|
||||
.text(' ' + display)
|
||||
.prepend($icon);
|
||||
|
||||
$progress
|
||||
.addClass('progress progress-striped active')
|
||||
.html('<span class="bar"></span>')
|
||||
.insertBefore($description);
|
||||
|
||||
$description.remove();
|
||||
|
||||
form.append($field.attr('name') || options.field, file);
|
||||
$.each(options.params || {}, function (key, value) {
|
||||
form.append(key, value);
|
||||
});
|
||||
|
||||
var transfer = $.ajax({
|
||||
url: options.action,
|
||||
type: options.method,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
data: form,
|
||||
progress: function (e) {
|
||||
if (!e.lengthComputable) return;
|
||||
|
||||
var progress = Math.max(0, Math.min(100, 100 * e.loaded / e.total));
|
||||
$progress.find('.bar').css('width', progress + '%');
|
||||
}
|
||||
}).done(function (rsp) {
|
||||
if (rsp.status !== 'ok') {
|
||||
$progress
|
||||
.removeClass('progress-striped active')
|
||||
.addClass('progress-danger');
|
||||
$form.trigger('failed', {
|
||||
status: rsp.status,
|
||||
message: rsp.message,
|
||||
key: key
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
$progress
|
||||
.removeClass('progress-striped active')
|
||||
.addClass('progress-success');
|
||||
|
||||
$form.trigger('uploaded', {
|
||||
file: file,
|
||||
evidence: rsp.evidence[0],
|
||||
key: key
|
||||
});
|
||||
}).fail(function () {
|
||||
$progress
|
||||
.removeClass('progress-striped active')
|
||||
.addClass('progress-danger');
|
||||
|
||||
$form.trigger('failed', {
|
||||
key: key
|
||||
});
|
||||
}).always(function () {
|
||||
$progress.find('.bar').css('width', '100%');
|
||||
});
|
||||
|
||||
$item.on('remove', function () {
|
||||
transfer.abort();
|
||||
$form.trigger('removed', {
|
||||
file: file,
|
||||
key: key
|
||||
});
|
||||
});
|
||||
|
||||
$item = addRow(e.type === "drop");
|
||||
});
|
||||
|
||||
if (e.type === "drop")
|
||||
$item.remove();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$template.find('input[type="file"]').on('change', upload);
|
||||
|
||||
$form
|
||||
.addClass('async')
|
||||
.on('dragenter', blockEvent)
|
||||
.on('dragover', blockEvent)
|
||||
.on('drop', upload);
|
||||
}
|
||||
|
||||
function goStandard () {
|
||||
$template.find('input[type="file"]').on('change', function () {
|
||||
var $item = $(this).parent(itemSelector),
|
||||
$description = $item.find('.description'),
|
||||
$filename = $(document.createElement('div')),
|
||||
$icon = $(document.createElement('span')),
|
||||
mediaType = this.files[0].type.split('/')[0],
|
||||
display = this.files[0].name;
|
||||
|
||||
if (this.files.length > 1) {
|
||||
$icon.addClass('icon-folder-open');
|
||||
if (display.length > 40) {
|
||||
var meta = display.match(/^(.*)(\.[^.]+)$/);
|
||||
display = meta[1].substr(0, 15) + '...' + meta[1].substr(-15) + (meta[2] ? meta[2] : '');
|
||||
}
|
||||
display += ' + ' + (this.files.length - 1) + ' more';
|
||||
} else {
|
||||
switch (mediaType) {
|
||||
case 'image': $icon.addClass('icon-picture'); break;
|
||||
case 'video': $icon.addClass('icon-facetime-video'); break;
|
||||
default: $icon.addClass('icon-file');
|
||||
}
|
||||
}
|
||||
|
||||
$filename
|
||||
.addClass('filename')
|
||||
.insertBefore($description)
|
||||
.text(' ' + display)
|
||||
.prepend($icon);
|
||||
|
||||
$description.remove();
|
||||
|
||||
addRow();
|
||||
});
|
||||
|
||||
$form
|
||||
.addClass('standard')
|
||||
.on('dragover', function (e) {
|
||||
blockEvent(e);
|
||||
|
||||
var x = e.originalEvent.pageX,
|
||||
y = e.originalEvent.pageY,
|
||||
$input = $wrapper.find('input[type="file"]').first(),
|
||||
offset = $input.offsetParent().offset();
|
||||
|
||||
$input.css({
|
||||
left: x - offset.left - 100,
|
||||
top: y - offset.top - 15
|
||||
});
|
||||
})
|
||||
.on('drop', function (e) {
|
||||
var $input = $wrapper.find('input[type="file"]').first();
|
||||
|
||||
$input.css({
|
||||
left: '',
|
||||
top: ''
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setup () {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
if (!input.files)
|
||||
return initializeBasic;
|
||||
|
||||
return initializeAdvanced;
|
||||
}
|
||||
|
||||
var initialize = setup();
|
||||
|
||||
$.fn.uploader = function (options) {
|
||||
this.each(function () {
|
||||
var $form = $(this),
|
||||
$fields = $form.find('input[type="hidden"]'),
|
||||
params = {};
|
||||
|
||||
$fields.each(function() {
|
||||
params[this.name] = this.value;
|
||||
});
|
||||
|
||||
return initialize(this, $.extend(options||{}, {
|
||||
action: $form.attr('action') || document.location.href,
|
||||
method: $form.attr('method'),
|
||||
field: 'media',
|
||||
params: params,
|
||||
itemWrapper: $form.find('.items'),
|
||||
template: $form.find('.item'),
|
||||
buttonContainer: $form.find('.buttons')
|
||||
}));
|
||||
});
|
||||
|
||||
return $(this);
|
||||
}
|
||||
})(jQuery);
|
|
@ -1,4 +1,4 @@
|
|||
// Target:../css/core.css
|
||||
// Target: ../css/core.css
|
||||
|
||||
@import "mixins.less";
|
||||
@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300);
|
||||
|
@ -19,25 +19,39 @@ body {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#main {
|
||||
padding-top:45px;
|
||||
padding-bottom:25px;
|
||||
& > h1:first-child, & > h2:first-child, & > h3:first-child, & > h4:first-child, & > p:first-child {
|
||||
margin-top:0px;
|
||||
padding-top:0px;
|
||||
padding-top: 45px;
|
||||
padding-bottom: 25px;
|
||||
|
||||
& > h1:first-child,
|
||||
& > h2:first-child,
|
||||
& > h3:first-child,
|
||||
& > h4:first-child,
|
||||
& > p:first-child {
|
||||
margin-top: 0px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
& > div > h1:first-child, & > div > h2:first-child, & > div > h3:first-child, & > div > h4:first-child, & > div > p:first-child {
|
||||
margin-top:0px;
|
||||
padding-top:0px;
|
||||
margin-top: 0px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul, ol {
|
||||
padding:0 0 0 0;
|
||||
margin:0 0 0 0;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding: 0 0 0 0;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
|
||||
.row,
|
||||
[class*="span"] {
|
||||
margin-left:0px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
/*navbar*/
|
||||
|
@ -124,7 +138,7 @@ ul, ol {
|
|||
background-repeat:no-repeat;
|
||||
margin:0 auto;
|
||||
float:none;
|
||||
text-indent:-9000px;
|
||||
text-indent:-9000px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,8 +149,9 @@ ul, ol {
|
|||
-moz-box-shadow:inset 0px 10px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
box-shadow:inset 0px 10px 20px 0px rgba(0, 0, 0, 0.25);
|
||||
a {
|
||||
color:#fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a.logo {
|
||||
text-indent:-9000px;
|
||||
width:82px;
|
||||
|
@ -145,18 +160,22 @@ ul, ol {
|
|||
background-position:center center;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
|
||||
a.logo.chi {
|
||||
background-image:url('../img/chi.png');
|
||||
background-image: url('../img/chi.png');
|
||||
}
|
||||
|
||||
a.logo.mac {
|
||||
background-image:url('../img/mac.png');
|
||||
background-image: url('../img/mac.png');
|
||||
}
|
||||
|
||||
a.logo.moz {
|
||||
background-image:url('../img/moz.png');
|
||||
background-image: url('../img/moz.png');
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color:#c0c0c0;
|
||||
text-decoration:none;
|
||||
text-decoration:none;
|
||||
}
|
||||
.upper {
|
||||
padding:50px 0 0 0;
|
||||
|
@ -171,7 +190,7 @@ ul, ol {
|
|||
}
|
||||
li {
|
||||
border-left:none;
|
||||
border-right:none;
|
||||
border-right:none;
|
||||
}
|
||||
}
|
||||
.lower {
|
||||
|
@ -185,27 +204,32 @@ ul, ol {
|
|||
margin:10px;
|
||||
}
|
||||
}
|
||||
|
||||
li:first-child {
|
||||
a {
|
||||
margin-left:0px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
}
|
||||
li.nth-child(even) {
|
||||
border-left:1px solid #fff;
|
||||
border-right:1px solid #fff;
|
||||
}
|
||||
li.last-child {
|
||||
border-right:none;
|
||||
}
|
||||
}
|
||||
|
||||
li:nth-child(even) {
|
||||
border-left: 1px solid #fff;
|
||||
border-right: 1px solid #fff;
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*sticky footer*/
|
||||
.wrapper {
|
||||
width:100%;
|
||||
width: 100%;
|
||||
|
||||
.inner-wrapper {
|
||||
width:100%
|
||||
width:100%
|
||||
}
|
||||
|
||||
&.primary {
|
||||
min-height:100%;
|
||||
height:auto !important;
|
||||
|
@ -215,6 +239,7 @@ ul, ol {
|
|||
padding:0px 0px 250px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
position:relative;
|
||||
color:#fff;
|
||||
|
@ -224,13 +249,214 @@ ul, ol {
|
|||
/*CSOL-site specific*/
|
||||
.poster a,
|
||||
.poster img {
|
||||
display:block;
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
#menu-login-form {
|
||||
padding:10px;
|
||||
text-align:left;
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*Evidence uploading / application*/
|
||||
#application-review {
|
||||
.well {
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
|
||||
.rubric {
|
||||
margin: 0 0 20px;
|
||||
|
||||
li {
|
||||
white-space: pre-line;
|
||||
list-style: none;
|
||||
border-left: solid 5px #DDD;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
&.required {
|
||||
border-color: #BBB;
|
||||
|
||||
.note {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#edit-application {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.items {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
border: solid 1px #CCC;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 9.5px;
|
||||
position: relative;
|
||||
border-top: solid 1px #DDD;
|
||||
margin: 0;
|
||||
background: #F5F5F5;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
background: #F0F0F0;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.description span {
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
|
||||
em {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.filename {
|
||||
padding: 5px 30px 5px 5px;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.remove {
|
||||
position: absolute;
|
||||
top: 9.5px;
|
||||
right: 9.5px;
|
||||
padding: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 0;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
border: solid 1px #DDD;
|
||||
border-top-color: #CCC;
|
||||
padding: 9.5px;
|
||||
margin: 0;
|
||||
border-radius: 0 0 4px 4px;
|
||||
background: rgba(255,255,255,0.25);
|
||||
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.1);
|
||||
|
||||
.btn {
|
||||
margin-left: 9.5px;
|
||||
}
|
||||
}
|
||||
|
||||
&.advanced {
|
||||
.item input {
|
||||
position: absolute;
|
||||
right: 200%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#evidence {
|
||||
.item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
background: #FFF;
|
||||
}
|
||||
|
||||
.processing::after {
|
||||
content: "Processing";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
right: 4px;
|
||||
padding: 2px 5px;
|
||||
background: #FFF;
|
||||
background: rgba(255,255,255,0.75);
|
||||
text-align: center;
|
||||
border-bottom: solid 1px #999;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 150px;
|
||||
min-height: 150px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
position: absolute;
|
||||
bottom: -6px;
|
||||
right: -6px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background: url('../images/delete.png') 50% 50% no-repeat;
|
||||
text-indent: -999em;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-list {
|
||||
list-style: none;
|
||||
margin: 20px 0;
|
||||
|
||||
li {
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
.details {
|
||||
position: relative;
|
||||
|
||||
.meta {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
|
||||
.filename {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.progress {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
|
||||
.bar {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
figure.thumbnail {
|
||||
margin:0 0 0 0;
|
||||
|
@ -290,7 +516,7 @@ body.home {
|
|||
& > .container {
|
||||
background-image:url('../img/home_drawing.png');
|
||||
background-position:top center;
|
||||
background-repeat:no-repeat;
|
||||
background-repeat:no-repeat;
|
||||
}
|
||||
}
|
||||
.brand {
|
||||
|
@ -302,7 +528,7 @@ body.home {
|
|||
top:50px;
|
||||
width:189px;
|
||||
height:131px;
|
||||
padding:0 0 0 0;
|
||||
padding:0 0 0 0;
|
||||
}
|
||||
.nav-wrap {
|
||||
width:inherit;
|
||||
|
@ -316,7 +542,7 @@ body.home {
|
|||
background-repeat:no-repeat;
|
||||
position:relative;
|
||||
z-index:1;
|
||||
box-shadow:none;
|
||||
box-shadow:none;
|
||||
ul {
|
||||
padding-top:200px;
|
||||
left:-6px;
|
||||
|
@ -374,7 +600,7 @@ body.home {
|
|||
#main {
|
||||
padding:0 0 0 0;
|
||||
display:none;
|
||||
|
||||
|
||||
}
|
||||
.navbar-static-top {
|
||||
.container {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{% extends 'applications/submitted.html' %}
|
||||
|
||||
{% block notice %}
|
||||
<div class="alert alert-success">
|
||||
Your application has been approved!
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,2 @@
|
|||
{% extends 'layout.html' %}
|
||||
{% set pageTitle = 'Apply for the ' + badge.name + ' badge' %}
|
|
@ -0,0 +1,132 @@
|
|||
{% extends 'applications/layout.html' %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/media/css/jquery.fancybox.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="span8 offset2">
|
||||
<div id="application-review">
|
||||
{% block intro %}
|
||||
{% endblock %}
|
||||
{% block items %}
|
||||
<ul id="evidence" class="thumbnails"{% if evidence.length == 0 %} style="display: none;"{% endif %}>
|
||||
{% for item in evidence %}
|
||||
<li class="span2 item item-{{ item.mediaType.split('/')[0] }}">
|
||||
{% if item.saved %}
|
||||
<a href="{{ item.getLocationUrl() }}" class="thumbnail" data-fancybox-type="{{ item.mediaType.split('/')[0] }}" data-fancybox-group="gallery" title="{{ item.original }}">
|
||||
<img src="{{ item.getThumbnailUrl() }}" width="150" height="150">
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="thumbnail processing" title="{{ item.original }}">
|
||||
<img src="{{ item.getThumbnailUrl() }}" width="150" height="150">
|
||||
</span>
|
||||
{% endif %}
|
||||
<form method="post" action="{{ item.getLocationUrl() }}">
|
||||
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<label title="Delete"><input type="submit" value="Delete"></label>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block form %}
|
||||
<form id="edit-application" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
||||
{% block descriptionTitle %}<h3>Start by telling us about your work</h3>{% endblock %}
|
||||
<textarea name="description" class="span8" rows="7" id="edit-description">{{ application.description }}</textarea>
|
||||
<p class="text-right"><button type="submit" value="save" class="btn">Update</button></p>
|
||||
{% block evidenceTitle %}<h3>Then upload your pictures and videos</h3>{% endblock %}
|
||||
<ul class="items">
|
||||
<li class="item">
|
||||
<input type="file" name="media" accept="image/*, video/*" multiple="multiple">
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-right buttons"><button type="submit" value="upload" class="btn">Upload</button></p>
|
||||
</form>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block finally %}
|
||||
<script src="/media/js/jquery.uploader.js"></script>
|
||||
<script src="/media/js/jquery.fancybox.js"></script>
|
||||
<script>
|
||||
(function ($) {
|
||||
var deleteTemplate = [
|
||||
'<input type="hidden" name="_csrf" value="{{ csrfToken }}">',
|
||||
'<input type="hidden" name="action" value="delete">',
|
||||
'<label title="Delete"><input type="submit" value="Delete"></label>',
|
||||
].join('\n');
|
||||
|
||||
function addLightbox ($collection) {
|
||||
$collection.fancybox({
|
||||
openEffect : 'none',
|
||||
closeEffect : 'none'
|
||||
});
|
||||
}
|
||||
|
||||
var $evidence = $('#evidence');
|
||||
|
||||
addLightbox($evidence.find('a.thumbnail'));
|
||||
|
||||
$evidence.on('submit', 'form', function () {
|
||||
var $form = $(this),
|
||||
$item = $form.parent('.item');
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action') || document.location.href,
|
||||
type: $form.attr('method'),
|
||||
data: $form.serialize(),
|
||||
complete: function () {
|
||||
$item.fadeOut(500, function() {
|
||||
$item.remove();
|
||||
|
||||
if (!$evidence.find('.item').length && $('#application-review .well').length)
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
var uploader = $('#edit-application').uploader();
|
||||
|
||||
uploader.on('uploaded', function (e, data) {
|
||||
var $list = $('#evidence'),
|
||||
$item = $(document.createElement('li')),
|
||||
$wrapper = $(document.createElement('span')),
|
||||
$form = $(document.createElement('form'));
|
||||
|
||||
$wrapper
|
||||
.html('<img src="' + data.evidence.thumbnail + '" width="150" height="150">')
|
||||
.attr('title', data.evidence.original)
|
||||
.addClass('thumbnail processing');
|
||||
|
||||
$form
|
||||
.attr('method', 'post')
|
||||
.attr('action', data.evidence.location)
|
||||
.html(deleteTemplate);
|
||||
|
||||
$item
|
||||
.attr('id', 'uploaded-item-' + data.key)
|
||||
.addClass('span2 item item-' + data.evidence.type.split('/')[0])
|
||||
.append($wrapper)
|
||||
.append($form)
|
||||
.appendTo($list);
|
||||
|
||||
addLightbox($item.find('.thumbnail'));
|
||||
});
|
||||
|
||||
uploader.on('removed', function (e, data) {
|
||||
var id = 'uploaded-item-' + data.key;
|
||||
|
||||
$('#' + id).find('form').submit();
|
||||
console.log('Removed', this, arguments);
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,61 @@
|
|||
{% extends 'applications/new.html' %}
|
||||
|
||||
{% block intro %}
|
||||
<div class="well">
|
||||
<h3>Review your application</h3>
|
||||
{% if application.description %}
|
||||
<pre>{{ application.description }}</pre>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block items %}
|
||||
{{ super() }}
|
||||
<h3>Confirm the requirements for this badge</h3>
|
||||
{% if badge.rubric %}
|
||||
<ul class="rubric">
|
||||
{% for item in badge.rubric.items %}
|
||||
<li{% if item.required %} class="required"{% endif %}>{{ item.text }}{% if item.required %} <span class="note">(Required)</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<h3>All set?</h3>
|
||||
<form method="post">
|
||||
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
||||
<input type="hidden" name="action" value="apply">
|
||||
<p class="text-center"><button type="submit" class="btn btn-large">Apply for this badge!</button></p>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block descriptionTitle %}<h3>Edit your description</h3>{% endblock %}
|
||||
{% block evidenceTitle %}<h3>Upload more badges and videos</h3>{% endblock %}
|
||||
|
||||
{% block finally %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
(function ($) {
|
||||
var $review = $('#application-review'),
|
||||
$form = $('#edit-application'),
|
||||
$p = $(document.createElement('p')),
|
||||
$button = $(document.createElement('button'));
|
||||
|
||||
$form.hide();
|
||||
|
||||
$button
|
||||
.addClass('btn')
|
||||
.html('<i class="icon-pencil"></i> Edit your application')
|
||||
.appendTo($p)
|
||||
.click(function() {
|
||||
$button.remove();
|
||||
$form.show();
|
||||
$('html, body').animate({
|
||||
scrollTop: $form.offset().top
|
||||
}, 500);
|
||||
});
|
||||
|
||||
$p
|
||||
.addClass('text-right edit-footer')
|
||||
.appendTo($review);
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,7 @@
|
|||
{% extends 'applications/submitted.html' %}
|
||||
|
||||
{% block notice %}
|
||||
<div class="alert alert-warning">
|
||||
Your application has not been successful.
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,48 @@
|
|||
{% extends 'applications/layout.html' %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/media/css/jquery.fancybox.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="span8 offset2">
|
||||
{% block notice %}
|
||||
<div class="alert">
|
||||
Your application is waiting to be reviewed.
|
||||
</div>
|
||||
{% endblock %}
|
||||
<div class="well">
|
||||
<div id="application-review">
|
||||
<h3>Your application</h3>
|
||||
<pre>{{ application.description }}</pre>
|
||||
<ul id="evidence" class="thumbnails"{% if evidence.length == 0 %} style="display: none;"{% endif %}>
|
||||
{% for item in evidence %}
|
||||
<li class="span2 item item-{{ item.mediaType.split('/')[0] }}">
|
||||
{% if item.saved %}
|
||||
<a href="{{ item.getLocationUrl() }}" class="thumbnail" data-fancybox-type="{{ item.mediaType.split('/')[0] }}" data-fancybox-group="gallery" title="{{ item.original }}">
|
||||
<img src="{{ item.getThumbnailUrl() }}" width="150" height="150">
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="thumbnail processing" title="{{ item.original }}">
|
||||
<img src="{{ item.getThumbnailUrl() }}" width="150" height="150">
|
||||
</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block finally %}
|
||||
<script src="/media/js/jquery.fancybox.js"></script>
|
||||
<script>
|
||||
(function ($) {
|
||||
$('#evidence').find('a.thumbnail').fancybox({
|
||||
openEffect : 'none',
|
||||
closeEffect : 'none'
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1 @@
|
|||
{% extends 'applications/submitted.html' %}
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<p class="text-right">
|
||||
<a href="{{ badge.url }}/claim" class="btn">Claim this badge</a>
|
||||
<a href="#applyModal" data-toggle="modal" class="btn">Apply</a>
|
||||
<a href="{{ badge.url }}/apply" class="btn">Apply</a>
|
||||
<a href="{{ badge.url }}/favorite" class="btn show-tooltip" title="Save this badge to your favorites"><i class="icon-heart"></i></a>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -73,106 +73,3 @@
|
|||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal %}
|
||||
<!-- Modal -->
|
||||
<div id="applyModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 id="myModalLabel">Apply for the {{badge.name}} badge</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if badge.prerequisites|length > 0 %}
|
||||
<h4>In order to earn this badge you need to make sure you have met the following requirements:</h4>
|
||||
<ul>
|
||||
{% for req in badge.prerequisites %}
|
||||
<li>{{req}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<h4>Upload photos or videos to show your work</h4>
|
||||
|
||||
<div id="draggable-upload-area">
|
||||
Drag and Drop Photos and Videos here or
|
||||
<a href="#" class="btn btn-primary btn-block">Choose Photos and Videos to Upload</a>
|
||||
</div><!-- .draggable-upload-area -->
|
||||
|
||||
<h4>Tell us more about the work you uploaded</h4>
|
||||
<p>Describe how your work meets the badge requirements and why you think you deserve to earn the badge. If you're especially proud of something you did, here's your chance to let us know.</p>
|
||||
|
||||
<textarea>Some helper text</textarea>
|
||||
|
||||
<a href="#applySuccess" class="btn btn-primary btn-block" data-dismiss="modal" data-toggle="modal">Apply</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div id="applySuccess" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>Badge submission success!</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if user.underage %}
|
||||
<p>You are trying to apply for the {{badge.name}} badge. We just want to make sure your parent or guardian is OK with this. We've sent an email to your parent/guardian and as soon as they give their approval of your badge application, it will be sent to a mentor.</p>
|
||||
<p>The mentor will then review your application and get back to you about your badge.</p>
|
||||
<p>In the mean time, keep on learning, earning and leveling up</p>
|
||||
{% else %}
|
||||
<p>You have applied for the {{badge.name}} badge. Your application will be sent to a mentor who will review it and get back to you about your badge.</p>
|
||||
<p>In the mean time, check out these badges and programs and keep on learning, earning and leveling up!</p>
|
||||
{% endif %}
|
||||
|
||||
<ul class="thumbnails">
|
||||
<li class="span3">
|
||||
<figure class="thumbnail">
|
||||
<a href="/badges/ae784f"><img src="/media/images/badge.png"></a>
|
||||
<figcaption class="caption">
|
||||
<p>Badge blah in voluptate velit...</p>
|
||||
<p class="text-right">
|
||||
<a href="/badges/ae784f" class="btn">Details</a>
|
||||
<a class="btn show-tooltip" title="Save this badge to your favorites" href="/badges/ae784f/favorite"><i class="icon-heart"></i></a>
|
||||
</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
<li class="span3">
|
||||
<figure class="thumbnail">
|
||||
<a href="/badges/ae784f"><img src="/media/images/badge.png"></a>
|
||||
<figcaption class="caption">
|
||||
<p>Badge blah in voluptate velit...</p>
|
||||
<p class="text-right">
|
||||
<a href="/badges/ae784f" class="btn">Details</a>
|
||||
<a class="btn show-tooltip" title="Save this badge to your favorites" href="/badges/ae784f/favorite"><i class="icon-heart"></i></a>
|
||||
</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
<li class="span3">
|
||||
<figure class="thumbnail">
|
||||
<a href="/badges/ae784f"><img src="/media/images/badge.png"></a>
|
||||
<figcaption class="caption">
|
||||
<p>Badge blah in voluptate velit...</p>
|
||||
<p class="text-right">
|
||||
<a href="/badges/ae784f" class="btn">Details</a>
|
||||
<a class="btn show-tooltip" title="Save this badge to your favorites" href="/badges/ae784f/favorite"><i class="icon-heart"></i></a>
|
||||
</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
<li class="span3">
|
||||
<figure class="thumbnail">
|
||||
<a href="/badges/ae784f"><img src="/media/images/badge.png"></a>
|
||||
<figcaption class="caption">
|
||||
<p>Badge blah in voluptate velit...</p>
|
||||
<p class="text-right">
|
||||
<a href="/badges/ae784f" class="btn">Details</a>
|
||||
<a class="btn show-tooltip" title="Save this badge to your favorites" href="/badges/ae784f/favorite"><i class="icon-heart"></i></a>
|
||||
</p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,6 @@
|
|||
{% extends 'errors/layout.html' %}
|
||||
{% set pageTitle = 'Forbidden' %}
|
||||
|
||||
{% block content %}
|
||||
<p>Sorry, but you can't see this page right now.</p>
|
||||
{% endblock %}
|
|
@ -10,6 +10,7 @@
|
|||
<link rel="icon" type="image/png" href="/media/images/favicon.png">
|
||||
<script type="text/javascript" src="//use.typekit.net/nht7hbp.js"></script>
|
||||
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body{% if bodyClass %} class="{{ bodyClass }}"{% endif %}>
|
||||
<div class="wrapper primary">
|
||||
|
|
Загрузка…
Ссылка в новой задаче