Merge remote-tracking branch 'edx-mitx/master' into feature/ichuang/staff-email-for-course-creation
Conflicts: cms/envs/common.py
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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$')
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
|
||||
// specific elements - course nav
|
||||
.nav-course {
|
||||
width: 335px;
|
||||
width: 285px;
|
||||
margin-top: -($baseline/4);
|
||||
@include font-size(14);
|
||||
|
||||
|
||||
267
cms/static/sass/elements/_tender-widget.scss
Normal file
267
cms/static/sass/elements/_tender-widget.scss
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -55,9 +55,11 @@
|
||||
|
||||
<%block name="content"></%block>
|
||||
<%include file="widgets/footer.html" />
|
||||
|
||||
<%include file="widgets/tender.html" />
|
||||
<%block name="jsextra"></%block>
|
||||
</body>
|
||||
|
||||
<%include file="widgets/qualaroo.html" />
|
||||
</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">
|
||||
<div class="main-wrapper">
|
||||
@@ -38,18 +35,15 @@
|
||||
<div class="scheduled-date-input row">
|
||||
<label>Release date:<!-- <span class="description">Determines when this subsection and the units within it will be released publicly.</span>--></label>
|
||||
<div class="datepair" data-language="javascript">
|
||||
<%
|
||||
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
|
||||
%>
|
||||
<input type="text" id="start_date" name="start_date" value="${start_date.strftime('%m/%d/%Y') if start_date is not None else ''}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
|
||||
<input type="text" id="start_time" name="start_time" value="${start_date.strftime('%H:%M') if start_date is not None else ''}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
|
||||
<input type="text" id="start_date" name="start_date" value="${get_time_struct_display(subsection.lms.start, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
|
||||
<input type="text" id="start_time" name="start_time" value="${get_time_struct_display(subsection.lms.start, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
|
||||
</div>
|
||||
% 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:
|
||||
<p class="notice">The date above differs from the release date of ${parent_item.display_name_with_default}, which is unset.
|
||||
% else:
|
||||
<p class="notice">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')}.
|
||||
<p class="notice">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
|
||||
<a href="#" class="sync-date no-spinner">Sync to ${parent_item.display_name_with_default}.</a></p>
|
||||
% endif
|
||||
@@ -66,12 +60,8 @@
|
||||
<a href="#" class="set-date">Set a due date</a>
|
||||
<div class="datepair date-setter">
|
||||
<p class="date-description">
|
||||
<%
|
||||
# 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
|
||||
%>
|
||||
<input type="text" id="due_date" name="due_date" value="${due_date.strftime('%m/%d/%Y') if due_date is not None else ''}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
|
||||
<input type="text" id="due_time" name="due_time" value="${due_date.strftime('%H:%M') if due_date is not None else ''}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
|
||||
<input type="text" id="due_date" name="due_date" value="${get_time_struct_display(subsection.lms.due, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
|
||||
<input type="text" id="due_time" name="due_time" value="${get_time_struct_display(subsection.lms.due, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
|
||||
<a href="#" class="remove-date">Remove due date</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<article class="my-classes">
|
||||
% if user.is_active:
|
||||
<ul class="class-list">
|
||||
%for course, url, lms_link in courses:
|
||||
%for course, url, lms_link in sorted(courses, key=lambda s: s[0].lower()):
|
||||
<li>
|
||||
<a class="class-link" href="${url}" class="class-name">
|
||||
<span class="class-name">${course}</span>
|
||||
|
||||
@@ -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</%block>
|
||||
@@ -163,11 +161,10 @@
|
||||
</h3>
|
||||
<div class="section-published-date">
|
||||
<%
|
||||
start_date = datetime.fromtimestamp(mktime(section.lms.start)) if section.lms.start is not None else None
|
||||
start_date_str = start_date.strftime('%m/%d/%Y') if start_date is not None else ''
|
||||
start_time_str = start_date.strftime('%H:%M') if start_date is not None else ''
|
||||
start_date_str = get_time_struct_display(section.lms.start, '%m/%d/%Y')
|
||||
start_time_str = get_time_struct_display(section.lms.start, '%I:%M %p')
|
||||
%>
|
||||
%if start_date is None:
|
||||
%if section.lms.start is None:
|
||||
<span class="published-status">This section has not been released.</span>
|
||||
<a href="#" class="schedule-button" data-date="" data-time="" data-id="${section.location}">Schedule</a>
|
||||
%else:
|
||||
|
||||
@@ -14,15 +14,14 @@
|
||||
<li class="nav-item nav-peripheral-pp">
|
||||
<a href="#">Privacy Policy</a>
|
||||
</li> -->
|
||||
|
||||
<li class="nav-item nav-peripheral-help">
|
||||
<a href="http://help.edge.edx.org/" rel="external">edX Studio Help</a>
|
||||
</li>
|
||||
<li class="nav-item nav-peripheral-contact">
|
||||
<a href="https://www.edx.org/contact" rel="external">Contact edX</a>
|
||||
</li>
|
||||
|
||||
% if user.is_authenticated():
|
||||
<!-- add in zendesk/tender feedback form UI -->
|
||||
<li class="nav-item nav-peripheral-feedback">
|
||||
<a class="show-tender" href="http://help.edge.edx.org/discussion/new" title="Use our feedback tool, Tender, to share your feedback">Contact Us</a>
|
||||
</li>
|
||||
% endif
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
|
||||
<div class="wrapper-header wrapper">
|
||||
<div class="wrapper-header wrapper" id="view-top">
|
||||
<header class="primary" role="banner">
|
||||
|
||||
<div class="wrapper wrapper-left ">
|
||||
|
||||
13
cms/templates/widgets/qualaroo.html
Normal file
13
cms/templates/widgets/qualaroo.html
Normal file
@@ -0,0 +1,13 @@
|
||||
% if settings.MITX_FEATURES.get('STUDIO_NPS_SURVEY'):
|
||||
<!-- Qualaroo is used for net promoter score surveys -->
|
||||
<script type="text/javascript">
|
||||
% if user.is_authenticated():
|
||||
var _kiq = _kiq || [];
|
||||
_kiq.push(['identify', "${ user.email }" ]);
|
||||
% endif
|
||||
</script>
|
||||
|
||||
<!-- Qualaroo for edx.org -->
|
||||
<script type="text/javascript" src="//s3.amazonaws.com/ki.js/48221/9SN.js" async="true"></script>
|
||||
<!-- end Qualaroo -->
|
||||
% endif
|
||||
13
cms/templates/widgets/tender.html
Normal file
13
cms/templates/widgets/tender.html
Normal file
@@ -0,0 +1,13 @@
|
||||
% if user.is_authenticated():
|
||||
|
||||
<script type="text/javascript">
|
||||
Tender = {
|
||||
hideToggle: true,
|
||||
title: '',
|
||||
body: '',
|
||||
hide_kb: 'true',
|
||||
widgetToggles: $('.show-tender')
|
||||
}
|
||||
</script>
|
||||
<script src="https://edxedge.tenderapp.com/tender_widget.js" type="text/javascript"></script>
|
||||
% endif
|
||||
Reference in New Issue
Block a user