diff --git a/cms/djangoapps/models/settings/course_grading.py b/cms/djangoapps/models/settings/course_grading.py index e111a19a88..6c24989915 100644 --- a/cms/djangoapps/models/settings/course_grading.py +++ b/cms/djangoapps/models/settings/course_grading.py @@ -144,25 +144,21 @@ class CourseGradingModel: @staticmethod def update_grace_period_from_json(course_location, graceperiodjson): """ - Update the course's default grace period. + Update the course's default grace period. Incoming dict is {hours: h, minutes: m} possibly as a + grace_period entry in an enclosing dict. """ if not isinstance(course_location, Location): course_location = Location(course_location) - if not isinstance(graceperiodjson, dict): - graceperiodjson = {'grace_period' : graceperiodjson} + if 'grace_period' in graceperiodjson: + graceperiodjson = graceperiodjson['grace_period'] - grace_time = converters.jsdate_to_time(graceperiodjson['grace_period']) - # NOTE: this does not handle > 24 hours - grace_rep = time.strftime("%H hours %M minutes %S seconds", grace_time) + grace_rep = " ".join(["%s %s" % (value, key) for (key, value) in graceperiodjson.iteritems()]) descriptor = get_modulestore(course_location).get_item(course_location) descriptor.metadata['graceperiod'] = grace_rep get_modulestore(course_location).update_metadata(course_location, descriptor.metadata) - return graceperiodjson - - @staticmethod def delete_grader(course_location, index): """ @@ -212,9 +208,7 @@ class CourseGradingModel: rawgrace = descriptor.metadata.get('graceperiod', None) if rawgrace: parsedgrace = {str(key): val for (val, key) in re.findall('\s*(\d*)\s*(\w*)', rawgrace)} - gracedate = datetime.datetime.today() - gracedate = gracedate.replace(minute = int(parsedgrace.get('minutes',0)), hour = int(parsedgrace.get('hours',0))) - return gracedate.isoformat() + 'Z' + return parsedgrace else: return None @staticmethod @@ -238,4 +232,4 @@ class CourseGradingModel: if not 'short_label' in grader: grader['short_label'] = "" - return grader \ No newline at end of file + return grader diff --git a/cms/static/coffee/src/client_templates/course_grade_policy.html b/cms/static/client_templates/course_grade_policy.html similarity index 100% rename from cms/static/coffee/src/client_templates/course_grade_policy.html rename to cms/static/client_templates/course_grade_policy.html diff --git a/cms/static/coffee/src/client_templates/course_info_update.html b/cms/static/coffee/src/client_templates/course_info_update.html deleted file mode 100644 index 54a4a38dde..0000000000 --- a/cms/static/coffee/src/client_templates/course_info_update.html +++ /dev/null @@ -1,28 +0,0 @@ -
  • - -
    -
    - - - -
    -
    - -
    -
    - - Save - Cancel -
    -
    -

    - <%= - updateModel.get('date') %> -

    -
    <%= updateModel.get('content') %>
    -
    - Edit - Delete -
    -
  • \ No newline at end of file diff --git a/cms/static/coffee/src/client_templates/load_templates.html b/cms/static/coffee/src/client_templates/load_templates.html deleted file mode 100644 index 3ff88d6fe5..0000000000 --- a/cms/static/coffee/src/client_templates/load_templates.html +++ /dev/null @@ -1,14 +0,0 @@ - - -<%block name="jsextra"> - - - - \ No newline at end of file diff --git a/cms/static/js/models/settings/course_grading_policy.js b/cms/static/js/models/settings/course_grading_policy.js index c2f88d0789..3c5f18b1cf 100644 --- a/cms/static/js/models/settings/course_grading_policy.js +++ b/cms/static/js/models/settings/course_grading_policy.js @@ -5,15 +5,12 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({ course_location : null, graders : null, // CourseGraderCollection grade_cutoffs : null, // CourseGradeCutoff model - grace_period : null // either null or seconds of grace period + grace_period : null // either null or { hours: n, minutes: m, ...} }, parse: function(attributes) { if (attributes['course_location']) { attributes.course_location = new CMS.Models.Location(attributes.course_location, {parse:true}); } - if (attributes['grace_period']) { - attributes.grace_period = new Date(attributes.grace_period); - } if (attributes['graders']) { var graderCollection; if (this.has('graders')) { @@ -31,6 +28,23 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({ url : function() { var location = this.get('course_location'); return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/grading'; + }, + gracePeriodToDate : function() { + var newDate = new Date(); + if (this.has('grace_period') && this.get('grace_period')['hours']) + newDate.setHours(this.get('grace_period')['hours']); + else newDate.setHours(0); + if (this.has('grace_period') && this.get('grace_period')['minutes']) + newDate.setMinutes(this.get('grace_period')['minutes']); + else newDate.setMinutes(0); + if (this.has('grace_period') && this.get('grace_period')['seconds']) + newDate.setSeconds(this.get('grace_period')['seconds']); + else newDate.setSeconds(0); + + return newDate; + }, + dateToGracePeriod : function(date) { + return {hours : date.getHours(), minutes : date.getMinutes(), seconds : date.getSeconds() }; } }); diff --git a/cms/static/js/views/settings/main_settings_view.js b/cms/static/js/views/settings/main_settings_view.js index 51d2e69a58..67d39820c7 100644 --- a/cms/static/js/views/settings/main_settings_view.js +++ b/cms/static/js/views/settings/main_settings_view.js @@ -292,8 +292,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ // instantiates an editor template for each update in the collection // Because this calls render, put it after everything which render may depend upon to prevent race condition. window.templateLoader.loadRemoteTemplate("course_info_update", - // TODO Where should the template reside? how to use the static.url to create the path? - "/static/coffee/src/client_templates/course_grade_policy.html", + "/static/client_templates/course_grade_policy.html", function (raw_template) { self.template = _.template(raw_template); self.render(); @@ -306,6 +305,9 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ }, render: function() { + // prevent bootstrap race condition by event dispatch + if (!this.template) return; + // Create and render the grading type subs var self = this; var gradelist = this.$el.find('.course-grading-assignment-list'); @@ -322,7 +324,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ var graceEle = this.$el.find('#course-grading-graceperiod'); graceEle.timepicker({'timeFormat' : 'H:i'}); // init doesn't take setTime - graceEle.timepicker('setTime', (this.model.has('grace_period') ? this.model.get('grace_period') : new Date(0))); + graceEle.timepicker('setTime', this.model.gracePeriodToDate()); return this; }, @@ -338,7 +340,7 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ switch (this.selectorToField[event.currentTarget.id]) { case 'grace_period': this.clearValidationErrors(); - this.model.save('grace_period', $(event.currentTarget).timepicker('getTime')); + this.model.save('grace_period', this.model.dateToGracePeriod($(event.currentTarget).timepicker('getTime'))); break; default: @@ -379,7 +381,6 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({ newBar = gradelist.children().last(); // get the dom object not the unparsed string newBar.resizable({ handles: "e", - // TODO perhaps add a start which sets minWidth to next element's edge containment : "parent", start : this.startMoveClosure(), resize : this.moveBarClosure(), diff --git a/cms/static/sass/_base.scss b/cms/static/sass/_base.scss index 3957cb60d9..a91d703d0f 100644 --- a/cms/static/sass/_base.scss +++ b/cms/static/sass/_base.scss @@ -181,11 +181,6 @@ code { padding: 20px; } - .details { - margin-bottom: 30px; - font-size: 14px; - } - h4 { padding: 6px 14px; border-bottom: 1px solid #cbd1db; @@ -343,29 +338,4 @@ body.show-wip { content: ''; @extend .spinner-icon; } -} - -.new-button { - @include grey-button; - padding: 20px 0; - text-align: center; - - &.big { - display: block; - } -} - -.edit-button.standard, -.delete-button.standard { - float: left; - @include white-button; - padding: 3px 10px 4px; - margin-left: 7px; - font-size: 12px; - font-weight: 400; - - .edit-icon, - .delete-icon { - margin-right: 4px; - } } \ No newline at end of file diff --git a/cms/static/sass/_cms_mixins.scss b/cms/static/sass/_cms_mixins.scss index 3a8f24b5a9..2f43bfd208 100644 --- a/cms/static/sass/_cms_mixins.scss +++ b/cms/static/sass/_cms_mixins.scss @@ -51,14 +51,14 @@ @include button; border: 1px solid $darkGrey; border-radius: 3px; - @include linear-gradient(top, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0)); + @include linear-gradient(top, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0) 60%); background-color: #dfe5eb; @include box-shadow(0 1px 0 rgba(255, 255, 255, .3) inset); - color: #778192; + color: #5d6779; &:hover { background-color: #f2f6f9; - color: #778192; + color: #5d6779; } } diff --git a/cms/static/sass/_course-info.scss b/cms/static/sass/_course-info.scss index 2ec22ebfea..6eb08943b1 100644 --- a/cms/static/sass/_course-info.scss +++ b/cms/static/sass/_course-info.scss @@ -1,179 +1,77 @@ -.course-info { +body.updates { h2 { margin-bottom: 24px; font-size: 22px; font-weight: 300; } - - .course-info-wrapper { - display: table; - width: 100%; - clear: both; - } - - .main-column, - .course-handouts { - float: none; - display: table-cell; - } - - .main-column { - border-radius: 3px 0 0 3px; - border-right-color: $mediumGrey; - } - - .CodeMirror { - border: 1px solid #3c3c3c; - background: #fff; - color: #3c3c3c; - } } .course-updates { padding: 30px 40px; - margin: 0; - .update-list > li { - padding: 34px 0 42px; + li { + padding: 24px 0 32px; border-top: 1px solid #cbd1db; + } - &.editing { - position: relative; - z-index: 1001; - padding: 0; - border-top: none; - border-radius: 3px; - background: #fff; - - .post-preview { - display: none; - } - } - - h1 { - float: none; - font-size: 24px; - font-weight: 300; - } - - h2 { - margin-bottom: 18px; - font-size: 14px; - font-weight: 700; - line-height: 30px; - color: #646464; - letter-spacing: 1px; - text-transform: uppercase; - } - - h3 { - margin: 34px 0 11px; - font-size: 16px; - font-weight: 700; - } + h3 { + margin-bottom: 18px; + font-size: 14px; + font-weight: 700; + color: #646464; + letter-spacing: 1px; + text-transform: uppercase; } .update-contents { + padding-left: 30px; + p { - font-size: 16px; - line-height: 25px; + font-size: 14px; + line-height: 18px; } p + p { - margin-top: 25px; - } - - .primary { - border: 1px solid #ddd; - background: #f6f6f6; - padding: 20px; + margin-top: 18px; } } .new-update-button { - @include blue-button; + @include grey-button; display: block; text-align: center; - padding: 18px 0; + padding: 12px 0; margin-bottom: 28px; } .new-update-form { @include edit-box; margin-bottom: 24px; - padding: 30px; - border: none; textarea { height: 180px; } } - - .post-actions { - float: right; - - .edit-button, - .delete-button{ - float: left; - @include white-button; - padding: 3px 10px 4px; - margin-left: 7px; - font-size: 12px; - font-weight: 400; - - .edit-icon, - .delete-icon { - margin-right: 4px; - } - } - } } .course-handouts { - width: 30%; - padding: 20px 30px; - margin: 0; - border-radius: 0 3px 3px 0; - border-left: none; - background: $lightGrey; + padding: 15px 20px; - h2 { - font-size: 18px; - font-weight: 700; + .new-handout-button { + @include grey-button; + display: block; + text-align: center; + padding: 12px 0; + margin-bottom: 28px; } - .edit-button { - float: right; - @include white-button; - padding: 3px 10px 4px; - margin-left: 7px; - font-size: 12px; - font-weight: 400; - - .edit-icon, - .delete-icon { - margin-right: 4px; - } - } - - .handouts-content { + li { + margin-bottom: 10px; font-size: 14px; } - .treeview-handoutsnav li { - margin-bottom: 12px; - } -} - -.edit-handouts-form { - @include edit-box; - position: absolute; - right: 0; - z-index: 10001; - width: 800px; - padding: 30px; - - textarea { - height: 300px; + .new-handout-form { + @include edit-box; + margin-bottom: 24px; } } \ No newline at end of file diff --git a/cms/static/sass/_courseware.scss b/cms/static/sass/_courseware.scss index 23024f74e4..094b6183dd 100644 --- a/cms/static/sass/_courseware.scss +++ b/cms/static/sass/_courseware.scss @@ -5,7 +5,12 @@ input.courseware-unit-search-input { } .courseware-overview { - + .new-courseware-section-button { + @include grey-button; + display: block; + text-align: center; + padding: 12px 0; + } } .courseware-section { @@ -141,18 +146,18 @@ input.courseware-unit-search-input { .section-name-edit { input { - font-size: 16px; + font-size: 16px; } .save-button { @include blue-button; - padding: 10px 20px; + padding: 7px 20px 7px; margin-right: 5px; } .cancel-button { @include white-button; - padding: 10px 20px; + padding: 7px 20px 7px; } } @@ -200,7 +205,7 @@ input.courseware-unit-search-input { .new-section-name-save, .new-subsection-name-save { @include blue-button; - padding: 6px 20px 8px; + padding: 2px 20px 5px; margin: 0 5px; color: #fff !important; } @@ -208,7 +213,7 @@ input.courseware-unit-search-input { .new-section-name-cancel, .new-subsection-name-cancel { @include white-button; - padding: 6px 20px 8px; + padding: 2px 20px 5px; color: #8891a1 !important; } diff --git a/cms/static/sass/_dashboard.scss b/cms/static/sass/_dashboard.scss index 8821f3736c..8763927bdb 100644 --- a/cms/static/sass/_dashboard.scss +++ b/cms/static/sass/_dashboard.scss @@ -89,7 +89,6 @@ .new-course-save { @include blue-button; - // padding: ; } .new-course-cancel { diff --git a/cms/static/sass/_graphics.scss b/cms/static/sass/_graphics.scss index 4a63a8a885..c6d775ed12 100644 --- a/cms/static/sass/_graphics.scss +++ b/cms/static/sass/_graphics.scss @@ -137,10 +137,6 @@ height: 11px; margin-right: 8px; background: url(../img/plus-icon.png) no-repeat; - - &.white { - background: url(../img/plus-icon-white.png) no-repeat; - } } .plus-icon-small { diff --git a/cms/static/sass/_static-pages.scss b/cms/static/sass/_static-pages.scss index c8ffa0316c..628d537f90 100644 --- a/cms/static/sass/_static-pages.scss +++ b/cms/static/sass/_static-pages.scss @@ -6,72 +6,6 @@ padding: 12px 0; } - .unit-body { - padding: 30px 40px; - } - - .components > li { - margin: 0; - border-radius: 0; - - &.new-component-item { - margin-top: 20px; - } - } - - .component { - border: 1px solid $mediumGrey; - border-top: none; - - &:first-child { - border-top: 1px solid $mediumGrey; - } - - &:hover { - border: 1px solid $mediumGrey; - border-top: none; - - &:first-child { - border-top: 1px solid $mediumGrey; - } - - .drag-handle { - background: url(../img/drag-handles.png) center no-repeat $lightGrey; - } - } - - .drag-handle { - top: 0; - right: 0; - z-index: 11; - width: 35px; - border: none; - background: url(../img/drag-handles.png) center no-repeat $lightGrey; - - &:hover { - background: url(../img/drag-handles.png) center no-repeat $lightGrey; - } - } - - .component-actions { - top: 26px; - right: 44px; - } - } - - .component.editing { - .xmodule_display { - display: none; - } - } - - .xmodule_display { - padding: 20px 20px 22px; - font-size: 24px; - font-weight: 300; - background: $lightGrey; - } - .static-page-item { position: relative; margin: 10px 0; diff --git a/cms/static/sass/_unit.scss b/cms/static/sass/_unit.scss index fdf737fc12..220bec507d 100644 --- a/cms/static/sass/_unit.scss +++ b/cms/static/sass/_unit.scss @@ -4,7 +4,6 @@ } .main-column { - clear: both; float: left; width: 70%; } @@ -55,11 +54,94 @@ position: relative; z-index: 10; margin: 20px 40px; + border: 1px solid #d1ddec; + border-radius: 3px; + background: #fff; + @include transition(none); + + &:hover { + border-color: #6696d7; + + .drag-handle, + .component-actions a { + background-color: $blue; + } + + .drag-handle { + border-color: $blue; + } + } + + &.editing { + border-color: #6696d7; + + .drag-handle, + .component-actions { + display: none; + } + } + + &.component-placeholder { + border-color: #6696d7; + } + + .xmodule_display { + padding: 40px 20px 20px; + } + + .component-actions { + position: absolute; + top: 4px; + right: 4px; + @include transition(opacity .15s); + } + + .edit-button, + .delete-button { + float: left; + padding: 3px 10px 4px; + margin-left: 3px; + border: 1px solid #fff; + border-radius: 3px; + background: #d1ddec; + font-size: 12px; + color: #fff; + @include transition(all .15s); + + &:hover { + background-color: $blue; + color: #fff; + } + + .edit-icon, + .delete-icon { + margin-right: 4px; + } + } + + .drag-handle { + position: absolute; + display: block; + top: -1px; + right: -16px; + z-index: -1; + width: 15px; + height: 100%; + border-radius: 0 3px 3px 0; + border: 1px solid #d1ddec; + background: url(../img/white-drag-handles.png) center no-repeat #d1ddec; + cursor: move; + @include transition(all .15s); + } &.new-component-item { padding: 0; - border: none; - border-radius: 0; + border: 1px solid #8891a1; + border-radius: 3px; + @include linear-gradient(top, rgba(255, 255, 255, .3), rgba(255, 255, 255, 0)); + background-color: #d1dae3; + @include box-shadow(0 1px 0 rgba(255, 255, 255, .2) inset); + @include transition(background-color .15s, border-color .15s); &.adding { background-color: $blue; @@ -141,63 +223,8 @@ } } - .component { - border: 1px solid #d1ddec; - border-radius: 3px; - background: #fff; - @include transition(none); - - &:hover { - border-color: #6696d7; - - .drag-handle { - background-color: $blue; - border-color: $blue; - } - } - - &.editing { - border-color: #6696d7; - - .drag-handle, - .component-actions { - display: none; - } - } - - &.component-placeholder { - border-color: #6696d7; - } - - .component-actions { - position: absolute; - top: 7px; - right: 9px; - @include transition(opacity .15s); - - a { - color: $darkGrey; - } - } - - .drag-handle { - position: absolute; - display: block; - top: -1px; - right: -16px; - z-index: -1; - width: 15px; - height: 100%; - border-radius: 0 3px 3px 0; - border: 1px solid #d1ddec; - background: url(../img/white-drag-handles.png) center no-repeat #d1ddec; - cursor: move; - @include transition(all .15s); - } - } - .xmodule_display { - padding: 40px 20px 20px; + padding: 10px 20px; } .component-editor { diff --git a/cms/static/sass/_users.scss b/cms/static/sass/_users.scss index bca9b4f2fb..7c60ee5c3b 100644 --- a/cms/static/sass/_users.scss +++ b/cms/static/sass/_users.scss @@ -2,6 +2,11 @@ .user-overview { @extend .window; padding: 30px 40px; + + .details { + margin-bottom: 20px; + font-size: 14px; + } } .new-user-button { diff --git a/cms/static/sass/base-style.scss b/cms/static/sass/base-style.scss index e8dbde3c12..73812125a8 100644 --- a/cms/static/sass/base-style.scss +++ b/cms/static/sass/base-style.scss @@ -25,7 +25,6 @@ @import "modal"; @import "alerts"; @import "login"; -@import "lms"; @import 'jquery-ui-calendar'; @import 'content-types'; diff --git a/common/static/js/vendor/underscore-min.js b/common/static/js/vendor/underscore-min.js index 5a0cb3b008..7ed6e5284f 100644 --- a/common/static/js/vendor/underscore-min.js +++ b/common/static/js/vendor/underscore-min.js @@ -1,32 +1 @@ -// Underscore.js 1.3.3 -// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Underscore is freely distributable under the MIT license. -// Portions of Underscore are inspired or borrowed from Prototype, -// Oliver Steele's Functional, and John Resig's Micro-Templating. -// For all details and documentation: -// http://documentcloud.github.com/underscore -(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== -c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break; -g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a, -c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(A&& -a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a, -c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b, -a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= -function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]}; -j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a= -i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&& -c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty= -function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"}; -b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a, -b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId= -function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape|| -u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c}; -b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d, -this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,v=e.reduce,h=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.3";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduce===v)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduceRight===h)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?-1!=n.indexOf(t):E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2);return w.map(n,function(n){return(w.isFunction(t)?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t){return w.isEmpty(t)?[]:w.filter(n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var F=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=F(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.indexi;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i};var I=function(){};w.bind=function(n,t){var r,e;if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));if(!w.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));I.prototype=n.prototype;var u=new I;I.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},w.bindAll=function(n){var t=o.call(arguments,1);return 0==t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=S(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&S(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return S(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),w.isFunction=function(n){return"function"==typeof n},w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return void 0===n},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+(0|Math.random()*(t-n+1))};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};T.unescape=w.invert(T.escape);var M={escape:RegExp("["+w.keys(T.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(T.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(M[n],function(t){return T[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=""+ ++N;return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){r=w.defaults({},r,w.templateSettings);var e=RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),u=0,i="__p+='";n.replace(e,function(t,r,e,a,o){return i+=n.slice(u,o).replace(D,function(n){return"\\"+B[n]}),r&&(i+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(i+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),a&&(i+="';\n"+a+"\n__p+='"),u=o+t.length,t}),i+="';\n",r.variable||(i="with(obj||{}){\n"+i+"}\n"),i="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+i+"return __p;\n";try{var a=Function(r.variable||"obj","_",i)}catch(o){throw o.source=i,o}if(t)return a(t,w);var c=function(n){return a.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+i+"}",c},w.chain=function(n){return w(n).chain()};var z=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file