Commit d9fa723e by Chris Dodge

Merge branch 'master' of github.com:MITx/mitx into fix/cdodge/export-draft-modules

Conflicts:
	common/lib/xmodule/xmodule/modulestore/xml_importer.py
parents 4cbb9253 276b86a7
...@@ -35,6 +35,7 @@ load-plugins= ...@@ -35,6 +35,7 @@ load-plugins=
# it should appear only once). # it should appear only once).
disable= disable=
# C0301: Line too long # C0301: Line too long
# C0302: Too many lines in module
# W0141: Used builtin function 'map' # W0141: Used builtin function 'map'
# W0142: Used * or ** magic # W0142: Used * or ** magic
# R0201: Method could be a function # R0201: Method could be a function
...@@ -42,8 +43,11 @@ disable= ...@@ -42,8 +43,11 @@ disable=
# R0902: Too many instance attributes # R0902: Too many instance attributes
# R0903: Too few public methods (1/2) # R0903: Too few public methods (1/2)
# R0904: Too many public methods # R0904: Too many public methods
# R0911: Too many return statements
# R0912: Too many branches
# R0913: Too many arguments # R0913: Too many arguments
C0301,W0141,W0142,R0201,R0901,R0902,R0903,R0904,R0913 # R0914: Too many local variables
C0301,C0302,W0141,W0142,R0201,R0901,R0902,R0903,R0904,R0911,R0912,R0913,R0914
[REPORTS] [REPORTS]
...@@ -92,7 +96,7 @@ zope=no ...@@ -92,7 +96,7 @@ zope=no
# List of members which are set dynamically and missed by pylint inference # List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed. Python regular # system, and so shouldn't trigger E0201 when accessed. Python regular
# expressions are accepted. # expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent,objects,DoesNotExist,can_read,can_write,get_url,size generated-members=REQUEST,acl_users,aq_parent,objects,DoesNotExist,can_read,can_write,get_url,size,content
[BASIC] [BASIC]
......
...@@ -120,6 +120,12 @@ def howitworks(request): ...@@ -120,6 +120,12 @@ def howitworks(request):
else: else:
return render_to_response('howitworks.html', {}) return render_to_response('howitworks.html', {})
# static/proof-of-concept views
def ux_alerts(request):
return render_to_response('ux-alerts.html', {})
# ==== Views for any logged-in user ================================== # ==== Views for any logged-in user ==================================
......
if (!window.CmsUtils) window.CmsUtils = {};
var $body; var $body;
var $modal; var $modal;
var $modalCover; var $modalCover;
...@@ -48,6 +50,10 @@ $(document).ready(function () { ...@@ -48,6 +50,10 @@ $(document).ready(function () {
(e).preventDefault(); (e).preventDefault();
}); });
// alerts/notifications - manual close
$('.action-alert-close, .alert.has-actions .nav-actions a').bind('click', hideAlert);
$('.action-notification-close').bind('click', hideNotification);
// nav - dropdown related // nav - dropdown related
$body.click(function (e) { $body.click(function (e) {
$('.nav-dropdown .nav-item .wrapper-nav-sub').removeClass('is-shown'); $('.nav-dropdown .nav-item .wrapper-nav-sub').removeClass('is-shown');
...@@ -87,7 +93,7 @@ $(document).ready(function () { ...@@ -87,7 +93,7 @@ $(document).ready(function () {
$('a[rel*="view"][href^="#"]').bind('click', smoothScrollLink); $('a[rel*="view"][href^="#"]').bind('click', smoothScrollLink);
// tender feedback window scrolling // tender feedback window scrolling
$('a.show-tender').bind('click', smoothScrollTop); $('a.show-tender').bind('click', window.CmsUtils.smoothScrollTop);
// toggling footer additional support // toggling footer additional support
$('.cta-show-sock').bind('click', toggleSock); $('.cta-show-sock').bind('click', toggleSock);
...@@ -159,21 +165,24 @@ $(document).ready(function () { ...@@ -159,21 +165,24 @@ $(document).ready(function () {
function smoothScrollLink(e) { function smoothScrollLink(e) {
(e).preventDefault(); (e).preventDefault();
$.smoothScroll({ $.smoothScroll({
offset: -200, offset: -200,
easing: 'swing', easing: 'swing',
speed: 1000, speed: 1000,
scrollElement: null, scrollElement: null,
scrollTarget: $(this).attr('href') scrollTarget: $(this).attr('href')
}); });
} }
function smoothScrollTop(e) { // On AWS instances, this base.js gets wrapped in a separate scope as part of Django static
// pipelining (note, this doesn't happen on local runtimes). So if we set it on window,
// when we can access it from other scopes (namely Course Advanced Settings).
window.CmsUtils.smoothScrollTop = function (e) {
(e).preventDefault(); (e).preventDefault();
$.smoothScroll({ $.smoothScroll({
offset: -200, offset: -200,
easing: 'swing', easing: 'swing',
speed: 1000, speed: 1000,
scrollElement: null, scrollElement: null,
scrollTarget: $('#view-top') scrollTarget: $('#view-top')
...@@ -483,9 +492,9 @@ function toggleSock(e) { ...@@ -483,9 +492,9 @@ function toggleSock(e) {
$sock.toggleClass('is-shown'); $sock.toggleClass('is-shown');
$sockContent.toggle('fast'); $sockContent.toggle('fast');
$.smoothScroll({ $.smoothScroll({
offset: -200, offset: -200,
easing: 'swing', easing: 'swing',
speed: 1000, speed: 1000,
scrollElement: null, scrollElement: null,
scrollTarget: $sock scrollTarget: $sock
...@@ -538,6 +547,17 @@ function removeDateSetter(e) { ...@@ -538,6 +547,17 @@ function removeDateSetter(e) {
$block.find('.time').val(''); $block.find('.time').val('');
} }
function hideNotification(e) {
(e).preventDefault();
$(this).closest('.wrapper-notification').removeClass('is-shown').addClass('is-hiding').attr('aria-hidden','true');
}
function hideAlert(e) {
(e).preventDefault();
$(this).closest('.wrapper-alert').removeClass('is-shown');
}
function showToastMessage(message, $button, lifespan) { function showToastMessage(message, $button, lifespan) {
var $toast = $('<div class="toast-notification"></div>'); var $toast = $('<div class="toast-notification"></div>');
var $closeBtn = $('<a href="#" class="close-button">×</a>'); var $closeBtn = $('<a href="#" class="close-button">×</a>');
...@@ -839,4 +859,4 @@ function saveSetSectionScheduleDate(e) { ...@@ -839,4 +859,4 @@ function saveSetSectionScheduleDate(e) {
hideModal(); hideModal();
}); });
} }
\ No newline at end of file
...@@ -32,7 +32,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -32,7 +32,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
var listEle$ = this.$el.find('.course-advanced-policy-list'); var listEle$ = this.$el.find('.course-advanced-policy-list');
listEle$.empty(); listEle$.empty();
// b/c we've deleted all old fields, clear the map and repopulate // b/c we've deleted all old fields, clear the map and repopulate
this.fieldToSelectorMap = {}; this.fieldToSelectorMap = {};
this.selectorToField = {}; this.selectorToField = {};
...@@ -101,13 +101,13 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -101,13 +101,13 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
}); });
}, },
showMessage: function (type) { showMessage: function (type) {
this.$el.find(".message-status").removeClass("is-shown"); $(".wrapper-alert").removeClass("is-shown");
if (type) { if (type) {
if (type === this.error_saving) { if (type === this.error_saving) {
this.$el.find(".message-status.error").addClass("is-shown"); $(".wrapper-alert-error").addClass("is-shown").attr('aria-hidden','false');
} }
else if (type === this.successful_changes) { else if (type === this.successful_changes) {
this.$el.find(".message-status.confirm").addClass("is-shown"); $(".wrapper-alert-confirmation").addClass("is-shown").attr('aria-hidden','false');
this.hideSaveCancelButtons(); this.hideSaveCancelButtons();
} }
} }
...@@ -117,17 +117,20 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -117,17 +117,20 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
} }
}, },
showSaveCancelButtons: function(event) { showSaveCancelButtons: function(event) {
if (!this.buttonsVisible) { if (!this.notificationBarShowing) {
this.$el.find(".message-status").removeClass("is-shown"); this.$el.find(".message-status").removeClass("is-shown");
$('.wrapper-notification').addClass('is-shown'); $('.wrapper-notification').removeClass('is-hiding').addClass('is-shown').attr('aria-hidden','false');
this.buttonsVisible = true; this.notificationBarShowing = true;
} }
}, },
hideSaveCancelButtons: function() { hideSaveCancelButtons: function() {
$('.wrapper-notification').removeClass('is-shown'); if (this.notificationBarShowing) {
this.buttonsVisible = false; $('.wrapper-notification').removeClass('is-shown').addClass('is-hiding').attr('aria-hidden','true');
this.notificationBarShowing = false;
}
}, },
saveView : function(event) { saveView : function(event) {
window.CmsUtils.smoothScrollTop(event);
// TODO one last verification scan: // TODO one last verification scan:
// call validateKey on each to ensure proper format // call validateKey on each to ensure proper format
// check for dupes // check for dupes
...@@ -146,6 +149,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -146,6 +149,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
}); });
}, },
revertView : function(event) { revertView : function(event) {
event.preventDefault();
var self = event.data; var self = event.data;
self.model.deleteKeys = []; self.model.deleteKeys = [];
self.model.clear({silent : true}); self.model.clear({silent : true});
...@@ -158,7 +162,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -158,7 +162,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
var newKeyId = _.uniqueId('policy_key_'), var newKeyId = _.uniqueId('policy_key_'),
newEle = this.template({ key : key, value : JSON.stringify(value, null, 4), newEle = this.template({ key : key, value : JSON.stringify(value, null, 4),
keyUniqueId: newKeyId, valueUniqueId: _.uniqueId('policy_value_')}); keyUniqueId: newKeyId, valueUniqueId: _.uniqueId('policy_value_')});
this.fieldToSelectorMap[key] = newKeyId; this.fieldToSelectorMap[key] = newKeyId;
this.selectorToField[newKeyId] = key; this.selectorToField[newKeyId] = key;
return newEle; return newEle;
...@@ -169,4 +173,4 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -169,4 +173,4 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
blurInput : function(event) { blurInput : function(event) {
$(event.target).prev().removeClass("is-focused"); $(event.target).prev().removeClass("is-focused");
} }
}); });
\ No newline at end of file
...@@ -25,7 +25,7 @@ a { ...@@ -25,7 +25,7 @@ a {
@include transition(color 0.25s ease-in-out); @include transition(color 0.25s ease-in-out);
&:hover { &:hover {
color: #cb9c40; color: $orange-d1;
} }
} }
...@@ -50,11 +50,72 @@ h1 { ...@@ -50,11 +50,72 @@ h1 {
// ==================== // ====================
// typography - basic
.title-1, .title-2, .title-3, .title-4, .title-5, .title-6 {
font-weight: 600;
color: $gray-d3;
margin: 0;
padding: 0;
}
.title-1 {
@include font-size(32);
margin-bottom: ($baseline*1.5);
}
.title-2 {
@include font-size(24);
margin-bottom: $baseline;
}
.title-3 {
@include font-size(18);
margin-bottom: ($baseline/2);
}
.title-4 {
@include font-size(14);
margin-bottom: $baseline;
font-weight: 500
}
.title-5 {
@include font-size(14);
color: $gray-l1;
margin-bottom: $baseline;
font-weight: 500
}
.title-6 {
@include font-size(14);
color: $gray-l2;
margin-bottom: $baseline;
font-weight: 500
}
p, ul, ol, dl {
margin-bottom: ($baseline/2);
&:last-child {
margin-bottom: 0;
}
}
// ====================
// layout - basic
.wrapper-view {
}
// ====================
// layout - basic page header // layout - basic page header
.wrapper-mast { .wrapper-mast {
margin: ($baseline*1.5) 0 0 0;
padding: 0 $baseline; padding: 0 $baseline;
position: relative; position: relative;
.mast, .metadata { .mast, .metadata {
@include clearfix(); @include clearfix();
@include font-size(16); @include font-size(16);
...@@ -62,7 +123,7 @@ h1 { ...@@ -62,7 +123,7 @@ h1 {
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
width: flex-grid(12); width: flex-grid(12);
margin: ($baseline*1.5) auto $baseline auto; margin: 0 auto $baseline auto;
color: $gray-d2; color: $gray-d2;
} }
...@@ -284,18 +345,33 @@ h1 { ...@@ -284,18 +345,33 @@ h1 {
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
} }
.title-4 { header {
@include clearfix();
}
.title-5 { .title-2 {
width: flex-grid(5, 12);
margin: 0 flex-gutter() 0 0;
float: left;
}
.tip {
@include font-size(13);
width: flex-grid(7, 12);
float: right;
margin-top: ($baseline/2);
text-align: right;
color: $gray-l2;
}
} }
} }
// layout - supplemental content // layout - supplemental content
.content-supplementary { .content-supplementary {
> section {
margin: 0 0 $baseline 0;
}
.bit { .bit {
@include font-size(13); @include font-size(13);
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
...@@ -761,10 +837,10 @@ body.js { ...@@ -761,10 +837,10 @@ body.js {
// ==================== // ====================
// works in progress // works in progress & testing
body.hide-wip { body.hide-wip {
.wip-box { .wip-box {
display: none; display: none;
} }
} }
\ No newline at end of file
...@@ -15,17 +15,17 @@ ...@@ -15,17 +15,17 @@
// mixins - grandfathered // mixins - grandfathered
@mixin button { @mixin button {
display: inline-block; display: inline-block;
padding: 4px 20px 6px; padding: ($baseline/5) $baseline ($baseline/4);
font-size: 14px; @include font-size(14);
font-weight: 700; font-weight: 700;
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset, 0 0 0 rgba(0, 0, 0, 0)); @include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset, 0 0 0 rgba(0, 0, 0, 0));
@include transition(background-color .15s, box-shadow .15s); @include transition(background-color .15s, box-shadow .15s);
&.disabled { &.disabled {
border: 1px solid $lightGrey !important; border: 1px solid $gray-l1 !important;
border-radius: 3px !important; border-radius: 3px !important;
background: $lightGrey !important; background: $gray-l1 !important;
color: $darkGrey !important; color: $gray-d1 !important;
pointer-events: none; pointer-events: none;
cursor: none; cursor: none;
&:hover { &:hover {
...@@ -38,32 +38,111 @@ ...@@ -38,32 +38,111 @@
} }
} }
@mixin green-button {
@include button;
border: 1px solid $green-d1;
border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: $green;
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset);
color: $white;
&:hover {
background-color: $green-s1;
color: $white;
}
&.disabled {
border: 1px solid $green-l3 !important;
background: $green-l3 !important;
color: $white !important;
@include box-shadow(none);
}
}
@mixin blue-button { @mixin blue-button {
@include button; @include button;
border: 1px solid #437fbf; border: 1px solid $blue-d1;
border-radius: 3px; border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0)); @include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: $blue; background-color: $blue;
color: #fff; color: $white;
&:hover, &.active { &:hover, &.active {
background-color: #62aaf5; background-color: $blue-s2;
color: #fff; color: $white;
}
&.disabled {
border: 1px solid $blue-l3 !important;
background: $blue-l3 !important;
color: $white !important;
@include box-shadow(none);
} }
} }
@mixin green-button { @mixin red-button {
@include button; @include button;
border: 1px solid #0d7011; border: 1px solid $red-d1;
border-radius: 3px; border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0)); @include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: $green; background-color: $red;
color: #fff; color: $white;
&:hover { &:hover, &.active {
background-color: #129416; background-color: $red-s1;
color: #fff; color: $white;
} }
&.disabled {
border: 1px solid $red-l3 !important;
background: $red-l3 !important;
color: $white !important;
@include box-shadow(none);
}
}
@mixin pink-button {
@include button;
border: 1px solid $pink-d1;
border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: $pink;
color: $white;
&:hover, &.active {
background-color: $pink-s1;
color: $white;
}
&.disabled {
border: 1px solid $pink-l3 !important;
background: $pink-l3 !important;
color: $white !important;
@include box-shadow(none);
}
}
@mixin orange-button {
@include button;
border: 1px solid $orange-d1;
border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 60%);
background-color: $orange;
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset);
color: $gray-d2;
&:hover {
background-color: $orange-s2;
color: $gray-d2;
}
&.disabled {
border: 1px solid $orange-l3 !important;
background: $orange-l2 !important;
color: $gray-l1 !important;
@include box-shadow(none);
}
} }
@mixin white-button { @mixin white-button {
...@@ -82,24 +161,9 @@ ...@@ -82,24 +161,9 @@
} }
} }
@mixin orange-button {
@include button;
border: 1px solid #bda046;
border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 60%);
background-color: #edbd3c;
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset);
color: #3c3c3c;
&:hover {
background-color: #ffcd46;
color: #3c3c3c;
}
}
@mixin grey-button { @mixin grey-button {
@include button; @include button;
border: 1px solid $darkGrey; border: 1px solid $gray-d2;
border-radius: 3px; border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0)); @include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: #d1dae3; background-color: #d1dae3;
...@@ -127,39 +191,17 @@ ...@@ -127,39 +191,17 @@
} }
} }
@mixin green-button {
@include button;
border: 1px solid $darkGreen;
border-radius: 3px;
@include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));
background-color: $green;
@include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset);
color: #fff;
&:hover {
background-color: $brightGreen;
color: #fff;
}
&.disabled {
border: 1px solid $disabledGreen !important;
background: $disabledGreen !important;
color: #fff !important;
@include box-shadow(none);
}
}
@mixin dark-grey-button { @mixin dark-grey-button {
@include button; @include button;
border: 1px solid #1c1e20; border: 1px solid $gray-d2;
border-radius: 3px; border-radius: 3px;
background: -webkit-linear-gradient(top, rgba(255, 255, 255, .2), rgba(255, 255, 255, 0)) $extraDarkGrey; background: -webkit-linear-gradient(top, rgba(255, 255, 255, .2), rgba(255, 255, 255, 0)) $gray-d1;
box-shadow: 0 1px 0 rgba(255, 255, 255, .2) inset; box-shadow: 0 1px 0 rgba(255, 255, 255, .2) inset;
color: #fff; color: $white;
&:hover { &:hover {
background-color: #595f64; background-color: $gray-d4;
color: #fff; color: $white;
} }
} }
...@@ -180,7 +222,7 @@ ...@@ -180,7 +222,7 @@
} }
textarea { textarea {
min-height: 80px; min-height: 80px;
} }
h5 { h5 {
...@@ -225,7 +267,7 @@ ...@@ -225,7 +267,7 @@
.section-item { .section-item {
position: relative; position: relative;
display: block; display: block;
padding: 6px 8px 8px 16px; padding: 6px 8px 8px 16px;
background: #edf1f5; background: #edf1f5;
font-size: 13px; font-size: 13px;
...@@ -296,6 +338,9 @@ ...@@ -296,6 +338,9 @@
} }
} }
// ====================
// sunsetted mixins
@mixin active { @mixin active {
@include linear-gradient(top, rgba(255, 255, 255, .4), rgba(255, 255, 255, 0)); @include linear-gradient(top, rgba(255, 255, 255, .4), rgba(255, 255, 255, 0));
background-color: rgba(255, 255, 255, .3); background-color: rgba(255, 255, 255, .3);
...@@ -389,4 +434,4 @@ ...@@ -389,4 +434,4 @@
.depth2 { z-index: 100; } .depth2 { z-index: 100; }
.depth3 { z-index: 1000; } .depth3 { z-index: 1000; }
.depth4 { z-index: 10000; } .depth4 { z-index: 10000; }
.depth5 { z-index: 100000; } .depth5 { z-index: 100000; }
\ No newline at end of file
...@@ -113,7 +113,7 @@ $green-u1: desaturate($green,15%); ...@@ -113,7 +113,7 @@ $green-u1: desaturate($green,15%);
$green-u2: desaturate($green,30%); $green-u2: desaturate($green,30%);
$green-u3: desaturate($green,45%); $green-u3: desaturate($green,45%);
$yellow: rgb(231, 214, 143); $yellow: rgb(237, 189, 60);
$yellow-l1: tint($yellow,20%); $yellow-l1: tint($yellow,20%);
$yellow-l2: tint($yellow,40%); $yellow-l2: tint($yellow,40%);
$yellow-l3: tint($yellow,60%); $yellow-l3: tint($yellow,60%);
...@@ -149,8 +149,13 @@ $orange-u3: desaturate($orange,45%); ...@@ -149,8 +149,13 @@ $orange-u3: desaturate($orange,45%);
$shadow: rgba(0,0,0,0.2); $shadow: rgba(0,0,0,0.2);
$shadow-l1: rgba(0,0,0,0.1); $shadow-l1: rgba(0,0,0,0.1);
$shadow-l2: rgba(0,0,0,0.05);
$shadow-d1: rgba(0,0,0,0.4); $shadow-d1: rgba(0,0,0,0.4);
// specific UI
$notification-height: ($baseline*10);
// colors - inherited // colors - inherited
$baseFontColor: $gray-d2; $baseFontColor: $gray-d2;
$offBlack: #3c3c3c; $offBlack: #3c3c3c;
...@@ -167,4 +172,4 @@ $disabledGreen: rgb(124, 206, 153); ...@@ -167,4 +172,4 @@ $disabledGreen: rgb(124, 206, 153);
$darkGreen: rgb(52, 133, 76); $darkGreen: rgb(52, 133, 76);
$lightBluishGrey: rgb(197, 207, 223); $lightBluishGrey: rgb(197, 207, 223);
$lightBluishGrey2: rgb(213, 220, 228); $lightBluishGrey2: rgb(213, 220, 228);
$error-red: rgb(253, 87, 87); $error-red: rgb(253, 87, 87);
\ No newline at end of file
@mixin bounce-in { // studio animations & keyframes
// ====================
// rotate clockwise
@mixin rotateClockwise {
0% {
@include transform(rotate(0deg));
}
100% {
@include transform(rotate(360deg));
}
}
@-moz-keyframes rotateClockwise { @include rotateClockwise(); }
@-webkit-keyframes rotateClockwise { @include rotateClockwise(); }
@-o-keyframes rotateClockwise { @include rotateClockwise(); }
@keyframes rotateClockwise { @include rotateClockwise();}
@mixin anim-rotateClockwise($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(rotateClockwise);
@include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both);
}
// ====================
// notifications slide up
@mixin notificationsSlideUp {
0% {
@include transform(translateY(0));
}
90% {
@include transform(translateY(-($notification-height)));
}
100% {
@include transform(translateY(-($notification-height*0.99)));
}
}
@-moz-keyframes notificationsSlideUp { @include notificationsSlideUp(); }
@-webkit-keyframes notificationsSlideUp { @include notificationsSlideUp(); }
@-o-keyframes notificationsSlideUp { @include notificationsSlideUp(); }
@keyframes notificationsSlideUp { @include notificationsSlideUp();}
@mixin anim-notificationsSlideUp($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(notificationsSlideUp);
@include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both);
}
// ====================
// notifications slide down
@mixin notificationsSlideDown {
0% {
@include transform(translateY(-($notification-height*0.99)));
}
10% {
@include transform(translateY(-($notification-height)));
}
100% {
@include transform(translateY(0));
}
}
@-moz-keyframes notificationsSlideDown { @include notificationsSlideDown(); }
@-webkit-keyframes notificationsSlideDown { @include notificationsSlideDown(); }
@-o-keyframes notificationsSlideDown { @include notificationsSlideDown(); }
@keyframes notificationsSlideDown { @include notificationsSlideDown();}
@mixin anim-notificationsSlideDown($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(notificationsSlideDown);
@include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both);
}
// ====================
// notifications slide up then down
@mixin notificationsSlideUpDown {
0%, 100% {
@include transform(translateY(0));
}
15%, 85% {
@include transform(translateY(-($notification-height)));
}
20%, 80% {
@include transform(translateY(-($notification-height*0.99)));
}
}
@-moz-keyframes notificationsSlideUpDown { @include notificationsSlideUpDown(); }
@-webkit-keyframes notificationsSlideUpDown { @include notificationsSlideUpDown(); }
@-o-keyframes notificationsSlideUpDown { @include notificationsSlideUpDown(); }
@keyframes notificationsSlideUpDown { @include notificationsSlideUpDown();}
@mixin anim-notificationsSlideUpDown($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(notificationsSlideUpDown);
@include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both);
}
// ====================
// bounce in
@mixin bounceIn {
0% { 0% {
opacity: 0; opacity: 0;
@include transform(scale(.3)); @include transform(scale(0.3));
} }
50% { 50% {
...@@ -14,14 +140,63 @@ ...@@ -14,14 +140,63 @@
} }
} }
@-moz-keyframes bounce-in { @include bounce-in(); } @-moz-keyframes bounceIn { @include bounceIn(); }
@-webkit-keyframes bounce-in { @include bounce-in(); } @-webkit-keyframes bounceIn { @include bounceIn(); }
@-o-keyframes bounce-in { @include bounce-in(); } @-o-keyframes bounceIn { @include bounceIn(); }
@keyframes bounce-in { @include bounce-in();} @keyframes bounceIn { @include bounceIn();}
@mixin bounce-in-animation($duration, $timing: ease-in-out) { @mixin anim-bounceIn($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(bounce-in); @include animation-name(bounceIn);
@include animation-duration($duration); @include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing); @include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both); @include animation-fill-mode(both);
} }
// ====================
// bounce in
@mixin bounceOut {
0% {
opacity: 0;
@include transform(scale(0.3));
}
50% {
opacity: 1;
@include transform(scale(1.05));
}
100% {
@include transform(scale(1));
}
0% {
@include transform(scale(1));
}
50% {
opacity: 1;
@include transform(scale(1.05));
}
100% {
opacity: 0;
@include transform(scale(0.3));
}
}
@-moz-keyframes bounceOut { @include bounceOut(); }
@-webkit-keyframes bounceOut { @include bounceOut(); }
@-o-keyframes bounceOut { @include bounceOut(); }
@keyframes bounceOut { @include bounceOut();}
@mixin anim-bounceOut($duration, $timing: ease-in-out, $count: 1, $delay: 0) {
@include animation-name(bounceOut);
@include animation-duration($duration);
@include animation-delay($delay);
@include animation-timing-function($timing);
@include animation-iteration-count($count);
@include animation-fill-mode(both);
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
// bourbon libs and resets // bourbon libs and resets
@import 'bourbon/bourbon'; @import 'bourbon/bourbon';
@import 'bourbon/addons/button'; @import 'bourbon/addons/button';
@import "variables";
@import 'vendor/normalize'; @import 'vendor/normalize';
@import 'reset'; @import 'reset';
......
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
color: $blue; color: $blue;
&:hover, &:active { &:hover, &:active {
background: $blue-l3; background: $blue-l4;
color: $blue-s2; color: $blue-s2;
} }
......
...@@ -8,11 +8,11 @@ input[type="password"], ...@@ -8,11 +8,11 @@ input[type="password"],
textarea.text { textarea.text {
padding: 6px 8px 8px; padding: 6px 8px 8px;
@include box-sizing(border-box); @include box-sizing(border-box);
border: 1px solid $mediumGrey; border: 1px solid $gray-l2;
border-radius: 2px; border-radius: 2px;
@include linear-gradient($lightGrey, tint($lightGrey, 90%)); @include linear-gradient($gray-l5, $white);
background-color: $lightGrey; background-color: $gray-l5;
@include box-shadow(0 1px 2px rgba(0, 0, 0, .1) inset); @include box-shadow(inset 0 1px 2px $shadow-l1);
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
font-size: 11px; font-size: 11px;
color: $baseFontColor; color: $baseFontColor;
...@@ -21,7 +21,7 @@ textarea.text { ...@@ -21,7 +21,7 @@ textarea.text {
&::-webkit-input-placeholder, &::-webkit-input-placeholder,
&:-moz-placeholder, &:-moz-placeholder,
&:-ms-input-placeholder { &:-ms-input-placeholder {
color: #979faf; color: $gray-l2;
} }
&:focus { &:focus {
...@@ -30,7 +30,72 @@ textarea.text { ...@@ -30,7 +30,72 @@ textarea.text {
} }
} }
// forms - specific // ====================
// forms - fields - not editable
.field.is-not-editable {
& label.is-focused {
color: $gray-d2;
}
label, input, textarea {
pointer-events: none;
}
}
// ====================
// field with error
.field.error {
input, textarea {
border-color: $red;
}
}
// ====================
// forms - additional UI
form {
.note {
@include box-sizing(border-box);
.title {
}
.copy {
}
// note with actions
&.has-actions {
@include clearfix();
.title {
}
.copy {
}
.list-actions {
}
}
}
.note-promotion {
}
}
// ====================
// forms - grandfathered
input.search { input.search {
padding: 6px 15px 8px 30px; padding: 6px 15px 8px 30px;
@include box-sizing(border-box); @include box-sizing(border-box);
...@@ -73,4 +138,4 @@ code { ...@@ -73,4 +138,4 @@ code {
background-color: #edf1f5; background-color: #edf1f5;
@include box-shadow(0 1px 2px rgba(0, 0, 0, 0.1) inset); @include box-shadow(0 1px 2px rgba(0, 0, 0, 0.1) inset);
font-family: Monaco, monospace; font-family: Monaco, monospace;
} }
\ No newline at end of file
...@@ -5,12 +5,12 @@ ...@@ -5,12 +5,12 @@
margin: 0; margin: 0;
padding: $baseline; padding: $baseline;
border-bottom: 1px solid $gray; border-bottom: 1px solid $gray;
@include box-shadow(0 1px 5px 0 rgba(0,0,0, 0.1)); @include box-shadow(0 1px 5px 0 rgba(0,0,0, 0.2));
background: $white; background: $white;
height: 76px; height: 76px;
position: relative; position: relative;
width: 100%; width: 100%;
z-index: 10; z-index: 1000;
a { a {
color: $baseFontColor; color: $baseFontColor;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
body.signup, body.signin { body.signup, body.signin {
.wrapper-content { .wrapper-content {
margin: 0; margin: ($baseline*1.5) 0 0 0;
padding: 0 $baseline; padding: 0 $baseline;
position: relative; position: relative;
width: 100%; width: 100%;
...@@ -18,7 +18,7 @@ body.signup, body.signin { ...@@ -18,7 +18,7 @@ body.signup, body.signin {
width: flex-grid(12); width: flex-grid(12);
margin: 0 auto; margin: 0 auto;
color: $gray-d2; color: $gray-d2;
header { header {
position: relative; position: relative;
margin-bottom: $baseline; margin-bottom: $baseline;
...@@ -121,7 +121,7 @@ body.signup, body.signin { ...@@ -121,7 +121,7 @@ body.signup, body.signin {
@include font-size(16); @include font-size(16);
height: 100%; height: 100%;
width: 100%; width: 100%;
padding: ($baseline/2); padding: ($baseline/2);
&.long { &.long {
width: 100%; width: 100%;
...@@ -136,15 +136,15 @@ body.signup, body.signin { ...@@ -136,15 +136,15 @@ body.signup, body.signin {
} }
:-moz-placeholder { :-moz-placeholder {
color: $gray-l3; color: $gray-l3;
} }
::-moz-placeholder { ::-moz-placeholder {
color: $gray-l3; color: $gray-l3;
} }
:-ms-input-placeholder { :-ms-input-placeholder {
color: $gray-l3; color: $gray-l3;
} }
&:focus { &:focus {
......
...@@ -147,7 +147,7 @@ body.course.settings { ...@@ -147,7 +147,7 @@ body.course.settings {
} }
label { label {
@include font-size(14); @extend .t-copy-sub1;
@include transition(color, 0.15s, ease-in-out); @include transition(color, 0.15s, ease-in-out);
margin: 0 0 ($baseline/4) 0; margin: 0 0 ($baseline/4) 0;
font-weight: 400; font-weight: 400;
...@@ -161,7 +161,7 @@ body.course.settings { ...@@ -161,7 +161,7 @@ body.course.settings {
@include placeholder($gray-l4); @include placeholder($gray-l4);
@include font-size(16); @include font-size(16);
@include size(100%,100%); @include size(100%,100%);
padding: ($baseline/2); padding: ($baseline/2);
&.long { &.long {
} }
...@@ -212,7 +212,7 @@ body.course.settings { ...@@ -212,7 +212,7 @@ body.course.settings {
padding: $baseline; padding: $baseline;
&:last-child { &:last-child {
padding-bottom: $baseline; padding-bottom: $baseline;
} }
.actions { .actions {
...@@ -238,33 +238,36 @@ body.course.settings { ...@@ -238,33 +238,36 @@ body.course.settings {
} }
} }
// not editable fields
.field.is-not-editable {
& label.is-focused {
color: $gray-d2;
}
}
// field with error
.field.error {
input, textarea {
border-color: $red;
}
}
// specific fields - basic // specific fields - basic
&.basic { &.basic {
.list-input { .list-input {
@include clearfix(); @include clearfix();
padding: 0 ($baseline/2);
.field { .field {
margin-bottom: 0; margin-bottom: 0;
} }
} }
// course details that should appear more like content than elements to change
.field.is-not-editable {
label {
}
input, textarea {
@extend .t-copy-lead1;
@include box-shadow(none);
border: none;
background: none;
padding: 0;
margin: 0;
font-weight: 600;
}
}
#field-course-organization { #field-course-organization {
float: left; float: left;
width: flex-grid(2, 9); width: flex-grid(2, 9);
...@@ -281,6 +284,58 @@ body.course.settings { ...@@ -281,6 +284,58 @@ body.course.settings {
float: left; float: left;
width: flex-grid(5, 9); width: flex-grid(5, 9);
} }
// course link note
.note-promotion-courseURL {
@include box-shadow(0 2px 1px $shadow-l1);
@include border-radius(($baseline/5));
margin-top: ($baseline*1.5);
border: 1px solid $gray-l2;
padding: ($baseline/2) 0 0 0;
.title {
@extend .t-copy-sub1;
margin: 0 0 ($baseline/10) 0;
padding: 0 ($baseline/2);
.tip {
display: inline;
margin-left: ($baseline/4);
}
}
.copy {
padding: 0 ($baseline/2) ($baseline/2) ($baseline/2);
.link-courseURL {
@extend .t-copy-lead1;
&:hover {
}
}
}
.list-actions {
@include box-shadow(inset 0 1px 1px $shadow-l1);
border-top: 1px solid $gray-l2;
padding: ($baseline/2);
background: $gray-l5;
.action-primary {
@include blue-button();
@include font-size(13);
font-weight: 600;
.icon {
@extend .t-icon;
@include font-size(16);
display: inline-block;
vertical-align: middle;
}
}
}
}
} }
// specific fields - schedule // specific fields - schedule
...@@ -322,7 +377,7 @@ body.course.settings { ...@@ -322,7 +377,7 @@ body.course.settings {
} }
} }
} }
// specific fields - overview // specific fields - overview
#field-course-overview { #field-course-overview {
...@@ -468,7 +523,7 @@ body.course.settings { ...@@ -468,7 +523,7 @@ body.course.settings {
} }
} }
} }
.grade-specific-bar { .grade-specific-bar {
height: 50px !important; height: 50px !important;
} }
...@@ -479,7 +534,7 @@ body.course.settings { ...@@ -479,7 +534,7 @@ body.course.settings {
li { li {
position: absolute; position: absolute;
top: 0; top: 0;
height: 50px; height: 50px;
text-align: right; text-align: right;
@include border-radius(2px); @include border-radius(2px);
...@@ -600,8 +655,8 @@ body.course.settings { ...@@ -600,8 +655,8 @@ body.course.settings {
} }
#field-course-grading-assignment-shortname, #field-course-grading-assignment-shortname,
#field-course-grading-assignment-totalassignments, #field-course-grading-assignment-totalassignments,
#field-course-grading-assignment-gradeweight, #field-course-grading-assignment-gradeweight,
#field-course-grading-assignment-droppable { #field-course-grading-assignment-droppable {
width: flex-grid(2, 6); width: flex-grid(2, 6);
} }
...@@ -734,4 +789,4 @@ body.course.settings { ...@@ -734,4 +789,4 @@ body.course.settings {
.content-supplementary { .content-supplementary {
width: flex-grid(3, 12); width: flex-grid(3, 12);
} }
} }
\ No newline at end of file
...@@ -49,20 +49,30 @@ ...@@ -49,20 +49,30 @@
<script type="text/javascript" src="${static.url('js/vendor/CodeMirror/htmlmixed.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/CodeMirror/htmlmixed.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/CodeMirror/css.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/CodeMirror/css.js')}"></script>
<script type="text/javascript"> <script type="text/javascript">
document.write('\x3Cscript type="text/javascript" src="' + document.write('\x3Cscript type="text/javascript" src="' +
document.location.protocol + '//www.youtube.com/player_api">\x3C/script>'); document.location.protocol + '//www.youtube.com/player_api">\x3C/script>');
</script> </script>
<%include file="widgets/header.html" /> <!-- view -->
<div class="wrapper wrapper-view">
<%block name="content"></%block> <%include file="widgets/header.html" />
% if user.is_authenticated(): <%block name="view_alerts"></%block>
<%include file="widgets/sock.html" /> <%block name="view_banners"></%block>
% endif
<%block name="content"></%block>
<%include file="widgets/footer.html" />
<%include file="widgets/tender.html" /> % if user.is_authenticated():
<%include file="widgets/sock.html" />
% endif
<%include file="widgets/footer.html" />
<%include file="widgets/tender.html" />
<%block name="view_notifications"></%block>
</div>
<%block name="view_prompts"></%block>
<%block name="jsextra"></%block> <%block name="jsextra"></%block>
</body> </body>
......
...@@ -26,9 +26,9 @@ ...@@ -26,9 +26,9 @@
// I believe that current (New Section/New Subsection) cause full page reloads which means these aren't needed globally // I believe that current (New Section/New Subsection) cause full page reloads which means these aren't needed globally
// but we really should change that behavior. // but we really should change that behavior.
if (!window.graderTypes) { if (!window.graderTypes) {
window.graderTypes = new CMS.Models.Settings.CourseGraderCollection(); window.graderTypes = new CMS.Models.Settings.CourseGraderCollection();
window.graderTypes.course_location = new CMS.Models.Location('${parent_location}'); window.graderTypes.course_location = new CMS.Models.Location('${parent_location}');
window.graderTypes.reset(${course_graders|n}); window.graderTypes.reset(${course_graders|n});
} }
$(".gradable-status").each(function(index, ele) { $(".gradable-status").each(function(index, ele) {
......
...@@ -42,13 +42,17 @@ editor.render(); ...@@ -42,13 +42,17 @@ editor.render();
</%block> </%block>
<%block name="content"> <%block name="content">
<div class="wrapper-content wrapper"> <div class="wrapper-mast wrapper">
<section class="content"> <header class="mast has-subtitle">
<header class="page"> <div class="title">
<span class="title-sub">Settings</span> <span class="title-sub">Settings</span>
<h1 class="title-1">Advanced Settings</h1> <h1 class="title-1">Advanced Settings</h1>
</header> </div>
</header>
</div>
<div class="wrapper-content wrapper">
<section class="content">
<article class="content-primary" role="main"> <article class="content-primary" role="main">
<form id="settings_advanced" class="settings-advanced" method="post" action=""> <form id="settings_advanced" class="settings-advanced" method="post" action="">
...@@ -69,7 +73,7 @@ editor.render(); ...@@ -69,7 +73,7 @@ editor.render();
<p class="instructions"><strong>Warning</strong>: Do not modify these policies unless you are familiar with their purpose.</p> <p class="instructions"><strong>Warning</strong>: Do not modify these policies unless you are familiar with their purpose.</p>
<ul class="list-input course-advanced-policy-list enum"> <ul class="list-input course-advanced-policy-list enum">
</ul> </ul>
</section> </section>
</form> </form>
...@@ -100,23 +104,61 @@ editor.render(); ...@@ -100,23 +104,61 @@ editor.render();
</aside> </aside>
</section> </section>
</div> </div>
</%block>
<%block name="view_notifications">
<!-- notification: change has been made and a save is needed --> <!-- notification: change has been made and a save is needed -->
<div class="wrapper wrapper-notification wrapper-notification-warning"> <div class="wrapper wrapper-notification wrapper-notification-warning" aria-hidden="true" role="dialog" aria-labelledby="notification-changesMade-title" aria-describedby="notification-changesMade-description">
<div class="notification warning"> <div class="notification warning has-actions">
<div class="copy"> <i class="ss-icon ss-symbolicons-block icon icon-warning">&#x26A0;</i>
<i class="ss-icon ss-symbolicons-block icon icon-warning">&#x26A0;</i>
<p><strong>Note: </strong>Your changes will not take effect until you <strong>save your <div class="copy">
progress</strong>. Take care with policy value formatting, as validation is <strong>not implemented</strong>.</p> <h2 class="title title-3" id="notification-changesMade-title">You've Made Some Changes</h2>
<p id="notification-changesMade-description">Your changes will not take effect until you <strong>save your progress</strong>. Take care with key and value formatting, as validation is <strong>not implemented</strong>.</p>
</div> </div>
<div class="actions"> <nav class="nav-actions">
<h3 class="sr">Notification Actions</h3>
<ul> <ul>
<li><a href="#" class="save-button">Save</a></li> <li class="nav-item">
<li><a href="#" class="cancel-button">Cancel</a></li> <a href="" class="action-primary save-button">Save Changes</a>
</li>
<li class="nav-item">
<a href="" class="action-secondary cancel-button">Cancel</a>
</li>
</ul> </ul>
</nav>
</div>
</div>
</%block>
<%block name="view_alerts">
<!-- alert: save confirmed with close -->
<div class="wrapper wrapper-alert wrapper-alert-confirmation" role="status">
<div class="alert confirmation">
<i class="ss-icon ss-symbolicons-standard icon icon-confirmation">&#x2713;</i>
<div class="copy">
<h2 class="title title-3">Your policy changes have been saved.</h2>
<p>Please note that validation of your policy key and value pairs is not currently in place yet. If you are having difficulties, please review your policy pairs.</p>
</div>
<a href="" rel="view" class="action action-alert-close">
<i class="ss-icon ss-symbolicons-block icon icon-close">&#x2421;</i>
<span class="label">close alert</span>
</a>
</div>
</div>
<!-- alert: error -->
<div class="wrapper wrapper-alert wrapper-alert-error" role="status">
<div class="alert error">
<i class="ss-icon ss-symbolicons-block icon icon-error">&#x26A0;</i>
<div class="copy">
<h2 class="title title-3">There was an error saving your information</h2>
<p>Please see the error below and correct it to ensure there are no problems in rendering your course.</p>
</div> </div>
</div> </div>
</div> </div>
</%block> </%block>
\ No newline at end of file
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
}); });
$(document).ready(function() { $(document).ready(function() {
$('body').addClass('js');
// tabs // tabs
$('.tab-group').tabs(); $('.tab-group').tabs();
......
...@@ -116,6 +116,8 @@ urlpatterns += ( ...@@ -116,6 +116,8 @@ urlpatterns += (
url(r'^logout$', 'student.views.logout_user', name='logout'), url(r'^logout$', 'student.views.logout_user', name='logout'),
# static/proof-of-concept views
url(r'^ux-alerts$', 'contentstore.views.ux_alerts', name='ux-alerts')
) )
if settings.ENABLE_JASMINE: if settings.ENABLE_JASMINE:
......
...@@ -199,8 +199,8 @@ class PeerGradingModule(PeerGradingFields, XModule): ...@@ -199,8 +199,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
self.student_data_for_location = response self.student_data_for_location = response
score_dict = { score_dict = {
'score': int(count_graded >= count_required), 'score': int(count_graded >= count_required and count_graded>0) * int(self.weight),
'total': self.max_grade, 'total': self.max_grade * int(self.weight),
} }
return score_dict return score_dict
......
...@@ -24,6 +24,11 @@ def strip_filenames(descriptor): ...@@ -24,6 +24,11 @@ def strip_filenames(descriptor):
""" """
print "strip filename from {desc}".format(desc=descriptor.location.url()) print "strip filename from {desc}".format(desc=descriptor.location.url())
descriptor._model_data.pop('filename', None) descriptor._model_data.pop('filename', None)
if hasattr(descriptor, 'xml_attributes'):
if 'filename' in descriptor.xml_attributes:
del descriptor.xml_attributes['filename']
for d in descriptor.get_children(): for d in descriptor.get_children():
strip_filenames(d) strip_filenames(d)
......
...@@ -11,11 +11,15 @@ ...@@ -11,11 +11,15 @@
font-size: ($sizeValue/10) + rem; font-size: ($sizeValue/10) + rem;
} }
// ====================
// line-height // line-height
@function lh($amount: 1) { @function lh($amount: 1) {
@return $body-line-height * $amount; @return $body-line-height * $amount;
} }
// ====================
// image-replacement hidden text // image-replacement hidden text
@mixin text-hide() { @mixin text-hide() {
text-indent: 100%; text-indent: 100%;
...@@ -35,6 +39,8 @@ ...@@ -35,6 +39,8 @@
width: 1px; width: 1px;
} }
// ====================
// vertical and horizontal centering // vertical and horizontal centering
@mixin vertically-and-horizontally-centered ($height, $width) { @mixin vertically-and-horizontally-centered ($height, $width) {
left: 50%; left: 50%;
...@@ -46,6 +52,8 @@ ...@@ -46,6 +52,8 @@
top: 150px; top: 150px;
} }
// ====================
// sizing // sizing
@mixin size($width: $baseline, $height: $baseline) { @mixin size($width: $baseline, $height: $baseline) {
height: $height; height: $height;
...@@ -56,6 +64,8 @@ ...@@ -56,6 +64,8 @@
@include size($size); @include size($size);
} }
// ====================
// placeholder styling // placeholder styling
@mixin placeholder($color) { @mixin placeholder($color) {
:-moz-placeholder { :-moz-placeholder {
......
...@@ -3,17 +3,12 @@ ...@@ -3,17 +3,12 @@
# django management command: dump grades to csv files # django management command: dump grades to csv files
# for use by batch processes # for use by batch processes
import os import csv
import sys
import string
import datetime
import json
from instructor.views import * from instructor.views import get_student_grade_summary_data
from courseware.courses import get_course_by_id from courseware.courses import get_course_by_id
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from django.conf import settings
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
...@@ -45,7 +40,7 @@ class Command(BaseCommand): ...@@ -45,7 +40,7 @@ class Command(BaseCommand):
request = self.DummyRequest() request = self.DummyRequest()
try: try:
course = get_course_by_id(course_id) course = get_course_by_id(course_id)
except Exception as err: except Exception:
if course_id in modulestore().courses: if course_id in modulestore().courses:
course = modulestore().courses[course_id] course = modulestore().courses[course_id]
else: else:
......
...@@ -11,7 +11,6 @@ import requests ...@@ -11,7 +11,6 @@ import requests
from requests.status_codes import codes from requests.status_codes import codes
import urllib import urllib
from collections import OrderedDict from collections import OrderedDict
import json
from StringIO import StringIO from StringIO import StringIO
...@@ -21,7 +20,6 @@ from django.http import HttpResponse ...@@ -21,7 +20,6 @@ from django.http import HttpResponse
from django_future.csrf import ensure_csrf_cookie from django_future.csrf import ensure_csrf_cookie
from django.views.decorators.cache import cache_control from django.views.decorators.cache import cache_control
from mitxmako.shortcuts import render_to_response from mitxmako.shortcuts import render_to_response
import requests
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from courseware import grades from courseware import grades
...@@ -36,11 +34,7 @@ from django_comment_client.models import (Role, ...@@ -36,11 +34,7 @@ from django_comment_client.models import (Role,
from django_comment_client.utils import has_forum_access from django_comment_client.utils import has_forum_access
from psychometrics import psychoanalyze from psychometrics import psychoanalyze
from student.models import CourseEnrollment, CourseEnrollmentAllowed from student.models import CourseEnrollment, CourseEnrollmentAllowed
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import InvalidLocationError, ItemNotFoundError, NoPathToItem
from xmodule.modulestore.search import path_to_location
import xmodule.graders as xmgraders import xmodule.graders as xmgraders
import track.views import track.views
...@@ -48,14 +42,15 @@ from .offline_gradecalc import student_grades, offline_grades_available ...@@ -48,14 +42,15 @@ from .offline_gradecalc import student_grades, offline_grades_available
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
template_imports = {'urllib': urllib}
# internal commands for managing forum roles: # internal commands for managing forum roles:
FORUM_ROLE_ADD = 'add' FORUM_ROLE_ADD = 'add'
FORUM_ROLE_REMOVE = 'remove' FORUM_ROLE_REMOVE = 'remove'
def split_by_comma_and_whitespace(s): def split_by_comma_and_whitespace(s):
"""
Return string s, split by , or whitespace
"""
return re.split(r'[\s,]', s) return re.split(r'[\s,]', s)
...@@ -141,7 +136,7 @@ def instructor_dashboard(request, course_id): ...@@ -141,7 +136,7 @@ def instructor_dashboard(request, course_id):
# 'beta', so adding it to get_access_group_name doesn't really make # 'beta', so adding it to get_access_group_name doesn't really make
# sense. # sense.
name = course_beta_test_group_name(course.location) name = course_beta_test_group_name(course.location)
(group, created) = Group.objects.get_or_create(name=name) (group, _) = Group.objects.get_or_create(name=name)
return group return group
# process actions from form POST # process actions from form POST
...@@ -237,13 +232,13 @@ def instructor_dashboard(request, course_id): ...@@ -237,13 +232,13 @@ def instructor_dashboard(request, course_id):
if '/' not in problem_to_reset: # allow state of modules other than problem to be reset if '/' not in problem_to_reset: # allow state of modules other than problem to be reset
problem_to_reset = "problem/" + problem_to_reset # but problem is the default problem_to_reset = "problem/" + problem_to_reset # but problem is the default
try: try:
(org, course_name, run) = course_id.split("/") (org, course_name, _) = course_id.split("/")
module_state_key = "i4x://" + org + "/" + course_name + "/" + problem_to_reset module_state_key = "i4x://" + org + "/" + course_name + "/" + problem_to_reset
module_to_reset = StudentModule.objects.get(student_id=student_to_reset.id, module_to_reset = StudentModule.objects.get(student_id=student_to_reset.id,
course_id=course_id, course_id=course_id,
module_state_key=module_state_key) module_state_key=module_state_key)
msg += "Found module to reset. " msg += "Found module to reset. "
except Exception as e: except Exception:
msg += "<font color='red'>Couldn't find module with that urlname. </font>" msg += "<font color='red'>Couldn't find module with that urlname. </font>"
if "Delete student state for problem" in action: if "Delete student state for problem" in action:
...@@ -352,7 +347,7 @@ def instructor_dashboard(request, course_id): ...@@ -352,7 +347,7 @@ def instructor_dashboard(request, course_id):
return_csv('', datatable, fp=fp) return_csv('', datatable, fp=fp)
fp.seek(0) fp.seek(0)
files = {'datafile': fp} files = {'datafile': fp}
msg2, dataset = _do_remote_gradebook(request.user, course, 'post-grades', files=files) msg2, _ = _do_remote_gradebook(request.user, course, 'post-grades', files=files)
msg += msg2 msg += msg2
...@@ -423,7 +418,7 @@ def instructor_dashboard(request, course_id): ...@@ -423,7 +418,7 @@ def instructor_dashboard(request, course_id):
datatable = {'header': ['username', 'email'] + profkeys} datatable = {'header': ['username', 'email'] + profkeys}
def getdat(u): def getdat(u):
p = u.profile p = u.profile
return [u.username, u.email] + [getattr(p,x,'') for x in profkeys] return [u.username, u.email] + [getattr(p, x, '') for x in profkeys]
datatable['data'] = [getdat(u) for u in enrolled_students] datatable['data'] = [getdat(u) for u in enrolled_students]
datatable['title'] = 'Student profile data for course %s' % course_id datatable['title'] = 'Student profile data for course %s' % course_id
...@@ -433,17 +428,17 @@ def instructor_dashboard(request, course_id): ...@@ -433,17 +428,17 @@ def instructor_dashboard(request, course_id):
elif 'Download CSV of all responses to problem' in action: elif 'Download CSV of all responses to problem' in action:
problem_to_dump = request.POST.get('problem_to_dump','') problem_to_dump = request.POST.get('problem_to_dump','')
if problem_to_dump[-4:]==".xml": if problem_to_dump[-4:] == ".xml":
problem_to_dump=problem_to_dump[:-4] problem_to_dump = problem_to_dump[:-4]
try: try:
(org, course_name, run)=course_id.split("/") (org, course_name, run) = course_id.split("/")
module_state_key="i4x://"+org+"/"+course_name+"/problem/"+problem_to_dump module_state_key = "i4x://" + org + "/" + course_name + "/problem/" + problem_to_dump
smdat = StudentModule.objects.filter(course_id=course_id, smdat = StudentModule.objects.filter(course_id=course_id,
module_state_key=module_state_key) module_state_key=module_state_key)
smdat = smdat.order_by('student') smdat = smdat.order_by('student')
msg += "Found %d records to dump " % len(smdat) msg += "Found %d records to dump " % len(smdat)
except Exception as err: except Exception as err:
msg+="<font color='red'>Couldn't find module with that urlname. </font>" msg += "<font color='red'>Couldn't find module with that urlname. </font>"
msg += "<pre>%s</pre>" % escape(err) msg += "<pre>%s</pre>" % escape(err)
smdat = [] smdat = []
...@@ -741,7 +736,7 @@ def _list_course_forum_members(course_id, rolename, datatable): ...@@ -741,7 +736,7 @@ def _list_course_forum_members(course_id, rolename, datatable):
# make sure datatable is set up properly for display first, before checking for errors # make sure datatable is set up properly for display first, before checking for errors
datatable['header'] = ['Username', 'Full name', 'Roles'] datatable['header'] = ['Username', 'Full name', 'Roles']
datatable['title'] = 'List of Forum {0}s in course {1}'.format(rolename, course_id) datatable['title'] = 'List of Forum {0}s in course {1}'.format(rolename, course_id)
datatable['data'] = []; datatable['data'] = []
try: try:
role = Role.objects.get(name=rolename, course_id=course_id) role = Role.objects.get(name=rolename, course_id=course_id)
except Role.DoesNotExist: except Role.DoesNotExist:
...@@ -923,7 +918,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True, ...@@ -923,7 +918,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
datarow = [student.id, student.username, student.profile.name, student.email] datarow = [student.id, student.username, student.profile.name, student.email]
try: try:
datarow.append(student.externalauthmap.external_email) datarow.append(student.externalauthmap.external_email)
except: # ExternalAuthMap.DoesNotExist except: # ExternalAuthMap.DoesNotExist
datarow.append('') datarow.append('')
if get_grades: if get_grades:
...@@ -1040,7 +1035,8 @@ def _do_enroll_students(course, course_id, students, overload=False): ...@@ -1040,7 +1035,8 @@ def _do_enroll_students(course, course_id, students, overload=False):
datatable['data'] = [[x, status[x]] for x in status] datatable['data'] = [[x, status[x]] for x in status]
datatable['title'] = 'Enrollment of students' datatable['title'] = 'Enrollment of students'
def sf(stat): return [x for x in status if status[x] == stat] def sf(stat):
return [x for x in status if status[x] == stat]
data = dict(added=sf('added'), rejected=sf('rejected') + sf('exists'), data = dict(added=sf('added'), rejected=sf('rejected') + sf('exists'),
deleted=sf('deleted'), datatable=datatable) deleted=sf('deleted'), datatable=datatable)
...@@ -1136,7 +1132,7 @@ def dump_grading_context(course): ...@@ -1136,7 +1132,7 @@ def dump_grading_context(course):
''' '''
msg = "-----------------------------------------------------------------------------\n" msg = "-----------------------------------------------------------------------------\n"
msg += "Course grader:\n" msg += "Course grader:\n"
msg += '%s\n' % course.grader.__class__ msg += '%s\n' % course.grader.__class__
graders = {} graders = {}
if isinstance(course.grader, xmgraders.WeightedSubsectionsGrader): if isinstance(course.grader, xmgraders.WeightedSubsectionsGrader):
...@@ -1151,7 +1147,7 @@ def dump_grading_context(course): ...@@ -1151,7 +1147,7 @@ def dump_grading_context(course):
gc = course.grading_context gc = course.grading_context
msg += "graded sections:\n" msg += "graded sections:\n"
msg += '%s\n' % gc['graded_sections'].keys() msg += '%s\n' % gc['graded_sections'].keys()
for (gs, gsvals) in gc['graded_sections'].items(): for (gs, gsvals) in gc['graded_sections'].items():
msg += "--> Section %s:\n" % (gs) msg += "--> Section %s:\n" % (gs)
......
...@@ -27,8 +27,6 @@ from mitxmako.shortcuts import render_to_string ...@@ -27,8 +27,6 @@ from mitxmako.shortcuts import render_to_string
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
template_imports = {'urllib': urllib}
system = ModuleSystem( system = ModuleSystem(
ajax_url=None, ajax_url=None,
track_function=None, track_function=None,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment