Commit d3a86a20 by Sef Kloninger

Merge branch 'feature/kluo/bulk-email-squashed' into edx-west/release-candidate-20130729

Conflicts:
	lms/static/sass/base/_variables.scss
parents 455552ca 4cc758da
...@@ -19,7 +19,7 @@ def i_see_only_the_settings_and_values(step): ...@@ -19,7 +19,7 @@ def i_see_only_the_settings_and_values(step):
world.verify_all_setting_entries( world.verify_all_setting_entries(
[ [
['Category', "Week 1", False], ['Category', "Week 1", False],
['Display Name', "Discussion Tag", False], ['Display Name', "Discussion", False],
['Subcategory', "Topic-Level Student-Visible Label", False] ['Subcategory', "Topic-Level Student-Visible Label", False]
]) ])
......
...@@ -37,6 +37,19 @@ def delegate_email_batches(hash_for_msg, recipient, course_id, course_url, user_ ...@@ -37,6 +37,19 @@ def delegate_email_batches(hash_for_msg, recipient, course_id, course_url, user_
log.error("get_course_by_id failed: " + exc.args[0]) log.error("get_course_by_id failed: " + exc.args[0])
raise Exception("get_course_by_id failed: " + exc.args[0]) raise Exception("get_course_by_id failed: " + exc.args[0])
email = None
retries = 0
while email is None:
try:
email = CourseEmail.objects.get(hash=hash_for_msg)
except CourseEmail.DoesNotExist as exc:
if retries < 3:
retries += 1
time.sleep(5)
else:
log.error("Failed to get CourseEmail with hash " + hash_for_msg + ", no workers fired.")
return 0
if recipient == "myself": if recipient == "myself":
recipient_qset = User.objects.filter(id=user_id).values('profile__name', 'email') recipient_qset = User.objects.filter(id=user_id).values('profile__name', 'email')
else: else:
......
...@@ -22,9 +22,11 @@ from django.views.decorators.cache import cache_control ...@@ -22,9 +22,11 @@ from django.views.decorators.cache import cache_control
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.mail import send_mail from django.core.mail import send_mail
from xmodule_modifiers import wrap_xmodule
import xmodule.graders as xmgraders import xmodule.graders as xmgraders
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.html_module import HtmlDescriptor
from courseware import grades from courseware import grades
from courseware.access import (has_access, get_access_group_name, from courseware.access import (has_access, get_access_group_name,
...@@ -82,7 +84,7 @@ def instructor_dashboard(request, course_id): ...@@ -82,7 +84,7 @@ def instructor_dashboard(request, course_id):
msg = '' msg = ''
to = None to = None
subject = None subject = None
html_message = None html_message = ''
problems = [] problems = []
plots = [] plots = []
datatable = {} datatable = {}
...@@ -749,6 +751,13 @@ s (~10k), it may take 1-2 hours to send all emails.</font>" ...@@ -749,6 +751,13 @@ s (~10k), it may take 1-2 hours to send all emails.</font>"
else: else:
instructor_tasks = None instructor_tasks = None
# HTML editor for email
if idash_mode == 'Email':
html_module = HtmlDescriptor(course.system, {'data': html_message})
editor = wrap_xmodule(html_module.get_html, html_module, 'xmodule_edit.html')()
else:
editor = None
# display course stats only if there is no other table to display: # display course stats only if there is no other table to display:
course_stats = None course_stats = None
if not datatable: if not datatable:
...@@ -765,9 +774,9 @@ s (~10k), it may take 1-2 hours to send all emails.</font>" ...@@ -765,9 +774,9 @@ s (~10k), it may take 1-2 hours to send all emails.</font>"
'course_stats': course_stats, 'course_stats': course_stats,
'msg': msg, 'msg': msg,
'modeflag': {idash_mode: 'selectedmode'}, 'modeflag': {idash_mode: 'selectedmode'},
'to': to, # email 'to': to, # email
'subject': subject, # email 'subject': subject, # email
'message': html_message, # email 'editor': editor, # email
'problems': problems, # psychometrics 'problems': problems, # psychometrics
'plots': plots, # psychometrics 'plots': plots, # psychometrics
'course_errors': modulestore().get_item_errors(course.location), 'course_errors': modulestore().get_item_errors(course.location),
......
...@@ -596,6 +596,11 @@ PIPELINE_JS = { ...@@ -596,6 +596,11 @@ PIPELINE_JS = {
'output_filename': 'js/lms-main_vendor.js', 'output_filename': 'js/lms-main_vendor.js',
'test_order': 0, 'test_order': 0,
}, },
'module-descriptor-js': {
'source_filenames': rooted_glob(COMMON_ROOT / 'static/', 'xmodule/descriptors/js/*.js'),
'output_filename': 'js/lms-module-descriptors.js',
'test_order': 8,
},
'module-js': { 'module-js': {
'source_filenames': rooted_glob(COMMON_ROOT / 'static', 'xmodule/modules/js/*.js'), 'source_filenames': rooted_glob(COMMON_ROOT / 'static', 'xmodule/modules/js/*.js'),
'output_filename': 'js/lms-modules.js', 'output_filename': 'js/lms-modules.js',
......
...@@ -39,6 +39,23 @@ $outer-border-color: rgb(170, 170, 170); ...@@ -39,6 +39,23 @@ $outer-border-color: rgb(170, 170, 170);
$light-gray: #ddd; $light-gray: #ddd;
$dark-gray: #333; $dark-gray: #333;
// used by descriptor css
$lightGrey: #edf1f5;
$darkGrey: #8891a1;
// edx.org-related
$m-gray-l1: rgb(203,203,203);
$m-gray-l2: rgb(246,246,246);
$m-gray: rgb(153,153,153);
$m-gray-d1: rgb(102,102,102);
$m-gray-d2: rgb(51,51,51);
$m-gray-a1: rgb(80,80,80);
$m-blue: rgb(65, 116, 170);
// $m-blue: rgb(85, 151, 221); (used in marketing redesign)
$m-blue-l1: rgb(85, 151, 221);
$m-blue-d1: shade($m-blue,15%);
$m-blue-s1: saturate($m-blue,15%);
$m-pink: rgb(204,51,102);
// edx.org marketing site variables // edx.org marketing site variables
$m-gray: #8A8C8F; $m-gray: #8A8C8F;
$m-gray-l1: #97999B; $m-gray-l1: #97999B;
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
// instructor // instructor
@import "course/instructor/instructor"; @import "course/instructor/instructor";
@import "course/instructor/email"; @import "course/instructor/email";
@import "xmodule/descriptors/css/module-styles.scss";
// discussion // discussion
@import "course/discussion/form-wmd-toolbar"; @import "course/discussion/form-wmd-toolbar";
.email-editor {
border: 1px solid #c8c8c8;
}
.xmodule_edit {
ul {
margin: 0;
padding: 0;
margin-bottom: 10px;
list-style: none;
}
a {
line-height: (16*1.48) + px;
line-height: 1.48rem;
}
}
.submit-email-action { .submit-email-action {
margin-top: 10px; margin-top: 10px;
line-height: 1.3; line-height: 1.3;
......
...@@ -9,6 +9,12 @@ ...@@ -9,6 +9,12 @@
<script type="text/javascript" src="${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-1.1.1.min.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-1.1.1.min.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-world-mill-en.js')}"></script> <script type="text/javascript" src="${static.url('js/vendor/jquery-jvectormap-1.1.1/jquery-jvectormap-world-mill-en.js')}"></script>
<script type="text/javascript" src="${static.url('js/course_groups/cohorts.js')}"></script> <script type="text/javascript" src="${static.url('js/course_groups/cohorts.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/codemirror-compressed.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/tiny_mce/tiny_mce.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/tiny_mce/jquery.tinymce.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/CodeMirror/htmlmixed.js')}"></script>
<script type="text/javascript" src="${static.url('js/vendor/CodeMirror/css.js')}"></script>
<%static:js group='module-descriptor-js'/>
%if instructor_tasks is not None: %if instructor_tasks is not None:
<script type="text/javascript" src="${static.url('js/pending_tasks.js')}"></script> <script type="text/javascript" src="${static.url('js/pending_tasks.js')}"></script>
%endif %endif
...@@ -457,12 +463,11 @@ function goto( mode) ...@@ -457,12 +463,11 @@ function goto( mode)
%else: %else:
<input type="text" id="id_subject" name="subject" maxlength="100" size="75"> <input type="text" id="id_subject" name="subject" maxlength="100" size="75">
%endif %endif
<label for="id_message">Message:</label> <label>Message:</label>
%if message: <div class="email-editor">
<textarea cols="100" id="id_message" name="message">${message}</textarea> ${editor}
%else: </div>
<textarea cols="100" id="id_message" name="message"></textarea> <input type="hidden" name="message" value="">
%endif
</p> </p>
<div class="submit-email-action"> <div class="submit-email-action">
Please try not to email students more than once a day. Important things to consider before sending: Please try not to email students more than once a day. Important things to consider before sending:
...@@ -472,6 +477,13 @@ function goto( mode) ...@@ -472,6 +477,13 @@ function goto( mode)
</ul> </ul>
<input type="submit" name="action" value="Send email"> <input type="submit" name="action" value="Send email">
</div> </div>
<script type="text/javascript">
var emailEditor = XModule.loadModule($('.xmodule_edit'));
document.idashform.onsubmit = function() {
this.message.value = emailEditor.save()['data'];
return true;
}
</script>
%endif %endif
</form> </form>
......
<%! from django.utils.translation import ugettext as _ %>
<section class="html-editor editor">
<ul class="editor-tabs">
<li><a href="#" class="visual-tab tab current" data-tab="visual">${_("Visual")}</a></li>
<li><a href="#" class="html-tab tab" data-tab="advanced">${_("HTML")}</a></li>
</ul>
<div class="row">
<textarea class="tiny-mce">${data | h}</textarea>
<textarea name="" class="edit-box">${data | h}</textarea>
</div>
</section>
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