Merge branch 'master' into diana/open-ended-ui-updates
This commit is contained in:
@@ -364,6 +364,16 @@ class ContentStoreTest(TestCase):
|
||||
effort = ms.get_item(Location(['i4x','edX','full','about','end_date', None]))
|
||||
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):
|
||||
import_from_xml(modulestore(), 'common/test/data/', ['full'])
|
||||
|
||||
@@ -1,89 +1,140 @@
|
||||
@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 {
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #3c3c3c;
|
||||
scrollbar-3dlight-color: #F0F0EE;
|
||||
scrollbar-arrow-color: #676662;
|
||||
scrollbar-base-color: #F0F0EE;
|
||||
scrollbar-darkshadow-color: #DDDDDD;
|
||||
scrollbar-face-color: #E0E0DD;
|
||||
scrollbar-highlight-color: #F0F0EE;
|
||||
scrollbar-shadow-color: #F0F0EE;
|
||||
scrollbar-track-color: #F5F5F5;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
font-family: 'Open Sans', Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: #3c3c3c;
|
||||
scrollbar-3dlight-color: #F0F0EE;
|
||||
scrollbar-arrow-color: #676662;
|
||||
scrollbar-base-color: #F0F0EE;
|
||||
scrollbar-darkshadow-color: #DDDDDD;
|
||||
scrollbar-face-color: #E0E0DD;
|
||||
scrollbar-highlight-color: #F0F0EE;
|
||||
scrollbar-shadow-color: #F0F0EE;
|
||||
scrollbar-track-color: #F5F5F5;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #3c3c3c;
|
||||
font-weight: normal;
|
||||
font-size: 2em;
|
||||
line-height: 1.4em;
|
||||
letter-spacing: 1px;
|
||||
color: #3c3c3c;
|
||||
font-weight: normal;
|
||||
font-size: 2em;
|
||||
line-height: 1.4em;
|
||||
letter-spacing: 1px;
|
||||
margin: 0 0 1.416em 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #646464;
|
||||
font-weight: normal;
|
||||
font-size: 1.2em;
|
||||
line-height: 1.2em;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 15px;
|
||||
text-transform: uppercase;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #646464;
|
||||
font-weight: normal;
|
||||
font-size: 1.2em;
|
||||
line-height: 1.2em;
|
||||
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;
|
||||
font-weight: 600;
|
||||
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;
|
||||
margin-bottom: 1.416em;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em !important;
|
||||
color: #3c3c3c;
|
||||
}
|
||||
|
||||
em, i {
|
||||
font-style: italic;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
strong, b {
|
||||
font-style: bold;
|
||||
font-style: bold;
|
||||
}
|
||||
|
||||
p + p, ul + p, ol + p {
|
||||
margin-top: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
margin: 1em 0;
|
||||
padding: 0 0 0 1em;
|
||||
margin: 1em 0;
|
||||
padding: 0 0 0 1em;
|
||||
color: #3c3c3c;
|
||||
|
||||
}
|
||||
|
||||
ol li, ul li {
|
||||
margin-bottom: 0.708em;
|
||||
margin-bottom: 0.708em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: decimal outside none;
|
||||
list-style: decimal outside none;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: disc outside none;
|
||||
list-style: disc outside none;
|
||||
}
|
||||
|
||||
a, a:link, a:visited, a:hover, a:active {
|
||||
color: #1d9dd9;
|
||||
}
|
||||
color: #1d9dd9;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
color: #3c3c3c;
|
||||
font-family: monospace, serif;
|
||||
font-size: 1em;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: monospace, serif;
|
||||
background: none;
|
||||
}
|
||||
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 {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
.header {
|
||||
padding: 6px 14px;
|
||||
border-bottom: 1px solid $mediumGrey;
|
||||
border-radius: 2px 2px 0 0;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<div class="unit-settings window">
|
||||
<h4>Page Settings</h4>
|
||||
<h4 class="header">Page Settings</h4>
|
||||
<div class="window-contents">
|
||||
<div class="row visibility">
|
||||
<label class="inline-label">Visibility:</label>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<article class="subsection-body window" data-id="${subsection.location}">
|
||||
<div class="subsection-name-input">
|
||||
<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>
|
||||
<label>Format:</label>
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
<div class="sidebar">
|
||||
<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="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>
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
<div class="sidebar">
|
||||
<div class="unit-settings window">
|
||||
<h4>Unit Settings</h4>
|
||||
<h4 class="header">Unit Settings</h4>
|
||||
<div class="window-contents">
|
||||
<div class="row visibility">
|
||||
<label class="inline-label">Visibility:</label>
|
||||
@@ -126,7 +126,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="window unit-location">
|
||||
<h4>Unit Location</h4>
|
||||
<h4 class="header">Unit Location</h4>
|
||||
<div class="window-contents">
|
||||
<div><input type="text" class="url" value="/courseware/${section.url_name}/${subsection.url_name}" disabled /></div>
|
||||
<ol>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
%if markdown != '' or data == '<problem>\n</problem>\n':
|
||||
<div class="editor-bar">
|
||||
<ul class="format-buttons">
|
||||
<li><a href="#" class="header-button" data-tooltip="Header"><span
|
||||
class="problem-editor-icon header"></span></a></li>
|
||||
<li><a href="#" class="header-button" data-tooltip="Heading 1"><span
|
||||
class="problem-editor-icon heading1"></span></a></li>
|
||||
<li><a href="#" class="multiple-choice-button" data-tooltip="Multiple Choice"><span
|
||||
class="problem-editor-icon multiple-choice"></span></a></li>
|
||||
<li><a href="#" class="checks-button" data-tooltip="Check Multiple"><span
|
||||
@@ -34,8 +34,8 @@
|
||||
<article class="simple-editor-cheatsheet">
|
||||
<div class="cheatsheet-wrapper">
|
||||
<div class="row">
|
||||
<h6>Header</h6>
|
||||
<div class="col sample header">
|
||||
<h6>Heading 1</h6>
|
||||
<div class="col sample heading-1">
|
||||
<img src="/static/img/header-example.png" />
|
||||
</div>
|
||||
<div class="col">
|
||||
|
||||
123
common/lib/xmodule/xmodule/css/html/display.scss
Normal file
123
common/lib/xmodule/xmodule/css/html/display.scss
Normal file
@@ -0,0 +1,123 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// HTML component editor:
|
||||
.html-editor {
|
||||
@include clearfix();
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
background: url(../img/problem-editor-icons.png) no-repeat;
|
||||
}
|
||||
|
||||
.problem-editor-icon.header {
|
||||
.problem-editor-icon.heading1 {
|
||||
width: 18px;
|
||||
background-position: -265px 0;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ class HtmlModule(XModule):
|
||||
]
|
||||
}
|
||||
js_module_name = "HTMLModule"
|
||||
|
||||
css = {'scss': [resource_string(__name__, 'css/html/display.scss')]}
|
||||
|
||||
def get_html(self):
|
||||
return self.html
|
||||
|
||||
|
||||
@@ -22,15 +22,24 @@ class @HTMLEditingDescriptor
|
||||
schema: "html5",
|
||||
# TODO: we should share this CSS with studio (and LMS)
|
||||
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
|
||||
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_align : "left",
|
||||
theme_advanced_statusbar_location : "none",
|
||||
theme_advanced_resizing : true,
|
||||
theme_advanced_blockformats : "p,code,h2,h3,blockquote",
|
||||
theme_advanced_blockformats : "p,pre,h1,h2,h3",
|
||||
width: '100%',
|
||||
height: '400px',
|
||||
setup : HTMLEditingDescriptor.setupTinyMCE,
|
||||
# Cannot get access to tinyMCE Editor instance (for focusing) until after it is rendered.
|
||||
# The tinyMCE callback passes in the editor as a paramter.
|
||||
init_instance_callback: @focusVisualEditor
|
||||
@@ -39,13 +48,25 @@ class @HTMLEditingDescriptor
|
||||
@showingVisualEditor = true
|
||||
@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)=>
|
||||
e.preventDefault();
|
||||
|
||||
if not $(e.currentTarget).hasClass('current')
|
||||
$('.editor-tabs .current').removeClass('current')
|
||||
$('.editor-tabs .current', @element).removeClass('current')
|
||||
$(e.currentTarget).addClass('current')
|
||||
$('table.mceToolbar').toggleClass(HTMLEditingDescriptor.isInactiveClass)
|
||||
$('table.mceToolbar', @element).toggleClass(HTMLEditingDescriptor.isInactiveClass)
|
||||
$(@advanced_editor.getWrapperElement()).toggleClass(HTMLEditingDescriptor.isInactiveClass)
|
||||
|
||||
visualEditor = @getVisualEditor()
|
||||
|
||||
@@ -73,7 +73,7 @@ class DraftModuleStore(ModuleStoreBase):
|
||||
except ItemNotFoundError:
|
||||
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
|
||||
that match location. Any element of location that is None is treated
|
||||
@@ -89,8 +89,8 @@ class DraftModuleStore(ModuleStoreBase):
|
||||
draft_loc = as_draft(location)
|
||||
|
||||
# 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)
|
||||
items = super(DraftModuleStore, self).get_items(location, depth=0)
|
||||
draft_items = super(DraftModuleStore, self).get_items(draft_loc, course_id=course_id, 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)
|
||||
non_draft_items = [
|
||||
|
||||
@@ -137,9 +137,6 @@ def import_from_xml(store, data_dir, course_dirs=None,
|
||||
|
||||
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
|
||||
# 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 -
|
||||
|
||||
BIN
common/static/images/ico-tinymce-code.png
Normal file
BIN
common/static/images/ico-tinymce-code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 553 B |
@@ -1,5 +1,6 @@
|
||||
<%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-ui.min.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
|
||||
rake test_lms[false] || TESTS_FAILED=1
|
||||
rake test_common/lib/capa || 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_common/lib/xmodule || TESTS_FAILED=1
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ class Command(BaseCommand):
|
||||
This command does not do anything other than report the current
|
||||
certificate status.
|
||||
|
||||
unavailable - A student is not eligible for a certificate.
|
||||
generating - A request has been made to generate a certificate,
|
||||
but it has not been generated yet.
|
||||
regenerating - A request has been made to regenerate a certificate,
|
||||
@@ -64,11 +63,7 @@ class Command(BaseCommand):
|
||||
enrolled_students = User.objects.filter(
|
||||
courseenrollment__course_id=course_id).prefetch_related(
|
||||
"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].update({'unavailable': unavailable_count})
|
||||
|
||||
tallies = GeneratedCertificate.objects.filter(
|
||||
course_id__exact=course_id).values('status').annotate(
|
||||
|
||||
@@ -23,26 +23,37 @@ class Command(BaseCommand):
|
||||
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('-n', '--noop',
|
||||
action='store_true',
|
||||
dest='noop',
|
||||
default=False,
|
||||
help="Don't add certificate requests to the queue"),
|
||||
action='store_true',
|
||||
dest='noop',
|
||||
default=False,
|
||||
help="Don't add certificate requests to the queue"),
|
||||
make_option('-c', '--course',
|
||||
metavar='COURSE_ID',
|
||||
dest='course',
|
||||
default=False,
|
||||
help='Grade and generate certificates for a specific course'),
|
||||
metavar='COURSE_ID',
|
||||
dest='course',
|
||||
default=False,
|
||||
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):
|
||||
|
||||
# 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 = [
|
||||
CertificateStatuses.unavailable
|
||||
]
|
||||
if options['force']:
|
||||
valid_statuses = getattr(CertificateStatuses, options['force'])
|
||||
else:
|
||||
valid_statuses = [CertificateStatuses.unavailable]
|
||||
|
||||
# Print update after this many students
|
||||
|
||||
@@ -54,8 +65,8 @@ class Command(BaseCommand):
|
||||
# Find all courses that have ended
|
||||
ended_courses = []
|
||||
for course_id in [course # all courses in COURSE_LISTINGS
|
||||
for sub in settings.COURSE_LISTINGS
|
||||
for course in settings.COURSE_LISTINGS[sub]]:
|
||||
for sub in settings.COURSE_LISTINGS
|
||||
for course in settings.COURSE_LISTINGS[sub]]:
|
||||
course_loc = CourseDescriptor.id_to_location(course_id)
|
||||
course = modulestore().get_instance(course_id, course_loc)
|
||||
if course.has_ended():
|
||||
@@ -64,8 +75,8 @@ class Command(BaseCommand):
|
||||
for course_id in ended_courses:
|
||||
print "Fetching enrolled students for {0}".format(course_id)
|
||||
enrolled_students = User.objects.filter(
|
||||
courseenrollment__course_id=course_id).prefetch_related(
|
||||
"groups").order_by('username')
|
||||
courseenrollment__course_id=course_id).prefetch_related(
|
||||
"groups").order_by('username')
|
||||
xq = XQueueCertInterface()
|
||||
total = enrolled_students.count()
|
||||
count = 0
|
||||
@@ -81,11 +92,11 @@ class Command(BaseCommand):
|
||||
hours, remainder = divmod(timeleft.seconds, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
print "{0}/{1} completed ~{2:02}:{3:02}m remaining".format(
|
||||
count, total, hours, minutes)
|
||||
count, total, hours, minutes)
|
||||
start = datetime.datetime.now()
|
||||
|
||||
if certificate_status_for_student(
|
||||
student, course_id)['status'] in VALID_STATUSES:
|
||||
student, course_id)['status'] in valid_statuses:
|
||||
if not options['noop']:
|
||||
# Add the certificate request to the queue
|
||||
ret = xq.add_cert(student, course_id)
|
||||
|
||||
@@ -192,7 +192,7 @@ class XQueueCertInterface(object):
|
||||
Will change the certificate status to 'deleting'.
|
||||
|
||||
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
|
||||
for a new cert
|
||||
@@ -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]
|
||||
|
||||
cert_status = certificate_status_for_student(
|
||||
|
||||
@@ -15,6 +15,8 @@ $monospace: Monaco, 'Bitstream Vera Sans Mono', 'Lucida Console', monospace;
|
||||
$body-font-size: em(14);
|
||||
$body-line-height: golden-ratio(.875em, 1);
|
||||
$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);
|
||||
|
||||
$blue: rgb(29,157,217);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
${module_content}
|
||||
%if edit_link:
|
||||
<div>
|
||||
<a href="${edit_link}">Edit</a> /
|
||||
<a href="${edit_link}">Edit</a> /
|
||||
<a href="#${element_id}_xqa-modal" onclick="javascript:getlog('${element_id}', {
|
||||
'location': '${location}',
|
||||
'xqa_key': '${xqa_key}',
|
||||
@@ -61,18 +61,16 @@ category = ${category | h}
|
||||
|
||||
<script type="text/javascript">
|
||||
// assumes courseware.html's loaded this method.
|
||||
% if staff_access:
|
||||
setup_debug('${element_id}',
|
||||
%if edit_link:
|
||||
'${edit_link}',
|
||||
%else:
|
||||
null,
|
||||
%endif
|
||||
{
|
||||
'location': '${location}',
|
||||
'xqa_key': '${xqa_key}',
|
||||
'category': '${category}',
|
||||
'user': '${user}'
|
||||
});
|
||||
% endif
|
||||
setup_debug('${element_id}',
|
||||
%if edit_link:
|
||||
'${edit_link}',
|
||||
%else:
|
||||
null,
|
||||
%endif
|
||||
{
|
||||
'location': '${location}',
|
||||
'xqa_key': '${xqa_key}',
|
||||
'category': '${category}',
|
||||
'user': '${user}'
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user