Commit cd7211b6 by Calen Pennington

Merge remote-tracking branch 'origin/master' into cpennington/cms-xml-processing

Conflicts:
	cms/envs/common.py
parents 6ebcfb63 24c1060b
...@@ -157,8 +157,8 @@ PIPELINE_CSS = { ...@@ -157,8 +157,8 @@ PIPELINE_CSS = {
PIPELINE_ALWAYS_RECOMPILE = ['sass/base-style.scss'] PIPELINE_ALWAYS_RECOMPILE = ['sass/base-style.scss']
from x_module import XModuleDescriptor from xmodule.x_module import XModuleDescriptor
from raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module" js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module"
try: try:
os.makedirs(js_file_dir) os.makedirs(js_file_dir)
......
<section id="textinput_${id}" class="textinput"> <section id="textinput_${id}" class="textinput">
% if state == 'unsubmitted':
<div class="unanswered" id="status_${id}">
% elif state == 'correct':
<div class="correct" id="status_${id}">
% elif state == 'incorrect':
<div class="incorrect" id="status_${id}">
% elif state == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif
<input type="text" name="input_${id}" id="input_${id}" value="${value}" <input type="text" name="input_${id}" id="input_${id}" value="${value}"
% if size: % if size:
size="${size}" size="${size}"
% endif % endif
/> />
<span id="answer_${id}"></span> <p class="status">
% if state == 'unsubmitted':
unanswered
% elif state == 'correct':
correct
% elif state == 'incorrect':
incorrect
% elif state == 'incomplete':
incomplete
% endif
</p>
<p id="answer_${id}" class="answer"></p>
% if state == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span>
% elif state == 'correct':
<span class="correct" id="status_${id}"></span>
% elif state == 'incorrect':
<span class="incorrect" id="status_${id}"></span>
% elif state == 'incomplete':
<span class="incorrect" id="status_${id}"></span>
% endif
% if msg: % if msg:
<span class="message">${msg|n}</span> <span class="message">${msg|n}</span>
% endif % endif
</div>
</section> </section>
...@@ -2,34 +2,36 @@ ...@@ -2,34 +2,36 @@
### version of textline.html which does dynammic math ### version of textline.html which does dynammic math
### ###
<section class="text-input-dynamath"> <section class="text-input-dynamath">
<table style="display:inline; vertical-align:middle;"> % if state == 'unsubmitted':
<tr> <div class="unanswered" id="status_${id}">
<td> % elif state == 'correct':
<input type="text" name="input_${id}" id="input_${id}" value="${value}" class="math" size="${size if size else ''}" /> <div class="correct" id="status_${id}">
</td> % elif state == 'incorrect':
<td> <div class="incorrect" id="status_${id}">
<span id="answer_${id}"></span> % elif state == 'incomplete':
<div class="incorrect" id="status_${id}">
% endif
<input type="text" name="input_${id}" id="input_${id}" value="${value}" class="math" size="${size if size else ''}" />
<p class="status">
% if state == 'unsubmitted': % if state == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span> unanswered
% elif state == 'correct': % elif state == 'correct':
<span class="correct" id="status_${id}"></span> correct
% elif state == 'incorrect': % elif state == 'incorrect':
<span class="incorrect" id="status_${id}"></span> incorrect
% elif state == 'incomplete': % elif state == 'incomplete':
<span class="incorrect" id="status_${id}"></span> incomplete
% endif % endif
</td> </p>
</tr>
<tr> <p id="answer_${id}" class="answer"></p>
<td>
<span id="display_${id}">`{::}`</span> <div id="display_${id}" class="equation">`{::}`</div>
</td>
<td> </div>
<textarea style="display:none" id="input_${id}_dynamath" name="input_${id}_dynamath"> </textarea> <textarea style="display:none" id="input_${id}_dynamath" name="input_${id}_dynamath"> </textarea>
</td>
</tr>
</table>
% if msg: % if msg:
<span class="message">${msg|n}</span> <span class="message">${msg|n}</span>
% endif % endif
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
import logging import logging
log = logging.getLogger("mitx.common.lib.mitxmako") log = logging.getLogger("mitx." + __name__)
from django.template import Context from django.template import Context
from django.http import HttpResponse from django.http import HttpResponse
......
...@@ -223,7 +223,7 @@ def get_module(tree, module, id_tag, module_id, sections_dirname, options): ...@@ -223,7 +223,7 @@ def get_module(tree, module, id_tag, module_id, sections_dirname, options):
result_set = tree.xpath(xpath_search) result_set = tree.xpath(xpath_search)
if len(result_set) < 1: if len(result_set) < 1:
# Not found in main tree. Let's look in the section files. # Not found in main tree. Let's look in the section files.
section_list = (s[:-4] for s in os.listdir(sections_dirname) if s[-4:]=='.xml') section_list = (s[:-4] for s in os.listdir(sections_dirname) if s.endswith('.xml'))
for section in section_list: for section in section_list:
try: try:
s = get_section(section, options, sections_dirname) s = get_section(section, options, sections_dirname)
......
...@@ -176,11 +176,13 @@ def get_score(user, problem, cache, coursename=None): ...@@ -176,11 +176,13 @@ def get_score(user, problem, cache, coursename=None):
## HACK 2: Backwards-compatibility: This should be written when a grade is saved, and removed from the system ## HACK 2: Backwards-compatibility: This should be written when a grade is saved, and removed from the system
# TODO: These are no longer correct params for I4xSystem -- figure out what this code # TODO: These are no longer correct params for I4xSystem -- figure out what this code
# does, clean it up. # does, clean it up.
from module_render import I4xSystem # from module_render import I4xSystem
system = I4xSystem(None, None, None, coursename=coursename) # system = I4xSystem(None, None, None, coursename=coursename)
total=float(xmodule.capa_module.Module(system, etree.tostring(problem), "id").max_score()) # total=float(xmodule.capa_module.Module(system, etree.tostring(problem), "id").max_score())
response.max_grade = total # response.max_grade = total
response.save() # response.save()
total = 1
# For a temporary fix, we just assume a problem is worth 1 point if we haven't seen it before. This is totally incorrect
#Now we re-weight the problem, if specified #Now we re-weight the problem, if specified
weight = problem.get("weight", None) weight = problem.get("weight", None)
......
...@@ -15,7 +15,7 @@ middleware.MakoMiddleware() ...@@ -15,7 +15,7 @@ middleware.MakoMiddleware()
def check_names(user, course): def check_names(user, course):
''' '''
Complain if any problems have alphanumeric names. Complain if any problems have non alphanumeric names.
TODO (vshnayder): there are some in 6.002x that don't. Is that actually a problem? TODO (vshnayder): there are some in 6.002x that don't. Is that actually a problem?
''' '''
all_ok = True all_ok = True
......
...@@ -20,10 +20,12 @@ jasmine.stubRequests = -> ...@@ -20,10 +20,12 @@ jasmine.stubRequests = ->
settings.success data: jasmine.stubbedMetadata[match[1]] settings.success data: jasmine.stubbedMetadata[match[1]]
else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/ else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/
settings.success jasmine.stubbedCaption settings.success jasmine.stubbedCaption
else if settings.url.match /modx\/problem\/.+\/problem_get$/
settings.success html: readFixtures('problem_content.html')
else if settings.url == '/calculate' || else if settings.url == '/calculate' ||
settings.url == '/6002x/modx/sequence/1/goto_position' || settings.url == '/6002x/modx/sequence/1/goto_position' ||
settings.url.match(/event$/) || settings.url.match(/event$/) ||
settings.url.match(/6002x\/modx\/problem\/.+\/problem_(check|reset|show|save)$/) settings.url.match(/modx\/problem\/.+\/problem_(check|reset|show|save)$/)
# do nothing # do nothing
else else
throw "External request attempted for #{settings.url}, which is not defined." throw "External request attempted for #{settings.url}, which is not defined."
......
...@@ -13,6 +13,7 @@ describe 'Problem', -> ...@@ -13,6 +13,7 @@ describe 'Problem', ->
spyOn($.fn, 'load').andCallFake (url, callback) -> spyOn($.fn, 'load').andCallFake (url, callback) ->
$(@).html readFixtures('problem_content.html') $(@).html readFixtures('problem_content.html')
callback() callback()
jasmine.stubRequests()
describe 'constructor', -> describe 'constructor', ->
beforeEach -> beforeEach ->
...@@ -21,12 +22,6 @@ describe 'Problem', -> ...@@ -21,12 +22,6 @@ describe 'Problem', ->
it 'set the element', -> it 'set the element', ->
expect(@problem.element).toBe '#problem_1' expect(@problem.element).toBe '#problem_1'
it 'set the content url', ->
expect(@problem.content_url).toEqual '/problem/url/problem_get?id=1'
it 'render the content', ->
expect($.fn.load).toHaveBeenCalledWith @problem.content_url, @problem.bind
describe 'bind', -> describe 'bind', ->
beforeEach -> beforeEach ->
spyOn window, 'update_schematics' spyOn window, 'update_schematics'
...@@ -57,8 +52,11 @@ describe 'Problem', -> ...@@ -57,8 +52,11 @@ describe 'Problem', ->
it 'bind the math input', -> it 'bind the math input', ->
expect($('input.math')).toHandleWith 'keyup', @problem.refreshMath expect($('input.math')).toHandleWith 'keyup', @problem.refreshMath
it 'display the math input', -> it 'replace math content on the page', ->
expect(@stubbedJax.root.toMathML).toHaveBeenCalled() expect(MathJax.Hub.Queue.mostRecentCall.args).toEqual [
['Text', @stubbedJax, ''],
[@problem.updateMathML, @stubbedJax, $('#input_example_1').get(0)]
]
describe 'render', -> describe 'render', ->
beforeEach -> beforeEach ->
...@@ -77,12 +75,19 @@ describe 'Problem', -> ...@@ -77,12 +75,19 @@ describe 'Problem', ->
expect(@problem.bind).toHaveBeenCalled() expect(@problem.bind).toHaveBeenCalled()
describe 'with no content given', -> describe 'with no content given', ->
beforeEach ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
callback html: "Hello World"
@problem.render()
it 'load the content via ajax', -> it 'load the content via ajax', ->
expect($.fn.load).toHaveBeenCalledWith @problem.content_url, @bind expect(@problem.element.html()).toEqual 'Hello World'
it 're-bind the content', ->
expect(@problem.bind).toHaveBeenCalled()
describe 'check', -> describe 'check', ->
beforeEach -> beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
@problem.answers = 'foo=1&bar=2' @problem.answers = 'foo=1&bar=2'
...@@ -116,7 +121,6 @@ describe 'Problem', -> ...@@ -116,7 +121,6 @@ describe 'Problem', ->
describe 'reset', -> describe 'reset', ->
beforeEach -> beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
it 'log the problem_reset event', -> it 'log the problem_reset event', ->
...@@ -130,13 +134,13 @@ describe 'Problem', -> ...@@ -130,13 +134,13 @@ describe 'Problem', ->
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_reset', { id: 1 }, jasmine.any(Function) expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_reset', { id: 1 }, jasmine.any(Function)
it 'render the returned content', -> it 'render the returned content', ->
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback("Reset!") spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
callback html: "Reset!"
@problem.reset() @problem.reset()
expect(@problem.element.html()).toEqual 'Reset!' expect(@problem.element.html()).toEqual 'Reset!'
describe 'show', -> describe 'show', ->
beforeEach -> beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
@problem.element.prepend '<div id="answer_1_1" /><div id="answer_1_2" />' @problem.element.prepend '<div id="answer_1_1" /><div id="answer_1_2" />'
...@@ -154,18 +158,19 @@ describe 'Problem', -> ...@@ -154,18 +158,19 @@ describe 'Problem', ->
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_show', jasmine.any(Function) expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_show', jasmine.any(Function)
it 'show the answers', -> it 'show the answers', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback('1_1': 'One', '1_2': 'Two') spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
callback answers: '1_1': 'One', '1_2': 'Two'
@problem.show() @problem.show()
expect($('#answer_1_1')).toHaveHtml 'One' expect($('#answer_1_1')).toHaveHtml 'One'
expect($('#answer_1_2')).toHaveHtml 'Two' expect($('#answer_1_2')).toHaveHtml 'Two'
it 'toggle the show answer button', -> it 'toggle the show answer button', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({}) spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback(answers: {})
@problem.show() @problem.show()
expect($('.show')).toHaveValue 'Hide Answer' expect($('.show')).toHaveValue 'Hide Answer'
it 'add the showed class to element', -> it 'add the showed class to element', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({}) spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback(answers: {})
@problem.show() @problem.show()
expect(@problem.element).toHaveClass 'showed' expect(@problem.element).toHaveClass 'showed'
...@@ -179,7 +184,8 @@ describe 'Problem', -> ...@@ -179,7 +184,8 @@ describe 'Problem', ->
''' '''
it 'set the correct_answer attribute on the choice', -> it 'set the correct_answer attribute on the choice', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback('1_1': [2, 3]) spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
callback answers: '1_1': [2, 3]
@problem.show() @problem.show()
expect($('label[for="input_1_1_1"]')).not.toHaveAttr 'correct_answer', 'true' expect($('label[for="input_1_1_1"]')).not.toHaveAttr 'correct_answer', 'true'
expect($('label[for="input_1_1_2"]')).toHaveAttr 'correct_answer', 'true' expect($('label[for="input_1_1_2"]')).toHaveAttr 'correct_answer', 'true'
...@@ -214,7 +220,6 @@ describe 'Problem', -> ...@@ -214,7 +220,6 @@ describe 'Problem', ->
describe 'save', -> describe 'save', ->
beforeEach -> beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
@problem.answers = 'foo=1&bar=2' @problem.answers = 'foo=1&bar=2'
...@@ -236,23 +241,29 @@ describe 'Problem', -> ...@@ -236,23 +241,29 @@ describe 'Problem', ->
describe 'refreshMath', -> describe 'refreshMath', ->
beforeEach -> beforeEach ->
@problem = new Problem 1, '/problem/url/' @problem = new Problem 1, '/problem/url/'
@stubbedJax.root.toMathML.andReturn '<MathML>'
$('#input_example_1').val 'E=mc^2' $('#input_example_1').val 'E=mc^2'
@problem.refreshMath target: $('#input_example_1').get(0)
it 'should queue the conversion and MathML element update', ->
expect(MathJax.Hub.Queue).toHaveBeenCalledWith ['Text', @stubbedJax, 'E=mc^2'],
[@problem.updateMathML, @stubbedJax, $('#input_example_1').get(0)]
describe 'updateMathML', ->
beforeEach ->
@problem = new Problem 1, '/problem/url/'
@stubbedJax.root.toMathML.andReturn '<MathML>'
describe 'when there is no exception', -> describe 'when there is no exception', ->
beforeEach -> beforeEach ->
@problem.refreshMath target: $('#input_example_1').get(0) @problem.updateMathML @stubbedJax, $('#input_example_1').get(0)
it 'should convert and display the MathML object', ->
expect(MathJax.Hub.Queue).toHaveBeenCalledWith ['Text', @stubbedJax, 'E=mc^2']
it 'should display debug output in hidden div', -> it 'convert jax to MathML', ->
expect($('#input_example_1_dynamath')).toHaveValue '<MathML>' expect($('#input_example_1_dynamath')).toHaveValue '<MathML>'
describe 'when there is an exception', -> describe 'when there is an exception', ->
beforeEach -> beforeEach ->
@stubbedJax.root.toMathML.andThrow {restart: true} @stubbedJax.root.toMathML.andThrow {restart: true}
@problem.refreshMath target: $('#input_example_1').get(0) @problem.updateMathML @stubbedJax, $('#input_example_1').get(0)
it 'should queue up the exception', -> it 'should queue up the exception', ->
expect(MathJax.Callback.After).toHaveBeenCalledWith [@problem.refreshMath, @stubbedJax], true expect(MathJax.Callback.After).toHaveBeenCalledWith [@problem.refreshMath, @stubbedJax], true
......
...@@ -35,6 +35,9 @@ describe 'VideoCaption', -> ...@@ -35,6 +35,9 @@ describe 'VideoCaption', ->
it 'bind player resize event', -> it 'bind player resize event', ->
expect($(@player)).toHandleWith 'resize', @caption.onWindowResize expect($(@player)).toHandleWith 'resize', @caption.onWindowResize
it 'bind player seek event', ->
expect($(@player)).toHandleWith 'seek', @caption.onUpdatePlayTime
it 'bind player updatePlayTime event', -> it 'bind player updatePlayTime event', ->
expect($(@player)).toHandleWith 'updatePlayTime', @caption.onUpdatePlayTime expect($(@player)).toHandleWith 'updatePlayTime', @caption.onUpdatePlayTime
......
class @Problem class @Problem
constructor: (@id, url) -> constructor: (@id, url) ->
@element = $("#problem_#{id}") @element = $("#problem_#{id}")
@content_url = "#{url}problem_get?id=#{@id}"
@render() @render()
$: (selector) -> $: (selector) ->
...@@ -17,7 +16,7 @@ class @Problem ...@@ -17,7 +16,7 @@ class @Problem
@$('section.action input.save').click @save @$('section.action input.save').click @save
@$('input.math').keyup(@refreshMath).each(@refreshMath) @$('input.math').keyup(@refreshMath).each(@refreshMath)
update_progress: (response) => updateProgress: (response) =>
if response.progress_changed if response.progress_changed
@element.attr progress: response.progress_status @element.attr progress: response.progress_status
@element.trigger('progressChanged') @element.trigger('progressChanged')
...@@ -27,10 +26,9 @@ class @Problem ...@@ -27,10 +26,9 @@ class @Problem
@element.html(content) @element.html(content)
@bind() @bind()
else else
$.postWithPrefix "/modx/problem/#{@id}/problem_get", '', (response) => $.postWithPrefix "/modx/problem/#{@id}/problem_get", (response) =>
@element.html(response.html) @element.html(response.html)
@bind() @bind()
check: => check: =>
Logger.log 'problem_check', @answers Logger.log 'problem_check', @answers
...@@ -38,7 +36,7 @@ class @Problem ...@@ -38,7 +36,7 @@ class @Problem
switch response.success switch response.success
when 'incorrect', 'correct' when 'incorrect', 'correct'
@render(response.contents) @render(response.contents)
@update_progress response @updateProgress response
else else
alert(response.success) alert(response.success)
...@@ -46,7 +44,7 @@ class @Problem ...@@ -46,7 +44,7 @@ class @Problem
Logger.log 'problem_reset', @answers Logger.log 'problem_reset', @answers
$.postWithPrefix "/modx/problem/#{@id}/problem_reset", id: @id, (response) => $.postWithPrefix "/modx/problem/#{@id}/problem_reset", id: @id, (response) =>
@render(response.html) @render(response.html)
@update_progress response @updateProgress response
show: => show: =>
if !@element.hasClass 'showed' if !@element.hasClass 'showed'
...@@ -62,7 +60,7 @@ class @Problem ...@@ -62,7 +60,7 @@ class @Problem
MathJax.Hub.Queue ["Typeset", MathJax.Hub] MathJax.Hub.Queue ["Typeset", MathJax.Hub]
@$('.show').val 'Hide Answer' @$('.show').val 'Hide Answer'
@element.addClass 'showed' @element.addClass 'showed'
@update_progress response @updateProgress response
else else
@$('[id^=answer_], [id^=solution_]').text '' @$('[id^=answer_], [id^=solution_]').text ''
@$('[correct_answer]').attr correct_answer: null @$('[correct_answer]').attr correct_answer: null
...@@ -74,21 +72,22 @@ class @Problem ...@@ -74,21 +72,22 @@ class @Problem
$.postWithPrefix "/modx/problem/#{@id}/problem_save", @answers, (response) => $.postWithPrefix "/modx/problem/#{@id}/problem_save", @answers, (response) =>
if response.success if response.success
alert 'Saved' alert 'Saved'
@update_progress response @updateProgress response
refreshMath: (event, element) => refreshMath: (event, element) =>
element = event.target unless element element = event.target unless element
target = "display_#{element.id.replace(/^input_/, '')}" target = "display_#{element.id.replace(/^input_/, '')}"
if jax = MathJax.Hub.getAllJax(target)[0] if jax = MathJax.Hub.getAllJax(target)[0]
MathJax.Hub.Queue ['Text', jax, $(element).val()] MathJax.Hub.Queue ['Text', jax, $(element).val()],
[@updateMathML, jax, element]
try updateMathML: (jax, element) =>
output = jax.root.toMathML '' try
$("##{element.id}_dynamath").val(output) $("##{element.id}_dynamath").val(jax.root.toMathML '')
catch exception catch exception
throw exception unless exception.restart throw exception unless exception.restart
MathJax.Callback.After [@refreshMath, jax], exception.restart MathJax.Callback.After [@refreshMath, jax], exception.restart
refreshAnswers: => refreshAnswers: =>
@$('input.schematic').each (index, element) -> @$('input.schematic').each (index, element) ->
......
...@@ -10,6 +10,7 @@ class @VideoCaption ...@@ -10,6 +10,7 @@ class @VideoCaption
$(window).bind('resize', @onWindowResize) $(window).bind('resize', @onWindowResize)
$(@player).bind('resize', @onWindowResize) $(@player).bind('resize', @onWindowResize)
$(@player).bind('updatePlayTime', @onUpdatePlayTime) $(@player).bind('updatePlayTime', @onUpdatePlayTime)
$(@player).bind('seek', @onUpdatePlayTime)
$(@player).bind('play', @onPlay) $(@player).bind('play', @onPlay)
@$('.hide-subtitles').click @toggle @$('.hide-subtitles').click @toggle
@$('.subtitles').mouseenter(@onMouseEnter).mouseleave(@onMouseLeave) @$('.subtitles').mouseenter(@onMouseEnter).mouseleave(@onMouseLeave)
......
...@@ -23,3 +23,7 @@ The dev server will automatically compile sass files that have changed. Simply s ...@@ -23,3 +23,7 @@ The dev server will automatically compile sass files that have changed. Simply s
the server using: the server using:
$ rake runserver $ rake runserver
To run it along side of development:
$ sass --watch lms/static/sass:lms/static/sass -r ./lms/static/sass/bourbon/lib/bourbon.rb
...@@ -62,6 +62,8 @@ div.book-wrapper { ...@@ -62,6 +62,8 @@ div.book-wrapper {
@extend .clearfix; @extend .clearfix;
li { li {
background-color: darken($cream, 4%);
&.last { &.last {
display: block; display: block;
float: left; float: left;
...@@ -77,6 +79,10 @@ div.book-wrapper { ...@@ -77,6 +79,10 @@ div.book-wrapper {
display: block; display: block;
float: right; float: right;
} }
&:hover {
background: none;
}
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
@import "plugins/jquery-ui-1.8.16.custom", "plugins/jquery.qtip.min"; @import "plugins/jquery-ui-1.8.16.custom", "plugins/jquery.qtip.min";
// pages // pages
@import "courseware/courseware", "courseware/sidebar", "courseware/video", "courseware/sequence-nav", "courseware/amplifier"; @import "courseware/courseware", "courseware/sidebar", "courseware/video", "courseware/sequence-nav", "courseware/amplifier", "courseware/problems";
@import "textbook"; @import "textbook";
@import "info"; @import "info";
@import "profile"; @import "profile";
......
...@@ -205,7 +205,7 @@ h1.top-header { ...@@ -205,7 +205,7 @@ h1.top-header {
border-top: 1px solid #fff; border-top: 1px solid #fff;
// @include box-shadow(inset 0 1px 0 #fff, inset 1px 0 0 #fff); // @include box-shadow(inset 0 1px 0 #fff, inset 1px 0 0 #fff);
font-size: 12px; font-size: 12px;
height:46px; // height:46px;
line-height: 46px; line-height: 46px;
margin: (-$body-line-height) (-$body-line-height) $body-line-height; margin: (-$body-line-height) (-$body-line-height) $body-line-height;
text-shadow: 0 1px 0 #fff; text-shadow: 0 1px 0 #fff;
...@@ -224,7 +224,7 @@ h1.top-header { ...@@ -224,7 +224,7 @@ h1.top-header {
} }
&.block-link { &.block-link {
background: darken($cream, 5%); // background: darken($cream, 5%);
border-left: 1px solid darken($cream, 20%); border-left: 1px solid darken($cream, 20%);
@include box-shadow(inset 1px 0 0 lighten($cream, 5%)); @include box-shadow(inset 1px 0 0 lighten($cream, 5%));
display: block; display: block;
......
...@@ -12,7 +12,11 @@ div.course-wrapper { ...@@ -12,7 +12,11 @@ div.course-wrapper {
@extend .table-wrapper; @extend .table-wrapper;
ul, ol { ul, ol {
list-style: none; padding-left: lh();
li {
margin-bottom: lh(.5);
}
} }
section.course-content { section.course-content {
...@@ -32,148 +36,6 @@ div.course-wrapper { ...@@ -32,148 +36,6 @@ div.course-wrapper {
} }
} }
ul {
li {
margin-bottom: lh(.5);
}
}
.problem-set {
position: relative;
@extend .clearfix;
h2 {
margin-top: 0;
margin-bottom: 15px;
width: flex-grid(2, 9);
padding-right: flex-gutter(9);
border-right: 1px dashed #ddd;
@include box-sizing(border-box);
display: table-cell;
vertical-align: top;
&.problem-header {
section.staff {
margin-top: 30px;
font-size: 80%;
}
}
@media screen and (max-width:1120px) {
display: block;
width: auto;
border-right: 0;
}
@media print {
display: block;
width: auto;
border-right: 0;
}
}
section.problem {
display: table-cell;
width: flex-grid(7, 9);
padding-left: flex-gutter(9);
@media screen and (max-width:1120px) {
display: block;
width: auto;
padding: 0;
}
@media print {
display: block;
width: auto;
padding: 0;
canvas, img {
page-break-inside: avoid;
}
}
span {
&.unanswered, &.ui-icon-bullet {
@include inline-block();
background: url('../images/unanswered-icon.png') center center no-repeat;
height: 14px;
position: relative;
top: 4px;
width: 14px;
}
&.correct, &.ui-icon-check {
@include inline-block();
background: url('../images/correct-icon.png') center center no-repeat;
height: 20px;
position: relative;
top: 6px;
width: 25px;
}
&.incorrect, &.ui-icon-close {
@include inline-block();
background: url('../images/incorrect-icon.png') center center no-repeat;
height: 20px;
width: 20px;
position: relative;
top: 6px;
}
}
}
div {
> span {
display: block;
margin-bottom: lh(.5);
&[answer] {
border-top: 1px solid #ededed;
border-bottom: 1px solid #ededed;
background: #f3f3f3;
margin: 0 (-(lh()));
padding: lh(.5) lh();
}
}
}
input[type="text"] {
display: inline-block;
width: 50%;
}
center {
display: block;
margin: lh() 0;
border: 1px solid #ccc;
padding: lh();
}
section.action {
margin-top: lh();
input[type="button"] {
padding: lh(.4) lh();
text-shadow: 0 -1px 0 #666;
}
}
}
section.problems-wrapper, div#seq_content {
@extend .problem-set;
}
section.problems-wrapper {
display: table;
width: 100%;
@media screen and (max-width:1120px) {
display: block;
width: auto;
}
}
div#seq_content { div#seq_content {
h1 { h1 {
background: none; background: none;
...@@ -184,6 +46,9 @@ div.course-wrapper { ...@@ -184,6 +46,9 @@ div.course-wrapper {
} }
ol.vert-mod { ol.vert-mod {
list-style: none;
padding-left: 0;
> li { > li {
@extend .clearfix; @extend .clearfix;
@extend .problem-set; @extend .problem-set;
...@@ -221,10 +86,6 @@ div.course-wrapper { ...@@ -221,10 +86,6 @@ div.course-wrapper {
height: 150px; height: 150px;
} }
ul {
list-style: disc outside none;
padding-left: 1em;
}
nav.sequence-bottom { nav.sequence-bottom {
ul { ul {
......
section.problem-set {
position: relative;
@extend .clearfix;
h2 {
margin-top: 0;
margin-bottom: 15px;
width: flex-grid(2, 9);
padding-right: flex-gutter(9);
border-right: 1px dashed #ddd;
@include box-sizing(border-box);
display: table-cell;
vertical-align: top;
&.problem-header {
section.staff {
margin-top: 30px;
font-size: 80%;
}
}
@media screen and (max-width:1120px) {
display: block;
width: auto;
border-right: 0;
}
@media print {
display: block;
width: auto;
border-right: 0;
}
}
section.problem {
display: table-cell;
width: flex-grid(7, 9);
padding-left: flex-gutter(9);
@media screen and (max-width:1120px) {
display: block;
width: auto;
padding: 0;
}
@media print {
display: block;
width: auto;
padding: 0;
canvas, img {
page-break-inside: avoid;
}
}
div {
p.status {
text-indent: -9999px;
margin: -1px 0 0 10px;
}
&.unanswered {
p.status {
@include inline-block();
background: url('../images/unanswered-icon.png') center center no-repeat;
height: 14px;
width: 14px;
}
}
&.correct, &.ui-icon-check {
p.status {
@include inline-block();
background: url('../images/correct-icon.png') center center no-repeat;
height: 20px;
width: 25px;
}
input {
border-color: green;
}
}
&.incorrect, &.ui-icon-close {
p.status {
@include inline-block();
background: url('../images/incorrect-icon.png') center center no-repeat;
height: 20px;
width: 20px;
text-indent: -9999px;
}
input {
border-color: red;
}
}
> span {
display: block;
margin-bottom: lh(.5);
}
p.answer {
@include inline-block();
margin-bottom: 0;
margin-left: 10px;
&:before {
content: "Answer: ";
font-weight: bold;
display: inline;
}
&:empty {
&:before {
display: none;
}
}
}
div.equation {
clear: both;
padding: 6px;
background: #eee;
span {
margin-bottom: 0;
}
}
span {
&.unanswered, &.ui-icon-bullet {
@include inline-block();
background: url('../images/unanswered-icon.png') center center no-repeat;
height: 14px;
position: relative;
top: 4px;
width: 14px;
}
&.correct, &.ui-icon-check {
@include inline-block();
background: url('../images/correct-icon.png') center center no-repeat;
height: 20px;
position: relative;
top: 6px;
width: 25px;
}
&.incorrect, &.ui-icon-close {
@include inline-block();
background: url('../images/incorrect-icon.png') center center no-repeat;
height: 20px;
width: 20px;
position: relative;
top: 6px;
}
}
}
ul {
list-style: disc outside none;
margin-bottom: lh();
margin-left: .75em;
margin-left: .75rem;
}
ol {
list-style: decimal outside none;
margin-bottom: lh();
margin-left: .75em;
margin-left: .75rem;
}
dl {
line-height: 1.4em;
}
dl dt {
font-weight: bold;
}
dl dd {
margin-bottom: 0;
}
dd {
margin-left: .5em;
margin-left: .5rem;
}
li {
line-height: 1.4em;
margin-bottom: lh(.5);
&:last-child {
margin-bottom: 0;
}
}
p {
margin-bottom: lh();
}
table {
margin-bottom: lh();
width: 100%;
border: 1px solid #ddd;
border-collapse: collapse;
th {
border-bottom: 2px solid #ccc;
font-weight: bold;
text-align: left;
}
td {
border: 1px solid #ddd;
}
caption, th, td {
padding: .25em .75em .25em 0;
padding: .25rem .75rem .25rem 0;
}
caption {
background: #f1f1f1;
margin-bottom: .75em;
margin-bottom: .75rem;
padding: .75em 0;
padding: .75rem 0;
}
tr, td, th {
vertical-align: middle;
}
}
hr {
background: #ddd;
border: none;
clear: both;
color: #ddd;
float: none;
height: 1px;
margin: 0 0 .75rem;
width: 100%;
}
.hidden {
display: none;
visibility: hidden;
}
input[type="text"] {
display: inline-block;
width: 50%;
}
center {
display: block;
margin: lh() 0;
border: 1px solid #ccc;
padding: lh();
}
}
section.action {
margin-top: lh(.5);
input[type="button"] {
padding: lh(.4) lh();
text-shadow: 0 -1px 0 #666;
}
}
}
section.problems-wrapper, div#seq_content {
@extend .problem-set;
}
section.problems-wrapper {
display: table;
width: 100%;
@media screen and (max-width:1120px) {
display: block;
width: auto;
}
}
...@@ -11,13 +11,14 @@ nav.sequence-nav { ...@@ -11,13 +11,14 @@ nav.sequence-nav {
height: 100%; height: 100%;
padding-right: flex-grid(1, 9); padding-right: flex-grid(1, 9);
width: 100%; width: 100%;
padding-left: 0;
a { a {
@extend .block-link; @extend .block-link;
} }
li { li {
border-left: 1px solid darken($cream, 20%); border-left: 1px solid darken($cream, 10%);
display: table-cell; display: table-cell;
min-width: 20px; min-width: 20px;
...@@ -29,18 +30,17 @@ nav.sequence-nav { ...@@ -29,18 +30,17 @@ nav.sequence-nav {
background-repeat: no-repeat; background-repeat: no-repeat;
&:hover { &:hover {
background-color: lighten($cream, 3%); background-color: lighten($cream, 8%);
} }
} }
.visited { .visited {
background-color: #DCCDA2; background-color: darken($cream, 4%);
background-repeat: no-repeat; background-repeat: no-repeat;
@include box-shadow(inset 0 0 3px darken(#dccda2, 10%)); @include box-shadow(0);
&:hover { &:hover {
background-color: $cream; background-color: $cream;
background-position: center center;
} }
} }
...@@ -51,7 +51,6 @@ nav.sequence-nav { ...@@ -51,7 +51,6 @@ nav.sequence-nav {
&:hover { &:hover {
background-color: #fff; background-color: #fff;
background-position: center;
} }
} }
...@@ -61,86 +60,87 @@ nav.sequence-nav { ...@@ -61,86 +60,87 @@ nav.sequence-nav {
cursor: pointer; cursor: pointer;
display: block; display: block;
height: 17px; height: 17px;
padding: 15px 0 14px; padding: 15px 0 17px;
position: relative; position: relative;
@include transition(all, .4s, $ease-in-out-quad); @include transition(all, .4s, $ease-in-out-quad);
width: 100%; width: 100%;
background-position: center 8px;
&.progress {
border-bottom-style: solid;
border-bottom-width: 4px;
}
&.progress-none {
@extend .progress;
border-bottom-color: red;
}
&.progress-some {
@extend .progress;
border-bottom-color: yellow;
}
&.progress-done {
@extend .progress;
border-bottom-color: green;
}
//video //video
&.seq_video_inactive { &.seq_video_inactive {
@extend .inactive; @extend .inactive;
background-image: url('../images/sequence-nav/video-icon-normal.png'); background-image: url('../images/sequence-nav/video-icon-visited.png');
background-position: center;
} }
&.seq_video_visited { &.seq_video_visited {
@extend .visited; @extend .visited;
background-image: url('../images/sequence-nav/video-icon-visited.png'); background-image: url('../images/sequence-nav/video-icon-normal.png');
background-position: center;
} }
&.seq_video_active { &.seq_video_active {
@extend .active; @extend .active;
background-image: url('../images/sequence-nav/video-icon-current.png'); background-image: url('../images/sequence-nav/video-icon-current.png');
background-position: center;
} }
//other //other
&.seq_other_inactive { &.seq_other_inactive {
@extend .inactive; @extend .inactive;
background-image: url('../images/sequence-nav/document-icon-normal.png'); background-image: url('../images/sequence-nav/document-icon-visited.png');
background-position: center;
} }
&.seq_other_visited { &.seq_other_visited {
@extend .visited; @extend .visited;
background-image: url('../images/sequence-nav/document-icon-visited.png'); background-image: url('../images/sequence-nav/document-icon-normal.png');
background-position: center;
} }
&.seq_other_active { &.seq_other_active {
@extend .active; @extend .active;
background-image: url('../images/sequence-nav/document-icon-current.png'); background-image: url('../images/sequence-nav/document-icon-current.png');
background-position: center;
} }
//vertical & problems //vertical & problems
&.seq_vertical_inactive, &.seq_problem_inactive { &.seq_vertical_inactive, &.seq_problem_inactive {
@extend .inactive; @extend .inactive;
background-image: url('../images/sequence-nav/list-icon-normal.png'); background-image: url('../images/sequence-nav/list-icon-visited.png');
background-position: center;
} }
&.seq_vertical_visited, &.seq_problem_visited { &.seq_vertical_visited, &.seq_problem_visited {
@extend .visited; @extend .visited;
background-image: url('../images/sequence-nav/list-icon-visited.png'); background-image: url('../images/sequence-nav/list-icon-normal.png');
background-position: center;
} }
&.seq_vertical_active, &.seq_problem_active { &.seq_vertical_active, &.seq_problem_active {
@extend .active; @extend .active;
background-image: url('../images/sequence-nav/list-icon-current.png'); background-image: url('../images/sequence-nav/list-icon-current.png');
background-position: center; }
&:after {
content: " ";
display: block;
width: 11px;
height: 11px;
background: url('../images/sequence-nav/status/dash.png') no-repeat center;
@include position( absolute, 0 0 6px 50% );
margin-left: -5px;
}
//progress
&.progress-none {
&:after {
background: url('../images/sequence-nav/status/not-started.png') no-repeat center;
}
}
&.progress-some {
&:after {
background: url('../images/sequence-nav/status/wrong.png') no-repeat center;
}
}
&.progress-done {
&:after {
background: url('../images/sequence-nav/status/check.png') no-repeat center;
}
} }
p { p {
...@@ -180,6 +180,8 @@ nav.sequence-nav { ...@@ -180,6 +180,8 @@ nav.sequence-nav {
} }
&:hover { &:hover {
background-position: center 8px;
p { p {
display: block; display: block;
margin-top: 4px; margin-top: 4px;
...@@ -215,6 +217,7 @@ nav.sequence-nav { ...@@ -215,6 +217,7 @@ nav.sequence-nav {
display: block; display: block;
text-indent: -9999px; text-indent: -9999px;
@include transition(all, .2s, $ease-in-out-quad); @include transition(all, .2s, $ease-in-out-quad);
line-height: 49px;
&:hover { &:hover {
opacity: .5; opacity: .5;
...@@ -277,6 +280,7 @@ section.course-content { ...@@ -277,6 +280,7 @@ section.course-content {
@include border-radius(3px); @include border-radius(3px);
@include box-shadow(inset 0 0 0 1px lighten(#f6efd4, 5%)); @include box-shadow(inset 0 0 0 1px lighten(#f6efd4, 5%));
@include inline-block(); @include inline-block();
padding-left: 0;
li { li {
float: left; float: left;
......
...@@ -52,14 +52,14 @@ section.course-index { ...@@ -52,14 +52,14 @@ section.course-index {
padding: 1em 1.5em; padding: 1em 1.5em;
li { li {
background: transparent;
border: 1px solid transparent;
@include border-radius(4px);
margin-bottom: lh(.5); margin-bottom: lh(.5);
position: relative;
padding: 5px 36px 5px 10px;
a { a {
border: 1px solid transparent;
background: transparent;
@include border-radius(4px);
position: relative;
padding: 5px 36px 5px 10px;
text-decoration: none; text-decoration: none;
display: block; display: block;
color: #666; color: #666;
...@@ -74,67 +74,70 @@ section.course-index { ...@@ -74,67 +74,70 @@ section.course-index {
display: block; display: block;
} }
} }
}
&:after {
background: transparent;
border-top: 1px solid rgb(180,180,180);
border-right: 1px solid rgb(180,180,180);
content: "";
display: block;
height: 12px;
margin-top: -6px;
opacity: 0;
position: absolute;
top: 50%;
right: 30px;
@include transform(rotate(45deg));
width: 12px;
}
&:hover {
@include background-image(linear-gradient(-90deg, rgba(245,245,245, 0.4), rgba(230,230,230, 0.4)));
border-color: rgb(200,200,200);
&:after { &:after {
opacity: 1; background: transparent;
right: 15px; border-top: 1px solid rgb(180,180,180);
@include transition(all, 0.2s, linear); border-right: 1px solid rgb(180,180,180);
content: "";
display: block;
height: 12px;
margin-top: -6px;
opacity: 0;
position: absolute;
top: 50%;
right: 30px;
@include transform(rotate(45deg));
width: 12px;
} }
> a p { &:hover {
color: #333; @include background-image(linear-gradient(-90deg, rgba(245,245,245, 0.4), rgba(230,230,230, 0.4)));
border-color: rgb(200,200,200);
&:after {
opacity: 1;
right: 15px;
@include transition(all, 0.2s, linear);
}
> a p {
color: #333;
}
} }
}
&:active { &:active {
@include box-shadow(inset 0 1px 14px 0 rgba(0,0,0, 0.1)); @include box-shadow(inset 0 1px 14px 0 rgba(0,0,0, 0.1));
top: 1px;
&:after { &:after {
opacity: 1; opacity: 1;
right: 15px; right: 15px;
}
} }
} }
&.active { &.active {
background: rgb(240,240,240);
@include background-image(linear-gradient(-90deg, rgb(245,245,245), rgb(230,230,230)));
border-color: rgb(200,200,200);
font-weight: bold; font-weight: bold;
> a p { > a {
color: #333; background: rgb(240,240,240);
@include background-image(linear-gradient(-90deg, rgb(245,245,245), rgb(230,230,230)));
border-color: rgb(200,200,200);
&:after {
opacity: 1;
right: 15px;
}
p {
color: #333;
}
} }
span.subtitle { span.subtitle {
font-weight: normal; font-weight: normal;
} }
&:after {
opacity: 1;
right: 15px;
}
} }
} }
} }
......
...@@ -442,6 +442,8 @@ section.course-content { ...@@ -442,6 +442,8 @@ section.course-content {
max-height: 460px; max-height: 460px;
overflow: auto; overflow: auto;
width: flex-grid(3, 9); width: flex-grid(3, 9);
padding-left: 0;
list-style: none;
li { li {
border: 0; border: 0;
......
...@@ -39,7 +39,7 @@ def django_admin(system, env, command, *args) ...@@ -39,7 +39,7 @@ def django_admin(system, env, command, *args)
return "#{django_admin} #{command} --settings=#{system}.envs.#{env} --pythonpath=. #{args.join(' ')}" return "#{django_admin} #{command} --settings=#{system}.envs.#{env} --pythonpath=. #{args.join(' ')}"
end end
task :default => [:pep8, :pylint, :test] task :default => [:test, :pep8, :pylint]
directory REPORT_DIR directory REPORT_DIR
directory LMS_REPORT_DIR directory LMS_REPORT_DIR
...@@ -159,3 +159,15 @@ end ...@@ -159,3 +159,15 @@ end
task :publish => :package do task :publish => :package do
sh("scp #{BUILD_DIR}/#{NORMALIZED_DEPLOY_NAME}_#{PKG_VERSION}*.deb #{PACKAGE_REPO}") sh("scp #{BUILD_DIR}/#{NORMALIZED_DEPLOY_NAME}_#{PKG_VERSION}*.deb #{PACKAGE_REPO}")
end end
namespace :cms do
desc "Import course data within the given DATA_DIR variable"
task :import do
if ENV['DATA_DIR']
sh(django_admin(:cms, :dev, :import, ENV['DATA_DIR']))
else
raise "Please specify a DATA_DIR variable that point to your data directory.\n" +
"Example: \`rake cms:import DATA_DIR=../data\`"
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment