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 = {
PIPELINE_ALWAYS_RECOMPILE = ['sass/base-style.scss']
from x_module import XModuleDescriptor
from raw_module import RawDescriptor
from xmodule.x_module import XModuleDescriptor
from xmodule.raw_module import RawDescriptor
js_file_dir = PROJECT_ROOT / "static" / "coffee" / "module"
try:
os.makedirs(js_file_dir)
......
<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}"
% if size:
size="${size}"
% 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:
<span class="message">${msg|n}</span>
% endif
</div>
</section>
......@@ -2,34 +2,36 @@
### version of textline.html which does dynammic math
###
<section class="text-input-dynamath">
<table style="display:inline; vertical-align:middle;">
<tr>
<td>
<input type="text" name="input_${id}" id="input_${id}" value="${value}" class="math" size="${size if size else ''}" />
</td>
<td>
<span id="answer_${id}"></span>
% 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}" class="math" size="${size if size else ''}" />
<p class="status">
% if state == 'unsubmitted':
<span class="unanswered" style="display:inline-block;" id="status_${id}"></span>
unanswered
% elif state == 'correct':
<span class="correct" id="status_${id}"></span>
correct
% elif state == 'incorrect':
<span class="incorrect" id="status_${id}"></span>
incorrect
% elif state == 'incomplete':
<span class="incorrect" id="status_${id}"></span>
incomplete
% endif
</td>
</tr>
<tr>
<td>
<span id="display_${id}">`{::}`</span>
</td>
<td>
</p>
<p id="answer_${id}" class="answer"></p>
<div id="display_${id}" class="equation">`{::}`</div>
</div>
<textarea style="display:none" id="input_${id}_dynamath" name="input_${id}_dynamath"> </textarea>
</td>
</tr>
</table>
% if msg:
<span class="message">${msg|n}</span>
% endif
......
......@@ -14,7 +14,7 @@
import logging
log = logging.getLogger("mitx.common.lib.mitxmako")
log = logging.getLogger("mitx." + __name__)
from django.template import Context
from django.http import HttpResponse
......
......@@ -223,7 +223,7 @@ def get_module(tree, module, id_tag, module_id, sections_dirname, options):
result_set = tree.xpath(xpath_search)
if len(result_set) < 1:
# 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:
try:
s = get_section(section, options, sections_dirname)
......
......@@ -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
# TODO: These are no longer correct params for I4xSystem -- figure out what this code
# does, clean it up.
from module_render import I4xSystem
system = I4xSystem(None, None, None, coursename=coursename)
total=float(xmodule.capa_module.Module(system, etree.tostring(problem), "id").max_score())
response.max_grade = total
response.save()
# from module_render import I4xSystem
# system = I4xSystem(None, None, None, coursename=coursename)
# total=float(xmodule.capa_module.Module(system, etree.tostring(problem), "id").max_score())
# response.max_grade = total
# 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
weight = problem.get("weight", None)
......
......@@ -15,7 +15,7 @@ middleware.MakoMiddleware()
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?
'''
all_ok = True
......
......@@ -20,10 +20,12 @@ jasmine.stubRequests = ->
settings.success data: jasmine.stubbedMetadata[match[1]]
else if match = settings.url.match /static\/subs\/(.+)\.srt\.sjson/
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' ||
settings.url == '/6002x/modx/sequence/1/goto_position' ||
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
else
throw "External request attempted for #{settings.url}, which is not defined."
......
......@@ -13,6 +13,7 @@ describe 'Problem', ->
spyOn($.fn, 'load').andCallFake (url, callback) ->
$(@).html readFixtures('problem_content.html')
callback()
jasmine.stubRequests()
describe 'constructor', ->
beforeEach ->
......@@ -21,12 +22,6 @@ describe 'Problem', ->
it 'set the element', ->
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', ->
beforeEach ->
spyOn window, 'update_schematics'
......@@ -57,8 +52,11 @@ describe 'Problem', ->
it 'bind the math input', ->
expect($('input.math')).toHandleWith 'keyup', @problem.refreshMath
it 'display the math input', ->
expect(@stubbedJax.root.toMathML).toHaveBeenCalled()
it 'replace math content on the page', ->
expect(MathJax.Hub.Queue.mostRecentCall.args).toEqual [
['Text', @stubbedJax, ''],
[@problem.updateMathML, @stubbedJax, $('#input_example_1').get(0)]
]
describe 'render', ->
beforeEach ->
......@@ -77,12 +75,19 @@ describe 'Problem', ->
expect(@problem.bind).toHaveBeenCalled()
describe 'with no content given', ->
beforeEach ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) ->
callback html: "Hello World"
@problem.render()
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', ->
beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/'
@problem.answers = 'foo=1&bar=2'
......@@ -116,7 +121,6 @@ describe 'Problem', ->
describe 'reset', ->
beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/'
it 'log the problem_reset event', ->
......@@ -130,13 +134,13 @@ describe 'Problem', ->
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_reset', { id: 1 }, jasmine.any(Function)
it 'render the returned content', ->
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) -> callback("Reset!")
spyOn($, 'postWithPrefix').andCallFake (url, answers, callback) ->
callback html: "Reset!"
@problem.reset()
expect(@problem.element.html()).toEqual 'Reset!'
describe 'show', ->
beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/'
@problem.element.prepend '<div id="answer_1_1" /><div id="answer_1_2" />'
......@@ -154,18 +158,19 @@ describe 'Problem', ->
expect($.postWithPrefix).toHaveBeenCalledWith '/modx/problem/1/problem_show', jasmine.any(Function)
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()
expect($('#answer_1_1')).toHaveHtml 'One'
expect($('#answer_1_2')).toHaveHtml 'Two'
it 'toggle the show answer button', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({})
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback(answers: {})
@problem.show()
expect($('.show')).toHaveValue 'Hide Answer'
it 'add the showed class to element', ->
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback({})
spyOn($, 'postWithPrefix').andCallFake (url, callback) -> callback(answers: {})
@problem.show()
expect(@problem.element).toHaveClass 'showed'
......@@ -179,7 +184,8 @@ describe 'Problem', ->
'''
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()
expect($('label[for="input_1_1_1"]')).not.toHaveAttr 'correct_answer', 'true'
expect($('label[for="input_1_1_2"]')).toHaveAttr 'correct_answer', 'true'
......@@ -214,7 +220,6 @@ describe 'Problem', ->
describe 'save', ->
beforeEach ->
jasmine.stubRequests()
@problem = new Problem 1, '/problem/url/'
@problem.answers = 'foo=1&bar=2'
......@@ -236,23 +241,29 @@ describe 'Problem', ->
describe 'refreshMath', ->
beforeEach ->
@problem = new Problem 1, '/problem/url/'
@stubbedJax.root.toMathML.andReturn '<MathML>'
$('#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', ->
beforeEach ->
@problem.refreshMath target: $('#input_example_1').get(0)
it 'should convert and display the MathML object', ->
expect(MathJax.Hub.Queue).toHaveBeenCalledWith ['Text', @stubbedJax, 'E=mc^2']
@problem.updateMathML @stubbedJax, $('#input_example_1').get(0)
it 'should display debug output in hidden div', ->
it 'convert jax to MathML', ->
expect($('#input_example_1_dynamath')).toHaveValue '<MathML>'
describe 'when there is an exception', ->
beforeEach ->
@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', ->
expect(MathJax.Callback.After).toHaveBeenCalledWith [@problem.refreshMath, @stubbedJax], true
......
......@@ -35,6 +35,9 @@ describe 'VideoCaption', ->
it 'bind player resize event', ->
expect($(@player)).toHandleWith 'resize', @caption.onWindowResize
it 'bind player seek event', ->
expect($(@player)).toHandleWith 'seek', @caption.onUpdatePlayTime
it 'bind player updatePlayTime event', ->
expect($(@player)).toHandleWith 'updatePlayTime', @caption.onUpdatePlayTime
......
class @Problem
constructor: (@id, url) ->
@element = $("#problem_#{id}")
@content_url = "#{url}problem_get?id=#{@id}"
@render()
$: (selector) ->
......@@ -17,7 +16,7 @@ class @Problem
@$('section.action input.save').click @save
@$('input.math').keyup(@refreshMath).each(@refreshMath)
update_progress: (response) =>
updateProgress: (response) =>
if response.progress_changed
@element.attr progress: response.progress_status
@element.trigger('progressChanged')
......@@ -27,10 +26,9 @@ class @Problem
@element.html(content)
@bind()
else
$.postWithPrefix "/modx/problem/#{@id}/problem_get", '', (response) =>
$.postWithPrefix "/modx/problem/#{@id}/problem_get", (response) =>
@element.html(response.html)
@bind()
check: =>
Logger.log 'problem_check', @answers
......@@ -38,7 +36,7 @@ class @Problem
switch response.success
when 'incorrect', 'correct'
@render(response.contents)
@update_progress response
@updateProgress response
else
alert(response.success)
......@@ -46,7 +44,7 @@ class @Problem
Logger.log 'problem_reset', @answers
$.postWithPrefix "/modx/problem/#{@id}/problem_reset", id: @id, (response) =>
@render(response.html)
@update_progress response
@updateProgress response
show: =>
if !@element.hasClass 'showed'
......@@ -62,7 +60,7 @@ class @Problem
MathJax.Hub.Queue ["Typeset", MathJax.Hub]
@$('.show').val 'Hide Answer'
@element.addClass 'showed'
@update_progress response
@updateProgress response
else
@$('[id^=answer_], [id^=solution_]').text ''
@$('[correct_answer]').attr correct_answer: null
......@@ -74,21 +72,22 @@ class @Problem
$.postWithPrefix "/modx/problem/#{@id}/problem_save", @answers, (response) =>
if response.success
alert 'Saved'
@update_progress response
@updateProgress response
refreshMath: (event, element) =>
element = event.target unless element
target = "display_#{element.id.replace(/^input_/, '')}"
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
output = jax.root.toMathML ''
$("##{element.id}_dynamath").val(output)
catch exception
throw exception unless exception.restart
MathJax.Callback.After [@refreshMath, jax], exception.restart
updateMathML: (jax, element) =>
try
$("##{element.id}_dynamath").val(jax.root.toMathML '')
catch exception
throw exception unless exception.restart
MathJax.Callback.After [@refreshMath, jax], exception.restart
refreshAnswers: =>
@$('input.schematic').each (index, element) ->
......
......@@ -10,6 +10,7 @@ class @VideoCaption
$(window).bind('resize', @onWindowResize)
$(@player).bind('resize', @onWindowResize)
$(@player).bind('updatePlayTime', @onUpdatePlayTime)
$(@player).bind('seek', @onUpdatePlayTime)
$(@player).bind('play', @onPlay)
@$('.hide-subtitles').click @toggle
@$('.subtitles').mouseenter(@onMouseEnter).mouseleave(@onMouseLeave)
......
......@@ -23,3 +23,7 @@ The dev server will automatically compile sass files that have changed. Simply s
the server using:
$ 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 {
@extend .clearfix;
li {
background-color: darken($cream, 4%);
&.last {
display: block;
float: left;
......@@ -77,6 +79,10 @@ div.book-wrapper {
display: block;
float: right;
}
&:hover {
background: none;
}
}
}
......
......@@ -7,7 +7,7 @@
@import "plugins/jquery-ui-1.8.16.custom", "plugins/jquery.qtip.min";
// 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 "info";
@import "profile";
......
......@@ -205,7 +205,7 @@ h1.top-header {
border-top: 1px solid #fff;
// @include box-shadow(inset 0 1px 0 #fff, inset 1px 0 0 #fff);
font-size: 12px;
height:46px;
// height:46px;
line-height: 46px;
margin: (-$body-line-height) (-$body-line-height) $body-line-height;
text-shadow: 0 1px 0 #fff;
......@@ -224,7 +224,7 @@ h1.top-header {
}
&.block-link {
background: darken($cream, 5%);
// background: darken($cream, 5%);
border-left: 1px solid darken($cream, 20%);
@include box-shadow(inset 1px 0 0 lighten($cream, 5%));
display: block;
......
......@@ -12,7 +12,11 @@ div.course-wrapper {
@extend .table-wrapper;
ul, ol {
list-style: none;
padding-left: lh();
li {
margin-bottom: lh(.5);
}
}
section.course-content {
......@@ -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 {
h1 {
background: none;
......@@ -184,6 +46,9 @@ div.course-wrapper {
}
ol.vert-mod {
list-style: none;
padding-left: 0;
> li {
@extend .clearfix;
@extend .problem-set;
......@@ -221,10 +86,6 @@ div.course-wrapper {
height: 150px;
}
ul {
list-style: disc outside none;
padding-left: 1em;
}
nav.sequence-bottom {
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 {
height: 100%;
padding-right: flex-grid(1, 9);
width: 100%;
padding-left: 0;
a {
@extend .block-link;
}
li {
border-left: 1px solid darken($cream, 20%);
border-left: 1px solid darken($cream, 10%);
display: table-cell;
min-width: 20px;
......@@ -29,18 +30,17 @@ nav.sequence-nav {
background-repeat: no-repeat;
&:hover {
background-color: lighten($cream, 3%);
background-color: lighten($cream, 8%);
}
}
.visited {
background-color: #DCCDA2;
background-color: darken($cream, 4%);
background-repeat: no-repeat;
@include box-shadow(inset 0 0 3px darken(#dccda2, 10%));
@include box-shadow(0);
&:hover {
background-color: $cream;
background-position: center center;
}
}
......@@ -51,7 +51,6 @@ nav.sequence-nav {
&:hover {
background-color: #fff;
background-position: center;
}
}
......@@ -61,86 +60,87 @@ nav.sequence-nav {
cursor: pointer;
display: block;
height: 17px;
padding: 15px 0 14px;
padding: 15px 0 17px;
position: relative;
@include transition(all, .4s, $ease-in-out-quad);
width: 100%;
&.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;
}
background-position: center 8px;
//video
&.seq_video_inactive {
@extend .inactive;
background-image: url('../images/sequence-nav/video-icon-normal.png');
background-position: center;
background-image: url('../images/sequence-nav/video-icon-visited.png');
}
&.seq_video_visited {
@extend .visited;
background-image: url('../images/sequence-nav/video-icon-visited.png');
background-position: center;
background-image: url('../images/sequence-nav/video-icon-normal.png');
}
&.seq_video_active {
@extend .active;
background-image: url('../images/sequence-nav/video-icon-current.png');
background-position: center;
}
//other
&.seq_other_inactive {
@extend .inactive;
background-image: url('../images/sequence-nav/document-icon-normal.png');
background-position: center;
background-image: url('../images/sequence-nav/document-icon-visited.png');
}
&.seq_other_visited {
@extend .visited;
background-image: url('../images/sequence-nav/document-icon-visited.png');
background-position: center;
background-image: url('../images/sequence-nav/document-icon-normal.png');
}
&.seq_other_active {
@extend .active;
background-image: url('../images/sequence-nav/document-icon-current.png');
background-position: center;
}
//vertical & problems
&.seq_vertical_inactive, &.seq_problem_inactive {
@extend .inactive;
background-image: url('../images/sequence-nav/list-icon-normal.png');
background-position: center;
background-image: url('../images/sequence-nav/list-icon-visited.png');
}
&.seq_vertical_visited, &.seq_problem_visited {
@extend .visited;
background-image: url('../images/sequence-nav/list-icon-visited.png');
background-position: center;
background-image: url('../images/sequence-nav/list-icon-normal.png');
}
&.seq_vertical_active, &.seq_problem_active {
@extend .active;
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 {
......@@ -180,6 +180,8 @@ nav.sequence-nav {
}
&:hover {
background-position: center 8px;
p {
display: block;
margin-top: 4px;
......@@ -215,6 +217,7 @@ nav.sequence-nav {
display: block;
text-indent: -9999px;
@include transition(all, .2s, $ease-in-out-quad);
line-height: 49px;
&:hover {
opacity: .5;
......@@ -277,6 +280,7 @@ section.course-content {
@include border-radius(3px);
@include box-shadow(inset 0 0 0 1px lighten(#f6efd4, 5%));
@include inline-block();
padding-left: 0;
li {
float: left;
......
......@@ -52,14 +52,14 @@ section.course-index {
padding: 1em 1.5em;
li {
background: transparent;
border: 1px solid transparent;
@include border-radius(4px);
margin-bottom: lh(.5);
position: relative;
padding: 5px 36px 5px 10px;
a {
border: 1px solid transparent;
background: transparent;
@include border-radius(4px);
position: relative;
padding: 5px 36px 5px 10px;
text-decoration: none;
display: block;
color: #666;
......@@ -74,67 +74,70 @@ section.course-index {
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 {
opacity: 1;
right: 15px;
@include transition(all, 0.2s, linear);
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;
}
> a p {
color: #333;
&: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 {
opacity: 1;
right: 15px;
@include transition(all, 0.2s, linear);
}
> a p {
color: #333;
}
}
}
&:active {
@include box-shadow(inset 0 1px 14px 0 rgba(0,0,0, 0.1));
top: 1px;
&:active {
@include box-shadow(inset 0 1px 14px 0 rgba(0,0,0, 0.1));
&:after {
opacity: 1;
right: 15px;
&:after {
opacity: 1;
right: 15px;
}
}
}
&.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;
> a p {
color: #333;
> a {
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 {
font-weight: normal;
}
&:after {
opacity: 1;
right: 15px;
}
}
}
}
......
......@@ -442,6 +442,8 @@ section.course-content {
max-height: 460px;
overflow: auto;
width: flex-grid(3, 9);
padding-left: 0;
list-style: none;
li {
border: 0;
......
......@@ -39,7 +39,7 @@ def django_admin(system, env, command, *args)
return "#{django_admin} #{command} --settings=#{system}.envs.#{env} --pythonpath=. #{args.join(' ')}"
end
task :default => [:pep8, :pylint, :test]
task :default => [:test, :pep8, :pylint]
directory REPORT_DIR
directory LMS_REPORT_DIR
......@@ -159,3 +159,15 @@ end
task :publish => :package do
sh("scp #{BUILD_DIR}/#{NORMALIZED_DEPLOY_NAME}_#{PKG_VERSION}*.deb #{PACKAGE_REPO}")
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