diff --git a/lms/static/images/search-icon.png b/lms/static/images/search-icon.png new file mode 100644 index 0000000000..22b0d2d3c2 Binary files /dev/null and b/lms/static/images/search-icon.png differ diff --git a/lms/static/js/jquery.gradebook.js b/lms/static/js/jquery.gradebook.js new file mode 100644 index 0000000000..187e58189f --- /dev/null +++ b/lms/static/js/jquery.gradebook.js @@ -0,0 +1,76 @@ + + + +var Gradebook = function($element) { + var _this = this; + var $element = $element; + var $grades = $element.find('.grades'); + var $gradeTable = $element.find('.grade-table'); + var $leftShadow = $('
'); + var $rightShadow = $('
'); + var tableHeight = $gradeTable.height(); + var maxScroll = $gradeTable.width() - $grades.width(); + var $body = $('body'); + var mouseOrigin; + var tableOrigin; + + var startDrag = function(e) { + mouseOrigin = e.pageX; + tableOrigin = $gradeTable.position().left; + $body.css('-webkit-user-select', 'none'); + $body.bind('mousemove', moveDrag); + $body.bind('mouseup', stopDrag); + }; + + var moveDrag = function(e) { + var offset = e.pageX - mouseOrigin; + var targetLeft = clamp(tableOrigin + offset, -maxScroll, 0); + + updateHorizontalPosition(targetLeft); + + setShadows(targetLeft); + }; + + var stopDrag = function(e) { + $body.css('-webkit-user-select', 'auto'); + $body.unbind('mousemove', moveDrag); + $body.unbind('mouseup', stopDrag); + }; + + var setShadows = function(left) { + var padding = 30; + + var leftPercent = clamp(-left / padding, 0, 1); + $leftShadow.css('opacity', leftPercent); + + var rightPercent = clamp((maxScroll + left) / padding, 0, 1); + $rightShadow.css('opacity', rightPercent); + }; + + var clamp = function(val, min, max) { + if(val > max) return max; + if(val < min) return min; + return val; + }; + + var updateWidths = function(e) { + maxScroll = $gradeTable.width() - $grades.width(); + var targetLeft = clamp($gradeTable.position().left, -maxScroll, 0); + updateHorizontalPosition(targetLeft); + setShadows(targetLeft); + } + + var updateHorizontalPosition = function(left) { + $gradeTable.css({ + 'left': left + 'px' + }); + } + + $leftShadow.css('height', tableHeight + 'px'); + $rightShadow.css('height', tableHeight + 'px'); + $grades.append($leftShadow).append($rightShadow); + setShadows(0); + $grades.css('height', tableHeight); + $gradeTable.bind('mousedown', startDrag); + $(window).bind('resize', updateWidths); +} \ No newline at end of file diff --git a/lms/static/sass/course.scss b/lms/static/sass/course.scss index c874076a31..d3a74cb91b 100644 --- a/lms/static/sass/course.scss +++ b/lms/static/sass/course.scss @@ -10,7 +10,7 @@ @import 'shared/tooltips'; // Course base / layout styles -@import 'course/layout/courseware_subnav'; +@import 'course/layout/courseware_header'; @import 'course/base/base'; @import 'course/base/extends'; @import 'module/module-styles.scss'; diff --git a/lms/static/sass/course/_gradebook.scss b/lms/static/sass/course/_gradebook.scss index b94f5de178..cd3205149c 100644 --- a/lms/static/sass/course/_gradebook.scss +++ b/lms/static/sass/course/_gradebook.scss @@ -1,11 +1,203 @@ +$cell-border-color: #e1e1e1; +$table-border-color: #c8c8c8; + div.gradebook-wrapper { @extend .table-wrapper; section.gradebook-content { @extend .content; + .student-search { + padding: 0 20px 0 15px; + } + + .student-search-field { + width: 100%; + height: 27px; + padding: 0 15px 0 35px; + box-sizing: border-box; + border-radius: 13px; + border: 1px solid $table-border-color; + background: url(../images/search-icon.png) no-repeat 9px center #f6f6f6; + font-family: $sans-serif; + font-size: 11px; + @include box-shadow(0 1px 4px rgba(0, 0, 0, .12) inset); + outline: none; + @include transition(border-color .15s); + + &::-webkit-input-placeholder, + &::-moz-input-placeholder { + font-style: italic; + } + + &:focus { + border-color: #1d9dd9; + } + } + + .student-table { + float: left; + // width: 264px; + width: 24%; + border-radius: 3px 0 0 3px; + color: #3c3c3c; + + th { + height: 50px; + } + + tr:first-child td { + border-top: 1px solid $table-border-color; + border-radius: 5px 0 0 0; + } + + tr:last-child td { + border-bottom: 1px solid $table-border-color; + border-radius: 0 0 0 5px; + } + + td { + height: 50px; + padding-left: 20px; + border-bottom: 1px solid $cell-border-color; + border-left: 1px solid $table-border-color; + background: #f3f3f3; + font-size: 13px; + line-height: 50px; + } + + tr:nth-child(odd) td { + background-color: #fbfbfb; + } + } + + .grades { + position: relative; + float: left; + width: 76%; + overflow: hidden; + + .left-shadow, + .right-shadow { + position: absolute; + top: 0; + z-index: 9999; + width: 20px; + pointer-events: none; + } + + .left-shadow { + left: 0; + background: -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + } + + .right-shadow { + right: 0; + background: -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0)); + } + } + + .grade-table { + position: absolute; + top: 0; + left: 0; + width: 1000px; + cursor: move; + -webkit-transition: none; + -webkit-user-select: none; + user-select: none; + + td, + th { + width: 50px; + text-align: center; + } + + thead th { + position: relative; + height: 50px; + background: -webkit-linear-gradient(top, $cell-border-color, #ddd); + font-size: 10px; + line-height: 10px; + font-weight: bold; + text-align: center; + box-shadow: 0 1px 0 $table-border-color inset, 0 2px 0 rgba(255, 255, 255, .7) inset; + + &:before { + content: ''; + display: block; + position: absolute; + left: 0; + top: 0; + z-index: 9999; + width: 1px; + height: 100%; + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, .15)); + } + + &:first-child { + border-radius: 5px 0 0 0; + box-shadow: 1px 1px 0 $table-border-color inset, 1px 2px 0 rgba(255, 255, 255, .7) inset; + + &:before { + display: hidden; + } + } + + &:last-child { + border-radius: 0 3px 0 0; + box-shadow: -1px 1px 0 $table-border-color inset, -1px 2px 0 rgba(255, 255, 255, .7) inset; + } + + .assignment { + margin: 9px 0; + } + + .type, + .number, + .max { + display: block; + } + + .max { + height: 12px; + background: -webkit-linear-gradient(top, #c6c6c6, #bababa); + font-size: 9px; + line-height: 12px; + color: #fff; + } + } + + tr { + border-right: 1px solid $table-border-color; + } + + tr:first-child td { + border-top: 1px solid $table-border-color; + } + + tr:last-child td { + border-bottom: 1px solid $table-border-color; + } + + td { + height: 50px; + border-bottom: 1px solid $cell-border-color; + background: #f3f3f3; + font-size: 13px; + line-height: 50px; + border-left: 1px solid $cell-border-color; + } + + tr:nth-child(odd) td { + background-color: #fbfbfb; + } + } + h1 { @extend .top-header; } } -} \ No newline at end of file +} + + diff --git a/lms/static/sass/course/base/_extends.scss b/lms/static/sass/course/base/_extends.scss index c5e61f593e..04eaf73094 100644 --- a/lms/static/sass/course/base/_extends.scss +++ b/lms/static/sass/course/base/_extends.scss @@ -173,29 +173,3 @@ h1.top-header { @include transition( all, .2s, $ease-in-out-quad); } -.global { - .find-courses-button { - display: none; - } - - h2 { - display: block; - float: left; - font-size: 0.9em; - font-weight: 600; - letter-spacing: 0; - line-height: 40px; - overflow: hidden; - text-overflow: ellipsis; - text-shadow: 0 1px 0 #fff; - text-transform: none; - white-space: nowrap; - width: 700px; - - .provider { - font: inherit; - font-weight: bold; - color: #6d6d6d; - } - } -} diff --git a/lms/static/sass/course/layout/_courseware_header.scss b/lms/static/sass/course/layout/_courseware_header.scss new file mode 100644 index 0000000000..dfa30b43a0 --- /dev/null +++ b/lms/static/sass/course/layout/_courseware_header.scss @@ -0,0 +1,85 @@ +nav.course-material { + @include clearfix; + @include box-sizing(border-box); + background: #f6f6f6; + border-bottom: 1px solid rgb(200,200,200); + margin: 0px auto 0px; + padding: 0px; + width: 100%; + + .inner-wrapper { + margin: 0 auto; + max-width: 1200px; + width: flex-grid(12); + } + + ol.course-tabs { + @include border-top-radius(4px); + @include clearfix; + padding: 10px 0 0 0; + + li { + float: left; + list-style: none; + + a { + color: darken($lighter-base-font-color, 20%); + display: block; + text-align: center; + padding: 8px 13px 12px; + font-size: 14px; + font-weight: 400; + text-decoration: none; + text-shadow: 0 1px rgb(255,255,255); + + &:hover { + color: $base-font-color; + } + + &.active { + background: rgb(255,255,255); + border: 1px solid rgb(200,200,200); + border-bottom: 0px; + @include border-top-radius(4px); + @include box-shadow(0 2px 0 0 rgba(255,255,255, 1)); + color: $blue; + } + } + } + } +} + +.course-content { + margin-top: 30px; + + .courseware { + min-height: 300px; + } +} + +.global { + .find-courses-button { + display: none; + } + + h2 { + display: block; + width: 700px; + float: left; + font-size: 0.9em; + font-weight: 600; + line-height: 40px; + letter-spacing: 0; + text-transform: none; + text-shadow: 0 1px 0 #fff; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + + .provider { + font: inherit; + font-weight: bold; + color: #6d6d6d; + } + } +} \ No newline at end of file diff --git a/lms/templates/gradebook.html b/lms/templates/gradebook.html index a4a81a6868..787fc23c9a 100644 --- a/lms/templates/gradebook.html +++ b/lms/templates/gradebook.html @@ -6,6 +6,7 @@ + <%block name="headextra"> @@ -19,6 +20,12 @@ .grade_None {color:LightGray;} + + <%include file="course_navigation.html" args="active_page=''" /> @@ -28,50 +35,75 @@

Gradebook

- %if len(students) > 0: - - <% - templateSummary = students[0]['grade_summary'] - %> - - - - - %for section in templateSummary['section_breakdown']: - +
Student${section['label']}
+ + + + + + + %for student in students: + + + %endfor - - - - <%def name="percent_data(fraction)"> - <% - letter_grade = 'None' - if fraction > 0: - letter_grade = 'F' - for grade in ['A', 'B', 'C']: - if fraction >= course.grade_cutoffs[grade]: - letter_grade = grade - break - - data_class = "grade_" + letter_grade - %> - - - - %for student in students: - - - %for section in student['grade_summary']['section_breakdown']: - ${percent_data( section['percent'] )} - %endfor - - - %endfor +
+ +
+ ${student['username']} +
Total
${ "{0:.0f}".format( 100 * fraction ) }
- ${student['username']}${percent_data( student['grade_summary']['percent'])}
+ + + + %if len(students) > 0: +
+ + <% + templateSummary = students[0]['grade_summary'] + %> + + + %for section in templateSummary['section_breakdown']: + + %endfor + + + + + <%def name="percent_data(fraction)"> + <% + letter_grade = 'None' + if fraction > 0: + letter_grade = 'F' + for grade in ['A', 'B', 'C']: + if fraction >= course.grade_cutoffs[grade]: + letter_grade = grade + break + + data_class = "grade_" + letter_grade + %> + + + + + %for student in students: + + %for section in student['grade_summary']['section_breakdown']: + ${percent_data( section['percent'] )} + %endfor + + + %endfor + +
${section['label']}Total
${ "{0:.0f}".format( 100 * fraction ) }
${percent_data( student['grade_summary']['percent'])}
+
+ %endif
+ +