diff --git a/.pylintrc b/.pylintrc index 9ea1e62ad4..2f2be69eb0 100644 --- a/.pylintrc +++ b/.pylintrc @@ -34,6 +34,7 @@ load-plugins= # multiple time (only on the command line, not in the configuration file where # it should appear only once). disable= +# C0301: Line too long # W0141: Used builtin function 'map' # W0142: Used * or ** magic # R0201: Method could be a function @@ -42,7 +43,7 @@ disable= # R0903: Too few public methods (1/2) # R0904: Too many public methods # R0913: Too many arguments - W0141,W0142,R0201,R0901,R0902,R0903,R0904,R0913 + C0301,W0141,W0142,R0201,R0901,R0902,R0903,R0904,R0913 [REPORTS] diff --git a/cms/djangoapps/contentstore/features/common.py b/cms/djangoapps/contentstore/features/common.py index 3878340af3..afb38c3f9e 100644 --- a/cms/djangoapps/contentstore/features/common.py +++ b/cms/djangoapps/contentstore/features/common.py @@ -9,6 +9,9 @@ from xmodule.modulestore.django import _MODULESTORES, modulestore from xmodule.templates import update_templates from auth.authz import get_user_by_email +from selenium.webdriver.common.keys import Keys +import time + from logging import getLogger logger = getLogger(__name__) @@ -140,3 +143,14 @@ def add_subsection(name='Subsection One'): save_css = 'input.new-subsection-name-save' world.css_fill(name_css, name) world.css_click(save_css) + + +def set_date_and_time(date_css, desired_date, time_css, desired_time): + world.css_fill(date_css, desired_date) + # hit TAB to get to the time field + e = world.css_find(date_css).first + e._element.send_keys(Keys.TAB) + world.css_fill(time_css, desired_time) + e = world.css_find(time_css).first + e._element.send_keys(Keys.TAB) + time.sleep(float(1)) diff --git a/cms/djangoapps/contentstore/features/section.py b/cms/djangoapps/contentstore/features/section.py index 0c0f5536a0..fca14e21f0 100644 --- a/cms/djangoapps/contentstore/features/section.py +++ b/cms/djangoapps/contentstore/features/section.py @@ -4,8 +4,6 @@ from lettuce import world, step from common import * from nose.tools import assert_equal -from selenium.webdriver.common.keys import Keys -import time ############### ACTIONS #################### @@ -39,16 +37,8 @@ def i_click_the_edit_link_for_the_release_date(step): @step('I save a new section release date$') def i_save_a_new_section_release_date(step): - date_css = 'input.start-date.date.hasDatepicker' - time_css = 'input.start-time.time.ui-timepicker-input' - world.css_fill(date_css, '12/25/2013') - # hit TAB to get to the time field - e = world.css_find(date_css).first - e._element.send_keys(Keys.TAB) - world.css_fill(time_css, '12:00am') - e = world.css_find(time_css).first - e._element.send_keys(Keys.TAB) - time.sleep(float(1)) + set_date_and_time('input.start-date.date.hasDatepicker', '12/25/2013', + 'input.start-time.time.ui-timepicker-input', '12:00am') world.browser.click_link_by_text('Save') diff --git a/cms/djangoapps/contentstore/features/subsection.feature b/cms/djangoapps/contentstore/features/subsection.feature index e913c6a4bf..cc3b2b1cbb 100644 --- a/cms/djangoapps/contentstore/features/subsection.feature +++ b/cms/djangoapps/contentstore/features/subsection.feature @@ -25,6 +25,13 @@ Feature: Create Subsection And I reload the page Then I see it marked as Homework + Scenario: Set a due date in a different year (bug #256) + Given I have opened a new subsection in Studio + And I have set a release date and due date in different years + Then I see the correct dates + And I reload the page + Then I see the correct dates + @skip-phantom Scenario: Delete a subsection Given I have opened a new course section in Studio @@ -33,3 +40,5 @@ Feature: Create Subsection When I press the "subsection" delete icon And I confirm the alert Then the subsection does not exist + + diff --git a/cms/djangoapps/contentstore/features/subsection.py b/cms/djangoapps/contentstore/features/subsection.py index 4ab27fcb49..1ec43e6971 100644 --- a/cms/djangoapps/contentstore/features/subsection.py +++ b/cms/djangoapps/contentstore/features/subsection.py @@ -16,6 +16,18 @@ def i_have_opened_a_new_course_section(step): add_section() +@step('I have added a new subsection$') +def i_have_added_a_new_subsection(step): + add_subsection() + + +@step('I have opened a new subsection in Studio$') +def i_have_opened_a_new_subsection(step): + step.given('I have opened a new course section in Studio') + step.given('I have added a new subsection') + world.css_click('span.subsection-name-value') + + @step('I click the New Subsection link') def i_click_the_new_subsection_link(step): world.css_click('a.new-subsection-item') @@ -43,9 +55,20 @@ def i_see_complete_subsection_name_with_quote_in_editor(step): assert_equal(world.css_find(css).value, 'Subsection With "Quote"') -@step('I have added a new subsection$') -def i_have_added_a_new_subsection(step): - add_subsection() +@step('I have set a release date and due date in different years$') +def test_have_set_dates_in_different_years(step): + set_date_and_time('input#start_date', '12/25/2011', 'input#start_time', '3:00am') + world.css_click('.set-date') + # Use a year in the past so that current year will always be different. + set_date_and_time('input#due_date', '01/02/2012', 'input#due_time', '4:00am') + + +@step('I see the correct dates$') +def i_see_the_correct_dates(step): + assert_equal('12/25/2011', world.css_find('input#start_date').first.value) + assert_equal('3:00am', world.css_find('input#start_time').first.value) + assert_equal('01/02/2012', world.css_find('input#due_date').first.value) + assert_equal('4:00am', world.css_find('input#due_time').first.value) @step('I mark it as Homework$') diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index d38918d6b0..83a2bde72d 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -151,10 +151,6 @@ def compute_unit_state(unit): return UnitState.public -def get_date_display(date): - return date.strftime("%d %B, %Y at %I:%M %p") - - def update_item(location, value): """ If value is None, delete the db entry. Otherwise, update it using the correct modulestore. diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py index e0d843bb4c..8850f230eb 100644 --- a/cms/djangoapps/contentstore/views.py +++ b/cms/djangoapps/contentstore/views.py @@ -6,7 +6,6 @@ import sys import time import tarfile import shutil -from datetime import datetime from collections import defaultdict from uuid import uuid4 from path import path @@ -42,17 +41,18 @@ from xmodule.modulestore.mongo import MongoUsage from mitxmako.shortcuts import render_to_response, render_to_string from xmodule.modulestore.django import modulestore from xmodule_modifiers import replace_static_urls, wrap_xmodule -from xmodule.exceptions import NotFoundError +from xmodule.exceptions import NotFoundError, ProcessingError from functools import partial from xmodule.contentstore.django import contentstore from xmodule.contentstore.content import StaticContent +from xmodule.util.date_utils import get_default_time_display from auth.authz import is_user_in_course_group_role, get_users_in_course_group_by_role from auth.authz import get_user_by_email, add_user_to_course_group, remove_user_from_course_group from auth.authz import INSTRUCTOR_ROLE_NAME, STAFF_ROLE_NAME, create_all_course_groups from .utils import get_course_location_for_item, get_lms_link_for_item, compute_unit_state, \ - get_date_display, UnitState, get_course_for_item, get_url_reverse, add_open_ended_panel_tab, \ + UnitState, get_course_for_item, get_url_reverse, add_open_ended_panel_tab, \ remove_open_ended_panel_tab from xmodule.modulestore.xml_importer import import_from_xml @@ -365,7 +365,7 @@ def edit_unit(request, location): 'draft_preview_link': preview_lms_link, 'published_preview_link': lms_link, 'subsection': containing_subsection, - 'release_date': get_date_display(datetime.fromtimestamp(time.mktime(containing_subsection.lms.start))) if containing_subsection.lms.start is not None else None, + 'release_date': get_default_time_display(containing_subsection.lms.start) if containing_subsection.lms.start is not None else None, 'section': containing_section, 'create_new_unit_template': Location('i4x', 'edx', 'templates', 'vertical', 'Empty'), 'unit_state': unit_state, @@ -439,9 +439,16 @@ def preview_dispatch(request, preview_id, location, dispatch=None): # Let the module handle the AJAX try: ajax_return = instance.handle_ajax(dispatch, request.POST) + except NotFoundError: log.exception("Module indicating to user that request doesn't exist") raise Http404 + + except ProcessingError: + log.warning("Module raised an error while processing AJAX request", + exc_info=True) + return HttpResponseBadRequest() + except: log.exception("error processing ajax call") raise @@ -821,7 +828,7 @@ def upload_asset(request, org, course, coursename): readback = contentstore().find(content.location) response_payload = {'displayname': content.name, - 'uploadDate': get_date_display(readback.last_modified_at), + 'uploadDate': get_default_time_display(readback.last_modified_at.timetuple()), 'url': StaticContent.get_url_path_from_location(content.location), 'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None, 'msg': 'Upload completed' @@ -1426,7 +1433,7 @@ def asset_index(request, org, course, name): id = asset['_id'] display_info = {} display_info['displayname'] = asset['displayname'] - display_info['uploadDate'] = get_date_display(asset['uploadDate']) + display_info['uploadDate'] = get_default_time_display(asset['uploadDate'].timetuple()) asset_location = StaticContent.compute_location(id['org'], id['course'], id['name']) display_info['url'] = StaticContent.get_url_path_from_location(asset_location) diff --git a/cms/envs/common.py b/cms/envs/common.py index c348753632..a56e56025f 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -35,6 +35,7 @@ MITX_FEATURES = { 'AUTH_USE_MIT_CERTIFICATES': False, 'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests 'STAFF_EMAIL': '', # email address for staff (eg to request course creation) + 'STUDIO_NPS_SURVEY': True, } ENABLE_JASMINE = False diff --git a/cms/envs/dev.py b/cms/envs/dev.py index b8d4d14b9e..ae78b93f06 100644 --- a/cms/envs/dev.py +++ b/cms/envs/dev.py @@ -112,6 +112,10 @@ CACHE_TIMEOUT = 0 # Dummy secret key for dev SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' +################################ PIPELINE ################################# + +PIPELINE_SASS_ARGUMENTS = '--debug-info --require {proj_dir}/static/sass/bourbon/lib/bourbon.rb'.format(proj_dir=PROJECT_ROOT) + ################################ DEBUG TOOLBAR ################################# INSTALLED_APPS += ('debug_toolbar', 'debug_toolbar_mongo') MIDDLEWARE_CLASSES += ('django_comment_client.utils.QueryCountDebugMiddleware', @@ -143,3 +147,6 @@ DEBUG_TOOLBAR_CONFIG = { # To see stacktraces for MongoDB queries, set this to True. # Stacktraces slow down page loads drastically (for pages with lots of queries). DEBUG_TOOLBAR_MONGO_STACKTRACES = True + +# disable NPS survey in dev mode +MITX_FEATURES['STUDIO_NPS_SURVEY'] = False diff --git a/cms/static/js/base.js b/cms/static/js/base.js index 7466233331..6ea918cc36 100644 --- a/cms/static/js/base.js +++ b/cms/static/js/base.js @@ -4,6 +4,9 @@ var $modalCover; var $newComponentItem; var $changedInput; var $spinner; +var $newComponentTypePicker; +var $newComponentTemplatePickers; +var $newComponentButton; $(document).ready(function () { $body = $('body'); @@ -83,6 +86,8 @@ $(document).ready(function () { // general link management - smooth scrolling page links $('a[rel*="view"][href^="#"]').bind('click', smoothScrollLink); + // tender feedback window scrolling + $('a.show-tender').bind('click', smoothScrollTop); // toggling overview section details $(function () { @@ -160,6 +165,18 @@ function smoothScrollLink(e) { }); } +function smoothScrollTop(e) { + (e).preventDefault(); + + $.smoothScroll({ + offset: -200, + easing: 'swing', + speed: 1000, + scrollElement: null, + scrollTarget: $('#view-top') + }); +} + function linkNewWindow(e) { window.open($(e.target).attr('href')); e.preventDefault(); @@ -228,7 +245,7 @@ function syncReleaseDate(e) { $("#start_time").val(""); } -function getEdxTimeFromDateTimeVals(date_val, time_val, format) { +function getEdxTimeFromDateTimeVals(date_val, time_val) { var edxTimeStr = null; if (date_val != '') { @@ -237,20 +254,17 @@ function getEdxTimeFromDateTimeVals(date_val, time_val, format) { // Note, we are using date.js utility which has better parsing abilities than the built in JS date parsing var date = Date.parse(date_val + " " + time_val); - if (format == null) - format = 'yyyy-MM-ddTHH:mm'; - - edxTimeStr = date.toString(format); + edxTimeStr = date.toString('yyyy-MM-ddTHH:mm'); } return edxTimeStr; } -function getEdxTimeFromDateTimeInputs(date_id, time_id, format) { +function getEdxTimeFromDateTimeInputs(date_id, time_id) { var input_date = $('#' + date_id).val(); var input_time = $('#' + time_id).val(); - return getEdxTimeFromDateTimeVals(input_date, input_time, format); + return getEdxTimeFromDateTimeVals(input_date, input_time); } function autosaveInput(e) { @@ -291,10 +305,8 @@ function saveSubsection() { } // Piece back together the date/time UI elements into one date/time string - // NOTE: our various "date/time" metadata elements don't always utilize the same formatting string - // so make sure we're passing back the correct format metadata['start'] = getEdxTimeFromDateTimeInputs('start_date', 'start_time'); - metadata['due'] = getEdxTimeFromDateTimeInputs('due_date', 'due_time', 'MMMM dd HH:mm'); + metadata['due'] = getEdxTimeFromDateTimeInputs('due_date', 'due_time'); $.ajax({ url: "/save_item", @@ -316,8 +328,8 @@ function saveSubsection() { function createNewUnit(e) { e.preventDefault(); - parent = $(this).data('parent'); - template = $(this).data('template'); + var parent = $(this).data('parent'); + var template = $(this).data('template'); $.post('/clone_item', {'parent_location': parent, diff --git a/cms/static/sass/_base.scss b/cms/static/sass/_base.scss index cadb442b7c..5a9ac2f280 100644 --- a/cms/static/sass/_base.scss +++ b/cms/static/sass/_base.scss @@ -644,7 +644,7 @@ hr.divide { position: absolute; top: 0; left: 0; - z-index: 99999; + z-index: 10000; padding: 0 10px; border-radius: 3px; background: rgba(0, 0, 0, 0.85); diff --git a/cms/static/sass/_variables.scss b/cms/static/sass/_variables.scss index 29ebf69271..3bac14fdf4 100644 --- a/cms/static/sass/_variables.scss +++ b/cms/static/sass/_variables.scss @@ -22,6 +22,7 @@ $black-t0: rgba(0,0,0,0.125); $black-t1: rgba(0,0,0,0.25); $black-t2: rgba(0,0,0,0.50); $black-t3: rgba(0,0,0,0.75); + $white: rgb(255,255,255); $white-t0: rgba(255,255,255,0.125); $white-t1: rgba(255,255,255,0.25); diff --git a/cms/static/sass/base-style.scss b/cms/static/sass/base-style.scss index 6a1f1bb252..b9becc4829 100644 --- a/cms/static/sass/base-style.scss +++ b/cms/static/sass/base-style.scss @@ -27,7 +27,8 @@ @import 'elements/forms'; @import 'elements/modal'; @import 'elements/alerts'; -@import 'elements/jquery-ui-calendar'; +@import 'elements/vendor'; +@import 'elements/tender-widget'; // specific views @import 'views/account'; diff --git a/cms/static/sass/elements/_header.scss b/cms/static/sass/elements/_header.scss index e8df37f57f..b7fb381f2e 100644 --- a/cms/static/sass/elements/_header.scss +++ b/cms/static/sass/elements/_header.scss @@ -132,7 +132,7 @@ // specific elements - course nav .nav-course { - width: 335px; + width: 285px; margin-top: -($baseline/4); @include font-size(14); diff --git a/cms/static/sass/elements/_tender-widget.scss b/cms/static/sass/elements/_tender-widget.scss new file mode 100644 index 0000000000..b4113732f0 --- /dev/null +++ b/cms/static/sass/elements/_tender-widget.scss @@ -0,0 +1,267 @@ +// tender help/support widget +// ==================== + +#tender_frame, #tender_window { + background-image: none !important; + background: none; +} + +#tender_window { + @include border-radius(3px); + @include box-shadow(0 2px 3px $shadow); + height: ($baseline*35) !important; + background: $white !important; + border: 1px solid $gray; +} + +#tender_window { + padding: 0 !important; +} + +#tender_frame { + background: $white; +} + +#tender_closer { + color: $blue-l2 !important; + text-transform: uppercase; + + &:hover { + color: $blue-l4 !important; + } +} + +// ==================== + +// tender style overrides - not rendered through here, but an archive is needed +#tender_frame iframe html { + font-size: 62.5%; +} + +.widget-layout { + font-family: 'Open Sans', sans-serif; +} + +.widget-layout .search, +.widget-layout .tabs, +.widget-layout .footer, +.widget-layout .header h1 a { + display: none; +} + +.widget-layout .header { + background: rgb(85, 151, 221); + padding: 10px 20px; +} + +.widget-layout h1, .widget-layout h2, .widget-layout h3, .widget-layout h4, .widget-layout h5, .widget-layout h6, .widget-layout label { + font-weight: 600; +} + +.widget-layout .header h1 { + font-size: 22px; +} + +.widget-layout .content { + overflow: auto; + height: auto !important; + padding: 20px; +} + +.widget-layout .flash { + margin: -10px 0 15px 0; + padding: 10px 20px !important; + background-image: none !important; +} + +.widget-layout .flash-error { + background: rgb(178, 6, 16) !important; + color: rgb(255,255,255) !important; +} + +.widget-layout label { + font-size: 14px; + margin-bottom: 5px; + color: #4c4c4c; + font-weight: 500; +} + +.widget-layout input[type="text"], .widget-layout textarea { + padding: 10px; + font-size: 16px; + color: rgb(0,0,0) !important; + border: 1px solid #b0b6c2; + border-radius: 2px; + background-color: #edf1f5; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #edf1f5),color-stop(100%, #fdfdfe)); + background-image: -webkit-linear-gradient(top, #edf1f5,#fdfdfe); + background-image: -moz-linear-gradient(top, #edf1f5,#fdfdfe); + background-image: -ms-linear-gradient(top, #edf1f5,#fdfdfe); + background-image: -o-linear-gradient(top, #edf1f5,#fdfdfe); + background-image: linear-gradient(top, #edf1f5,#fdfdfe); + background-color: #edf1f5; + -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.1) inset; + -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.1) inset; + box-shadow: 0 1px 2px rgba(0,0,0,0.1) inset; +} + +.widget-layout input[type="text"]:focus, .widget-layout textarea:focus { + background-color: #fffcf1; + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fffcf1),color-stop(100%, #fffefd)); + background-image: -webkit-linear-gradient(top, #fffcf1,#fffefd); + background-image: -moz-linear-gradient(top, #fffcf1,#fffefd); + background-image: -ms-linear-gradient(top, #fffcf1,#fffefd); + background-image: -o-linear-gradient(top, #fffcf1,#fffefd); + background-image: linear-gradient(top, #fffcf1,#fffefd); + outline: 0; +} + +.widget-layout textarea { + width: 97%; +} + +.widget-layout p.note { + text-align: right !important; + display: inline-block !important; + position: absolute !important; + right: -130px !important; + top: -5px !important; + font-size: 13px !important; + opacity: 0.80; +} + +.widget-layout .form-actions { + margin: 15px 0; + border: none; + padding: 0; +} + +.widget-layout dl.form { + float: none; + width: 100%; + border-bottom: 1px solid #f2f2f2; + margin-bottom: 10px; + padding-bottom: 10px; +} + +.widget-layout dl.form:last-child { + border: none; + padding-bottom: 0; + margin-bottom: 20px; +} + +.widget-layout dl.form dt, .widget-layout dl.form dd { + display: inline-block; + vertical-align: middle; +} + +.widget-layout dl.form dt { + margin-right: 15px; + width: 70px; +} + +.widget-layout dl.form dd { + width: 65%; + position: relative; +} + +// specific elements +.widget-layout #discussion_body { + +} + +.widget-layout #discussion_body:before { + content: "What Question or Feedback Would You Like to Share?"; + display: block; + font-size: 14px; + margin-bottom: 5px; + color: #4c4c4c; + font-weight: 500; +} + + +.widget-layout dl#brain_buster_captcha { + float: none; + width: 100%; + border-top: 1px solid #f2f2f2; + margin-top: 10px; + padding-top: 10px; +} + +.widget-layout dl#brain_buster_captcha dd { + display: block !important; +} + +.widget-layout dl#brain_buster_captcha #captcha_answer { + border-color: #333; +} + +.widget-layout dl#brain_buster_captcha dd label { + display: block; + font-weight: 700; + margin: 0 15px 5px 0 !important; +} + +.widget-layout dl#brain_buster_captcha dd #captcha_answer { + display: block; + width: 97%%; +} + +.widget-layout .form-actions .btn-post_topic { + display: block; + width: 100%; + height: auto !important; + font-size: 16px; + font-weight: 700; + -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset,0 0 0 rgba(0,0,0,0); + -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset,0 0 0 rgba(0,0,0,0); + box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset,0 0 0 rgba(0,0,0,0); + -webkit-transition-property: background-color,0.15s; + -moz-transition-property: background-color,0.15s; + -ms-transition-property: background-color,0.15s; + -o-transition-property: background-color,0.15s; + transition-property: background-color,0.15s; + -webkit-transition-duration: box-shadow,0.15s; + -moz-transition-duration: box-shadow,0.15s; + -ms-transition-duration: box-shadow,0.15s; + -o-transition-duration: box-shadow,0.15s; + transition-duration: box-shadow,0.15s; + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -ms-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; + -webkit-transition-delay: 0; + -moz-transition-delay: 0; + -ms-transition-delay: 0; + -o-transition-delay: 0; + transition-delay: 0; + border: 1px solid #34854c; + border-radius: 3px; + background-color: rgba(255,255,255,0.3); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(255,255,255,0.3)),color-stop(100%, rgba(255,255,255,0))); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,0.3),rgba(255,255,255,0)); + background-image: -moz-linear-gradient(top, rgba(255,255,255,0.3),rgba(255,255,255,0)); + background-image: -ms-linear-gradient(top, rgba(255,255,255,0.3),rgba(255,255,255,0)); + background-image: -o-linear-gradient(top, rgba(255,255,255,0.3),rgba(255,255,255,0)); + background-image: linear-gradient(top, rgba(255,255,255,0.3),rgba(255,255,255,0)); + background-color: #25b85a; + -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset; + -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset; + box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset; + color: #fff; + text-align: center; + margin-top: 20px; + padding: 10px 20px; +} + +.widget-layout .form-actions #private-discussion-opt { + float: none; + text-align: left; + margin: 0 0 15px 0; +} + +.widget-layout .form-actions .btn-post_topic:hover, .widget-layout .form-actions .btn-post_topic:active { + background-color: #16ca57; + color: #fff; +} \ No newline at end of file diff --git a/cms/static/sass/elements/_jquery-ui-calendar.scss b/cms/static/sass/elements/_vendor.scss similarity index 85% rename from cms/static/sass/elements/_jquery-ui-calendar.scss rename to cms/static/sass/elements/_vendor.scss index 3d20bde642..b106f322ab 100644 --- a/cms/static/sass/elements/_jquery-ui-calendar.scss +++ b/cms/static/sass/elements/_vendor.scss @@ -1,6 +1,7 @@ -// studio - elements - JQUI calendar +// studio - elements - vendor overrides // ==================== +// JQUI calendar .ui-datepicker { border-color: $darkGrey; border-radius: 2px; @@ -8,6 +9,7 @@ font-family: $sans-serif; font-size: 12px; @include box-shadow(0 5px 10px rgba(0, 0, 0, 0.1)); + z-index: 100000 !important; .ui-widget-header { background: $darkGrey; @@ -53,4 +55,11 @@ border-color: $orange; color: #fff; } +} + +// ==================== + +// JQUI timepicker +.ui-timepicker-list { + z-index: 100000 !important; } \ No newline at end of file diff --git a/cms/static/sass/views/_outline.scss b/cms/static/sass/views/_outline.scss index 0d72e2d2bf..6a141fa789 100644 --- a/cms/static/sass/views/_outline.scss +++ b/cms/static/sass/views/_outline.scss @@ -26,7 +26,7 @@ body.course.outline { position: relative; top: -4px; right: 50px; - width: 145px; + width: 100px; .status-label { position: absolute; @@ -62,7 +62,7 @@ body.course.outline { opacity: 0.0; position: absolute; top: -1px; - left: 5px; + right: 0; margin: 0; padding: 8px 12px; background: $white; @@ -160,7 +160,7 @@ body.course.outline { .section-published-date { position: absolute; top: 19px; - right: 90px; + right: 80px; padding: 4px 10px; border-radius: 3px; background: $lightGrey; @@ -271,8 +271,6 @@ body.course.outline { .section-published-date { float: right; - width: 265px; - margin-right: 220px; @include border-radius(3px); background: $lightGrey; diff --git a/cms/templates/base.html b/cms/templates/base.html index e852b5d7fe..15f4c556bb 100644 --- a/cms/templates/base.html +++ b/cms/templates/base.html @@ -55,9 +55,11 @@ <%block name="content"> <%include file="widgets/footer.html" /> - + <%include file="widgets/tender.html" /> <%block name="jsextra"> + + <%include file="widgets/qualaroo.html" /> diff --git a/cms/templates/edit_subsection.html b/cms/templates/edit_subsection.html index eb5a9a9824..80385de829 100644 --- a/cms/templates/edit_subsection.html +++ b/cms/templates/edit_subsection.html @@ -1,9 +1,7 @@ <%inherit file="base.html" /> <%! - from time import mktime - import dateutil.parser import logging - from datetime import datetime + from xmodule.util.date_utils import get_time_struct_display %> <%! from django.core.urlresolvers import reverse %> @@ -13,7 +11,6 @@ <%namespace name="units" file="widgets/units.html" /> <%namespace name='static' file='static_content.html'/> -<%namespace name='datetime' module='datetime'/> <%block name="content">
@@ -38,18 +35,15 @@
- <% - start_date = datetime.fromtimestamp(mktime(subsection.lms.start)) if subsection.lms.start is not None else None - parent_start_date = datetime.fromtimestamp(mktime(parent_item.lms.start)) if parent_item.lms.start is not None else None - %> - - + +
% if subsection.lms.start != parent_item.lms.start and subsection.lms.start: - % if parent_start_date is None: + % if parent_item.lms.start is None:

The date above differs from the release date of ${parent_item.display_name_with_default}, which is unset. % else: -

The date above differs from the release date of ${parent_item.display_name_with_default} – ${parent_start_date.strftime('%m/%d/%Y')} at ${parent_start_date.strftime('%H:%M')}. +

The date above differs from the release date of ${parent_item.display_name_with_default} – + ${get_time_struct_display(parent_item.lms.start, '%m/%d/%Y at %I:%M %p')}. % endif Sync to ${parent_item.display_name_with_default}.

% endif @@ -66,12 +60,8 @@ Set a due date

- <% - # due date uses it own formatting for stringifying the date. As with capa_module.py, there's a utility module available for us to use - due_date = dateutil.parser.parse(subsection.lms.due) if subsection.lms.due else None - %> - - + + Remove due date

diff --git a/cms/templates/index.html b/cms/templates/index.html index 6a59ac8b86..8b14ea179a 100644 --- a/cms/templates/index.html +++ b/cms/templates/index.html @@ -69,7 +69,7 @@
% if user.is_active:
    - %for course, url, lms_link in courses: + %for course, url, lms_link in sorted(courses, key=lambda s: s[0].lower()):
  • ${course} diff --git a/cms/templates/overview.html b/cms/templates/overview.html index d45a90093e..04aae12f4a 100644 --- a/cms/templates/overview.html +++ b/cms/templates/overview.html @@ -1,9 +1,7 @@ <%inherit file="base.html" /> <%! - from time import mktime - import dateutil.parser import logging - from datetime import datetime + from xmodule.util.date_utils import get_time_struct_display %> <%! from django.core.urlresolvers import reverse %> <%block name="title">Course Outline @@ -163,11 +161,10 @@
  • --> + - - % if user.is_authenticated(): - + % endif diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html index d601b940f5..167d5417d7 100644 --- a/cms/templates/widgets/header.html +++ b/cms/templates/widgets/header.html @@ -1,6 +1,6 @@ <%! from django.core.urlresolvers import reverse %> -
    +