Commit cc67017d by Diana Huang

Merge branch 'master' into diana/open-ended-ui-updates

parents 5ca1586e 548f3de5
...@@ -364,6 +364,16 @@ class ContentStoreTest(TestCase): ...@@ -364,6 +364,16 @@ class ContentStoreTest(TestCase):
effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None])) effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None]))
self.assertEqual(effort.definition['data'],'TBD') self.assertEqual(effort.definition['data'],'TBD')
def test_remove_hide_progress_tab(self):
import_from_xml(modulestore(), 'common/test/data/', ['full'])
ms = modulestore('direct')
cs = contentstore()
source_location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012')
course = ms.get_item(source_location)
self.assertNotIn('hide_progress_tab', course.metadata)
def test_clone_course(self): def test_clone_course(self):
import_from_xml(modulestore(), 'common/test/data/', ['full']) import_from_xml(modulestore(), 'common/test/data/', ['full'])
......
@font-face{font-family:'Open Sans';font-style:normal;font-weight:700;src:local("Open Sans Bold"),local("OpenSans-Bold"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/k3k702ZOKiLJc3WVjuplzKRDOzjiPcYnFooOUGCOsRk.woff) format("woff")}@font-face{font-family:'Open Sans';font-style:normal;font-weight:300;src:local("Open Sans Light"),local("OpenSans-Light"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff) format("woff")}@font-face{font-family:'Open Sans';font-style:italic;font-weight:700;src:local("Open Sans Bold Italic"),local("OpenSans-BoldItalic"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxhbnBKKEOwRKgsHDreGcocg.woff) format("woff")}@font-face{font-family:'Open Sans';font-style:italic;font-weight:300;src:local("Open Sans Light Italic"),local("OpenSansLight-Italic"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxvR_54zmj3SbGZQh3vCOwvY.woff) format("woff")}@font-face{font-family:'Open Sans';font-style:italic;font-weight:400;src:local("Open Sans Italic"),local("OpenSans-Italic"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/xjAJXh38I15wypJXxuGMBrrIa-7acMAeDBVuclsi6Gc.woff) format("woff")}@font-face{font-family:'Open Sans';font-style:normal;font-weight:400;src:local("Open Sans"),local("OpenSans"),url(http://themes.googleusercontent.com/static/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3bO3LdcAZYWl9Si6vvxL-qU.woff) format("woff")}
.mceContentBody { .mceContentBody {
padding: 10px; padding: 10px;
background-color: #fff; background-color: #fff;
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif; font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
font-size: 16px; font-size: 16px;
line-height: 1.6; line-height: 1.6;
color: #3c3c3c; color: #3c3c3c;
scrollbar-3dlight-color: #F0F0EE; scrollbar-3dlight-color: #F0F0EE;
scrollbar-arrow-color: #676662; scrollbar-arrow-color: #676662;
scrollbar-base-color: #F0F0EE; scrollbar-base-color: #F0F0EE;
scrollbar-darkshadow-color: #DDDDDD; scrollbar-darkshadow-color: #DDDDDD;
scrollbar-face-color: #E0E0DD; scrollbar-face-color: #E0E0DD;
scrollbar-highlight-color: #F0F0EE; scrollbar-highlight-color: #F0F0EE;
scrollbar-shadow-color: #F0F0EE; scrollbar-shadow-color: #F0F0EE;
scrollbar-track-color: #F5F5F5; scrollbar-track-color: #F5F5F5;
} }
h1 { h1 {
color: #3c3c3c; color: #3c3c3c;
font-weight: normal; font-weight: normal;
font-size: 2em; font-size: 2em;
line-height: 1.4em; line-height: 1.4em;
letter-spacing: 1px; letter-spacing: 1px;
margin: 0 0 1.416em 0;
} }
h2 { h2 {
color: #646464; color: #646464;
font-weight: normal; font-weight: normal;
font-size: 1.2em; font-size: 1.2em;
line-height: 1.2em; line-height: 1.2em;
letter-spacing: 1px; letter-spacing: 1px;
margin-bottom: 15px; margin-bottom: 15px;
text-transform: uppercase; text-transform: uppercase;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
}
h3, h4, h5, h6 {
margin: 0 0 10px 0;
font-weight: 600;
} }
h3 { h3 {
font-size: 1.2em; font-size: 1.2em;
font-weight: 600; }
h4 {
font-size: 1em;
}
h5 {
font-size: .83em;
}
h6 {
font-size: 0.75em;
} }
p { p {
margin-bottom: 1.416em; margin-bottom: 1.416em;
font-size: 1em; font-size: 1em;
line-height: 1.6em !important; line-height: 1.6em !important;
color: $baseFontColor; color: #3c3c3c;
} }
em, i { em, i {
font-style: italic; font-style: italic;
} }
strong, b { strong, b {
font-style: bold; font-style: bold;
} }
p + p, ul + p, ol + p { p + p, ul + p, ol + p {
margin-top: 20px; margin-top: 20px;
} }
ol, ul { ol, ul {
margin: 1em 0; margin: 1em 0;
padding: 0 0 0 1em; padding: 0 0 0 1em;
color: #3c3c3c;
} }
ol li, ul li { ol li, ul li {
margin-bottom: 0.708em; margin-bottom: 0.708em;
} }
ol { ol {
list-style: decimal outside none; list-style: decimal outside none;
} }
ul { ul {
list-style: disc outside none; list-style: disc outside none;
} }
a, a:link, a:visited, a:hover, a:active { a, a:link, a:visited, a:hover, a:active {
color: #1d9dd9; color: #1d9dd9;
} }
img { img {
max-width: 100%; max-width: 100%;
} }
code { pre {
margin: 1em 0;
color: #3c3c3c;
font-family: monospace, serif; font-family: monospace, serif;
background: none; font-size: 1em;
} white-space: pre-wrap;
\ No newline at end of file word-wrap: break-word;
}
code {
font-family: monospace, serif;
background: none;
color: #3c3c3c;
padding: 0;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 16px;
}
th {
background: #eee;
font-weight: bold;
}
table td, th {
margin: 20px 0;
padding: 10px;
border: 1px solid #ccc !important;
text-align: left;
font-size: 14px;
}
...@@ -199,7 +199,7 @@ code { ...@@ -199,7 +199,7 @@ code {
padding: 20px; padding: 20px;
} }
h4 { .header {
padding: 6px 14px; padding: 6px 14px;
border-bottom: 1px solid $mediumGrey; border-bottom: 1px solid $mediumGrey;
border-radius: 2px 2px 0 0; border-radius: 2px 2px 0 0;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
</div> </div>
<div class="sidebar"> <div class="sidebar">
<div class="unit-settings window"> <div class="unit-settings window">
<h4>Page Settings</h4> <h4 class="header">Page Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="row visibility"> <div class="row visibility">
<label class="inline-label">Visibility:</label> <label class="inline-label">Visibility:</label>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<article class="subsection-body window" data-id="${subsection.location}"> <article class="subsection-body window" data-id="${subsection.location}">
<div class="subsection-name-input"> <div class="subsection-name-input">
<label>Display Name:</label> <label>Display Name:</label>
<input type="text" value="${subsection.metadata['display_name']}" class="subsection-display-name-input" data-metadata-name="display_name"/> <input type="text" value="${subsection.display_name}" class="subsection-display-name-input" data-metadata-name="display_name"/>
</div> </div>
<div> <div>
<label>Format:</label> <label>Format:</label>
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
<div class="sidebar"> <div class="sidebar">
<div class="unit-settings window id-holder" data-id="${subsection.location}"> <div class="unit-settings window id-holder" data-id="${subsection.location}">
<h4>Subsection Settings</h4> <h4 class="header">Subsection Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="scheduled-date-input row"> <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> <label>Release date:<!-- <span class="description">Determines when this subsection and the units within it will be released publicly.</span>--></label>
......
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
<div class="sidebar"> <div class="sidebar">
<div class="unit-settings window"> <div class="unit-settings window">
<h4>Unit Settings</h4> <h4 class="header">Unit Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="row visibility"> <div class="row visibility">
<label class="inline-label">Visibility:</label> <label class="inline-label">Visibility:</label>
...@@ -126,7 +126,7 @@ ...@@ -126,7 +126,7 @@
</div> </div>
</div> </div>
<div class="window unit-location"> <div class="window unit-location">
<h4>Unit Location</h4> <h4 class="header">Unit Location</h4>
<div class="window-contents"> <div class="window-contents">
<div><input type="text" class="url" value="/courseware/${section.url_name}/${subsection.url_name}" disabled /></div> <div><input type="text" class="url" value="/courseware/${section.url_name}/${subsection.url_name}" disabled /></div>
<ol> <ol>
......
...@@ -4,8 +4,8 @@ ...@@ -4,8 +4,8 @@
%if markdown != '' or data == '<problem>\n</problem>\n': %if markdown != '' or data == '<problem>\n</problem>\n':
<div class="editor-bar"> <div class="editor-bar">
<ul class="format-buttons"> <ul class="format-buttons">
<li><a href="#" class="header-button" data-tooltip="Header"><span <li><a href="#" class="header-button" data-tooltip="Heading 1"><span
class="problem-editor-icon header"></span></a></li> class="problem-editor-icon heading1"></span></a></li>
<li><a href="#" class="multiple-choice-button" data-tooltip="Multiple Choice"><span <li><a href="#" class="multiple-choice-button" data-tooltip="Multiple Choice"><span
class="problem-editor-icon multiple-choice"></span></a></li> class="problem-editor-icon multiple-choice"></span></a></li>
<li><a href="#" class="checks-button" data-tooltip="Check Multiple"><span <li><a href="#" class="checks-button" data-tooltip="Check Multiple"><span
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
<article class="simple-editor-cheatsheet"> <article class="simple-editor-cheatsheet">
<div class="cheatsheet-wrapper"> <div class="cheatsheet-wrapper">
<div class="row"> <div class="row">
<h6>Header</h6> <h6>Heading 1</h6>
<div class="col sample header"> <div class="col sample heading-1">
<img src="/static/img/header-example.png" /> <img src="/static/img/header-example.png" />
</div> </div>
<div class="col"> <div class="col">
......
// HTML component display:
* {
line-height: 1.4em;
}
h1 {
color: $baseFontColor;
font: normal 2em/1.4em $sans-serif;
letter-spacing: 1px;
margin: 0 0 1.416em 0;
}
h2 {
color: #646464;
font: normal 1.2em/1.2em $sans-serif;
letter-spacing: 1px;
margin-bottom: 15px;
text-transform: uppercase;
-webkit-font-smoothing: antialiased;
}
h3, h4, h5, h6 {
margin: 0 0 10px 0;
font-weight: 600;
}
h3 {
font-size: 1.2em;
}
h4 {
font-size: 1em;
}
h5 {
font-size: .83em;
}
h6 {
font-size: 0.75em;
}
p {
margin-bottom: 1.416em;
font-size: 1em;
line-height: 1.6em !important;
color: $baseFontColor;
}
em, i {
font-style: italic;
}
strong, b {
font-style: bold;
}
p + p, ul + p, ol + p {
margin-top: 20px;
}
ol, ul {
margin: 1em 0;
padding: 0 0 0 1em;
color: $baseFontColor;
li {
margin-bottom: 0.708em;
}
}
ol {
list-style: decimal outside none;
}
ul {
list-style: disc outside none;
}
a {
&:link, &:visited, &:hover, &:active {
color: #1d9dd9;
}
}
img {
max-width: 100%;
}
pre {
margin: 1em 0;
color: $baseFontColor;
font-family: monospace, serif;
font-size: 1em;
white-space: pre-wrap;
word-wrap: break-word;
}
code {
color: $baseFontColor;
font-family: monospace, serif;
background: none;
padding: 0;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 16px;
}
th {
background: #eee;
font-weight: bold;
}
table td, th {
margin: 20px 0;
padding: 10px;
border: 1px solid #ccc !important;
text-align: left;
font-size: 14px;
}
\ No newline at end of file
// HTML component editor:
.html-editor { .html-editor {
@include clearfix(); @include clearfix();
......
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
background: url(../img/problem-editor-icons.png) no-repeat; background: url(../img/problem-editor-icons.png) no-repeat;
} }
.problem-editor-icon.header { .problem-editor-icon.heading1 {
width: 18px; width: 18px;
background-position: -265px 0; background-position: -265px 0;
} }
......
...@@ -25,7 +25,8 @@ class HtmlModule(XModule): ...@@ -25,7 +25,8 @@ class HtmlModule(XModule):
] ]
} }
js_module_name = "HTMLModule" js_module_name = "HTMLModule"
css = {'scss': [resource_string(__name__, 'css/html/display.scss')]}
def get_html(self): def get_html(self):
return self.html return self.html
......
...@@ -22,15 +22,24 @@ class @HTMLEditingDescriptor ...@@ -22,15 +22,24 @@ class @HTMLEditingDescriptor
schema: "html5", schema: "html5",
# TODO: we should share this CSS with studio (and LMS) # TODO: we should share this CSS with studio (and LMS)
content_css : "/static/css/tiny-mce.css", content_css : "/static/css/tiny-mce.css",
# Disable h4, h5, and h6 styles as we don't have CSS for them.
formats : {
h4: {},
h5: {},
h6: {}
},
# Disable visual aid on borderless table.
visual:false,
# We may want to add "styleselect" when we collect all styles used throughout the LMS # We may want to add "styleselect" when we collect all styles used throughout the LMS
theme_advanced_buttons1 : "formatselect,bold,italic,underline,bullist,numlist,outdent,indent,blockquote,link,unlink", theme_advanced_buttons1 : "formatselect,bold,italic,underline,|,bullist,numlist,outdent,indent,|,blockquote,wrapAsCode,|,link,unlink",
theme_advanced_toolbar_location : "top", theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left", theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "none", theme_advanced_statusbar_location : "none",
theme_advanced_resizing : true, theme_advanced_resizing : true,
theme_advanced_blockformats : "p,code,h2,h3,blockquote", theme_advanced_blockformats : "p,pre,h1,h2,h3",
width: '100%', width: '100%',
height: '400px', height: '400px',
setup : HTMLEditingDescriptor.setupTinyMCE,
# Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered. # Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered.
# The tinyMCE callback passes in the editor as a paramter. # The tinyMCE callback passes in the editor as a paramter.
init_instance_callback: @focusVisualEditor init_instance_callback: @focusVisualEditor
...@@ -39,13 +48,25 @@ class @HTMLEditingDescriptor ...@@ -39,13 +48,25 @@ class @HTMLEditingDescriptor
@showingVisualEditor = true @showingVisualEditor = true
@element.on('click', '.editor-tabs .tab', @onSwitchEditor) @element.on('click', '.editor-tabs .tab', @onSwitchEditor)
@setupTinyMCE: (ed) ->
ed.addButton('wrapAsCode', {
title : 'Code Block',
image : '/static/images/ico-tinymce-code.png',
onclick : () ->
ed.formatter.toggle('code')
})
ed.onNodeChange.add((editor, command, e) ->
command.setActive('wrapAsCode', e.nodeName == 'CODE')
)
onSwitchEditor: (e)=> onSwitchEditor: (e)=>
e.preventDefault(); e.preventDefault();
if not $(e.currentTarget).hasClass('current') if not $(e.currentTarget).hasClass('current')
$('.editor-tabs .current').removeClass('current') $('.editor-tabs .current', @element).removeClass('current')
$(e.currentTarget).addClass('current') $(e.currentTarget).addClass('current')
$('table.mceToolbar').toggleClass(HTMLEditingDescriptor.isInactiveClass) $('table.mceToolbar', @element).toggleClass(HTMLEditingDescriptor.isInactiveClass)
$(@advanced_editor.getWrapperElement()).toggleClass(HTMLEditingDescriptor.isInactiveClass) $(@advanced_editor.getWrapperElement()).toggleClass(HTMLEditingDescriptor.isInactiveClass)
visualEditor = @getVisualEditor() visualEditor = @getVisualEditor()
......
...@@ -73,7 +73,7 @@ class DraftModuleStore(ModuleStoreBase): ...@@ -73,7 +73,7 @@ class DraftModuleStore(ModuleStoreBase):
except ItemNotFoundError: except ItemNotFoundError:
return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, location, depth=0)) return wrap_draft(super(DraftModuleStore, self).get_instance(course_id, location, depth=0))
def get_items(self, location, depth=0): def get_items(self, location, course_id=None, depth=0):
""" """
Returns a list of XModuleDescriptor instances for the items Returns a list of XModuleDescriptor instances for the items
that match location. Any element of location that is None is treated that match location. Any element of location that is None is treated
...@@ -89,8 +89,8 @@ class DraftModuleStore(ModuleStoreBase): ...@@ -89,8 +89,8 @@ class DraftModuleStore(ModuleStoreBase):
draft_loc = as_draft(location) draft_loc = as_draft(location)
# cdodge: we're forcing depth=0 here as the Draft store is not handling caching well # cdodge: we're forcing depth=0 here as the Draft store is not handling caching well
draft_items = super(DraftModuleStore, self).get_items(draft_loc, depth=0) draft_items = super(DraftModuleStore, self).get_items(draft_loc, course_id=course_id, depth=0)
items = super(DraftModuleStore, self).get_items(location, depth=0) items = super(DraftModuleStore, self).get_items(location, course_id=course_id, depth=0)
draft_locs_found = set(item.location._replace(revision=None) for item in draft_items) draft_locs_found = set(item.location._replace(revision=None) for item in draft_items)
non_draft_items = [ non_draft_items = [
......
...@@ -137,9 +137,6 @@ def import_from_xml(store, data_dir, course_dirs=None, ...@@ -137,9 +137,6 @@ def import_from_xml(store, data_dir, course_dirs=None,
module = remap_namespace(module, target_location_namespace) module = remap_namespace(module, target_location_namespace)
# HACK: for now we don't support progress tabs. There's a special metadata configuration setting for this.
module.metadata['hide_progress_tab'] = True
# cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which # cdodge: more hacks (what else). Seems like we have a problem when importing a course (like 6.002) which
# does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS, # does not have any tabs defined in the policy file. The import goes fine and then displays fine in LMS,
# but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that - # but if someone tries to add a new tab in the CMS, then the LMS barfs because it expects that -
......
<%namespace name='static' file='static_content.html'/> <%namespace name='static' file='static_content.html'/>
<script type="text/javascript" src="${static.url('js/vendor/RequireJS.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery.min.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery-ui.min.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery-ui.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/swfobject/swfobject.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/swfobject/swfobject.js')}"></script>
......
...@@ -43,7 +43,9 @@ rake test_cms[false] || TESTS_FAILED=1 ...@@ -43,7 +43,9 @@ rake test_cms[false] || TESTS_FAILED=1
rake test_lms[false] || TESTS_FAILED=1 rake test_lms[false] || TESTS_FAILED=1
rake test_common/lib/capa || TESTS_FAILED=1 rake test_common/lib/capa || TESTS_FAILED=1
rake test_common/lib/xmodule || TESTS_FAILED=1 rake test_common/lib/xmodule || TESTS_FAILED=1
rake phantomjs_jasmine_lms || true # Don't run the lms jasmine tests for now because
# they mostly all fail anyhow
# rake phantomjs_jasmine_lms || true
rake phantomjs_jasmine_cms || TESTS_FAILED=1 rake phantomjs_jasmine_cms || TESTS_FAILED=1
rake phantomjs_jasmine_common/lib/xmodule || TESTS_FAILED=1 rake phantomjs_jasmine_common/lib/xmodule || TESTS_FAILED=1
......
...@@ -16,7 +16,6 @@ class Command(BaseCommand): ...@@ -16,7 +16,6 @@ class Command(BaseCommand):
This command does not do anything other than report the current This command does not do anything other than report the current
certificate status. certificate status.
unavailable - A student is not eligible for a certificate.
generating - A request has been made to generate a certificate, generating - A request has been made to generate a certificate,
but it has not been generated yet. but it has not been generated yet.
regenerating - A request has been made to regenerate a certificate, regenerating - A request has been made to regenerate a certificate,
...@@ -64,11 +63,7 @@ class Command(BaseCommand): ...@@ -64,11 +63,7 @@ class Command(BaseCommand):
enrolled_students = User.objects.filter( enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id).prefetch_related( courseenrollment__course_id=course_id).prefetch_related(
"groups").order_by('username') "groups").order_by('username')
unavailable_count = enrolled_students.count() - \
GeneratedCertificate.objects.filter(
course_id__exact=course_id).count()
cert_data[course_id] = {'enrolled': enrolled_students.count()} cert_data[course_id] = {'enrolled': enrolled_students.count()}
cert_data[course_id].update({'unavailable': unavailable_count})
tallies = GeneratedCertificate.objects.filter( tallies = GeneratedCertificate.objects.filter(
course_id__exact=course_id).values('status').annotate( course_id__exact=course_id).values('status').annotate(
......
...@@ -23,26 +23,37 @@ class Command(BaseCommand): ...@@ -23,26 +23,37 @@ class Command(BaseCommand):
option_list = BaseCommand.option_list + ( option_list = BaseCommand.option_list + (
make_option('-n', '--noop', make_option('-n', '--noop',
action='store_true', action='store_true',
dest='noop', dest='noop',
default=False, default=False,
help="Don't add certificate requests to the queue"), help="Don't add certificate requests to the queue"),
make_option('-c', '--course', make_option('-c', '--course',
metavar='COURSE_ID', metavar='COURSE_ID',
dest='course', dest='course',
default=False, default=False,
help='Grade and generate certificates for a specific course'), help='Grade and generate certificates '
'for a specific course'),
make_option('-f', '--force-gen',
metavar='STATUS',
dest='force',
default=False,
help='Will generate new certificates for only those users '
'whose entry in the certificate table matches STATUS. '
'STATUS can be generating, unavailable, deleted, error '
'or notpassing.'),
) )
def handle(self, *args, **options): def handle(self, *args, **options):
# Will only generate a certificate if the current # Will only generate a certificate if the current
# status is in this state # status is in the unavailable state, can be set
# to something else with the force flag
VALID_STATUSES = [ if options['force']:
CertificateStatuses.unavailable valid_statuses = getattr(CertificateStatuses, options['force'])
] else:
valid_statuses = [CertificateStatuses.unavailable]
# Print update after this many students # Print update after this many students
...@@ -54,8 +65,8 @@ class Command(BaseCommand): ...@@ -54,8 +65,8 @@ class Command(BaseCommand):
# Find all courses that have ended # Find all courses that have ended
ended_courses = [] ended_courses = []
for course_id in [course # all courses in COURSE_LISTINGS for course_id in [course # all courses in COURSE_LISTINGS
for sub in settings.COURSE_LISTINGS for sub in settings.COURSE_LISTINGS
for course in settings.COURSE_LISTINGS[sub]]: for course in settings.COURSE_LISTINGS[sub]]:
course_loc = CourseDescriptor.id_to_location(course_id) course_loc = CourseDescriptor.id_to_location(course_id)
course = modulestore().get_instance(course_id, course_loc) course = modulestore().get_instance(course_id, course_loc)
if course.has_ended(): if course.has_ended():
...@@ -64,8 +75,8 @@ class Command(BaseCommand): ...@@ -64,8 +75,8 @@ class Command(BaseCommand):
for course_id in ended_courses: for course_id in ended_courses:
print "Fetching enrolled students for {0}".format(course_id) print "Fetching enrolled students for {0}".format(course_id)
enrolled_students = User.objects.filter( enrolled_students = User.objects.filter(
courseenrollment__course_id=course_id).prefetch_related( courseenrollment__course_id=course_id).prefetch_related(
"groups").order_by('username') "groups").order_by('username')
xq = XQueueCertInterface() xq = XQueueCertInterface()
total = enrolled_students.count() total = enrolled_students.count()
count = 0 count = 0
...@@ -81,11 +92,11 @@ class Command(BaseCommand): ...@@ -81,11 +92,11 @@ class Command(BaseCommand):
hours, remainder = divmod(timeleft.seconds, 3600) hours, remainder = divmod(timeleft.seconds, 3600)
minutes, seconds = divmod(remainder, 60) minutes, seconds = divmod(remainder, 60)
print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format( print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format(
count, total, hours, minutes) count, total, hours, minutes)
start = datetime.datetime.now() start = datetime.datetime.now()
if certificate_status_for_student( if certificate_status_for_student(
student, course_id)['status'] in VALID_STATUSES: student, course_id)['status'] in valid_statuses:
if not options['noop']: if not options['noop']:
# Add the certificate request to the queue # Add the certificate request to the queue
ret = xq.add_cert(student, course_id) ret = xq.add_cert(student, course_id)
......
...@@ -192,7 +192,7 @@ class XQueueCertInterface(object): ...@@ -192,7 +192,7 @@ class XQueueCertInterface(object):
Will change the certificate status to 'deleting'. Will change the certificate status to 'deleting'.
Certificate must be in the 'unavailable', 'error', Certificate must be in the 'unavailable', 'error',
or 'deleted' state. 'deleted' or 'generating' state.
If a student has a passing grade a request will made If a student has a passing grade a request will made
for a new cert for a new cert
...@@ -204,7 +204,8 @@ class XQueueCertInterface(object): ...@@ -204,7 +204,8 @@ class XQueueCertInterface(object):
""" """
VALID_STATUSES = [status.unavailable, status.deleted, status.error, VALID_STATUSES = [ status.generating,
status.unavailable, status.deleted, status.error,
status.notpassing] status.notpassing]
cert_status = certificate_status_for_student( cert_status = certificate_status_for_student(
......
...@@ -15,6 +15,8 @@ $monospace: Monaco, 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; ...@@ -15,6 +15,8 @@ $monospace: Monaco, 'Bitstream Vera Sans Mono', 'Lucida Console', monospace;
$body-font-size: em(14); $body-font-size: em(14);
$body-line-height: golden-ratio(.875em, 1); $body-line-height: golden-ratio(.875em, 1);
$base-font-color: rgb(60,60,60); $base-font-color: rgb(60,60,60);
$baseFontColor: rgb(60,60,60);
$base-font-color: rgb(60,60,60);
$lighter-base-font-color: rgb(100,100,100); $lighter-base-font-color: rgb(100,100,100);
$blue: rgb(29,157,217); $blue: rgb(29,157,217);
......
${module_content} ${module_content}
%if edit_link: %if edit_link:
<div> <div>
<a href="${edit_link}">Edit</a> / <a href="${edit_link}">Edit</a> /
<a href="#${element_id}_xqa-modal" onclick="javascript:getlog('${element_id}', { <a href="#${element_id}_xqa-modal" onclick="javascript:getlog('${element_id}', {
'location': '${location}', 'location': '${location}',
'xqa_key': '${xqa_key}', 'xqa_key': '${xqa_key}',
...@@ -61,18 +61,16 @@ category = ${category | h} ...@@ -61,18 +61,16 @@ category = ${category | h}
<script type="text/javascript"> <script type="text/javascript">
// assumes courseware.html's loaded this method. // assumes courseware.html's loaded this method.
% if staff_access: setup_debug('${element_id}',
setup_debug('${element_id}', %if edit_link:
%if edit_link: '${edit_link}',
'${edit_link}', %else:
%else: null,
null, %endif
%endif {
{ 'location': '${location}',
'location': '${location}', 'xqa_key': '${xqa_key}',
'xqa_key': '${xqa_key}', 'category': '${category}',
'category': '${category}', 'user': '${user}'
'user': '${user}' });
});
% endif
</script> </script>
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