Changed GET to POST and xmodule HTML editor call, section CSS
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -89,3 +89,4 @@ Akshay Jagadeesh <akjags@gmail.com>
|
|||||||
Nick Parlante <nick.parlante@cs.stanford.edu>
|
Nick Parlante <nick.parlante@cs.stanford.edu>
|
||||||
Marko Seric <marko.seric@math.uzh.ch>
|
Marko Seric <marko.seric@math.uzh.ch>
|
||||||
Felipe Montoya <felipe.montoya@edunext.co>
|
Felipe Montoya <felipe.montoya@edunext.co>
|
||||||
|
Julia Hansbrough <julia@edx.org>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ the top. Include a label indicating the component affected.
|
|||||||
|
|
||||||
LMS: Disable data download buttons on the instructor dashboard for large courses
|
LMS: Disable data download buttons on the instructor dashboard for large courses
|
||||||
|
|
||||||
|
LMS: Ported bulk emailing to the beta instructor dashboard.
|
||||||
|
|
||||||
LMS: Refactor and clean student dashboard templates.
|
LMS: Refactor and clean student dashboard templates.
|
||||||
|
|
||||||
LMS: Fix issue with CourseMode expiration dates
|
LMS: Fix issue with CourseMode expiration dates
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ class TestInstructorDashboardEmailView(ModuleStoreTestCase):
|
|||||||
|
|
||||||
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
|
@patch.dict(settings.MITX_FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True})
|
||||||
def test_email_flag_true(self):
|
def test_email_flag_true(self):
|
||||||
from nose.tools import set_trace; set_trace()
|
|
||||||
# Assert that the URL for the email view is in the response
|
# Assert that the URL for the email view is in the response
|
||||||
response = self.client.get(self.url)
|
response = self.client.get(self.url)
|
||||||
self.assertTrue(self.email_link in response.content)
|
self.assertTrue(self.email_link in response.content)
|
||||||
|
|||||||
@@ -106,6 +106,43 @@ def require_query_params(*args, **kwargs):
|
|||||||
return wrapped
|
return wrapped
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
def require_post_params(*args, **kwargs):
|
||||||
|
"""
|
||||||
|
Checks for required paremters or renders a 400 error.
|
||||||
|
(decorator with arguments)
|
||||||
|
|
||||||
|
`args` is a *list of required GET parameter names.
|
||||||
|
`kwargs` is a **dict of required GET parameter names
|
||||||
|
to string explanations of the parameter
|
||||||
|
"""
|
||||||
|
required_params = []
|
||||||
|
required_params += [(arg, None) for arg in args]
|
||||||
|
required_params += [(key, kwargs[key]) for key in kwargs]
|
||||||
|
# required_params = e.g. [('action', 'enroll or unenroll'), ['emails', None]]
|
||||||
|
|
||||||
|
def decorator(func): # pylint: disable=C0111
|
||||||
|
def wrapped(*args, **kwargs): # pylint: disable=C0111
|
||||||
|
request = args[0]
|
||||||
|
|
||||||
|
error_response_data = {
|
||||||
|
'error': 'Missing required query parameter(s)',
|
||||||
|
'parameters': [],
|
||||||
|
'info': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
for (param, extra) in required_params:
|
||||||
|
default = object()
|
||||||
|
if request.POST.get(param, default) == default:
|
||||||
|
error_response_data['parameters'] += [param]
|
||||||
|
error_response_data['info'][param] = extra
|
||||||
|
|
||||||
|
if len(error_response_data['parameters']) > 0:
|
||||||
|
return JsonResponse(error_response_data, status=400)
|
||||||
|
else:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
return wrapped
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def require_level(level):
|
def require_level(level):
|
||||||
"""
|
"""
|
||||||
@@ -749,19 +786,19 @@ def send_email(request, course_id):
|
|||||||
@ensure_csrf_cookie
|
@ensure_csrf_cookie
|
||||||
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
|
||||||
@require_level('staff')
|
@require_level('staff')
|
||||||
@require_query_params(send_to="sending to whom", subject="subject line", message="message text")
|
@require_post_params(send_to="sending to whom", subject="subject line", message="message text")
|
||||||
def send_email(request, course_id):
|
def send_email(request, course_id):
|
||||||
"""
|
"""
|
||||||
Send an email to self, staff, or everyone involved in a course.
|
Send an email to self, staff, or everyone involved in a course.
|
||||||
Query Paramaters:
|
Query Parameters:
|
||||||
- 'send_to' specifies what group the email should be sent to
|
- 'send_to' specifies what group the email should be sent to
|
||||||
- 'subject' specifies email's subject
|
- 'subject' specifies email's subject
|
||||||
- 'message' specifies email's content
|
- 'message' specifies email's content
|
||||||
"""
|
"""
|
||||||
course = get_course_by_id(course_id)
|
course = get_course_by_id(course_id)
|
||||||
send_to = request.GET.get("send_to")
|
send_to = request.POST.get("send_to")
|
||||||
subject = request.GET.get("subject")
|
subject = request.POST.get("subject")
|
||||||
message = request.GET.get("message")
|
message = request.POST.get("message")
|
||||||
text_message = html_to_text(message)
|
text_message = html_to_text(message)
|
||||||
email = CourseEmail(
|
email = CourseEmail(
|
||||||
course_id=course_id,
|
course_id=course_id,
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ def _section_student_admin(course_id, access):
|
|||||||
'section_display_name': _('Student Admin'),
|
'section_display_name': _('Student Admin'),
|
||||||
'access': access,
|
'access': access,
|
||||||
'get_student_progress_url_url': reverse('get_student_progress_url', kwargs={'course_id': course_id}),
|
'get_student_progress_url_url': reverse('get_student_progress_url', kwargs={'course_id': course_id}),
|
||||||
|
'enrollment_url': reverse('students_update_enrollment', kwargs={'course_id': course_id}),
|
||||||
'reset_student_attempts_url': reverse('reset_student_attempts', kwargs={'course_id': course_id}),
|
'reset_student_attempts_url': reverse('reset_student_attempts', kwargs={'course_id': course_id}),
|
||||||
'rescore_problem_url': reverse('rescore_problem', kwargs={'course_id': course_id}),
|
'rescore_problem_url': reverse('rescore_problem', kwargs={'course_id': course_id}),
|
||||||
'list_instructor_tasks_url': reverse('list_instructor_tasks', kwargs={'course_id': course_id}),
|
'list_instructor_tasks_url': reverse('list_instructor_tasks', kwargs={'course_id': course_id}),
|
||||||
@@ -160,12 +161,15 @@ def _section_data_download(course_id):
|
|||||||
def _section_send_email(course_id, access, course):
|
def _section_send_email(course_id, access, course):
|
||||||
""" Provide data for the corresponding bulk email section """
|
""" Provide data for the corresponding bulk email section """
|
||||||
html_module = HtmlDescriptor(course.system, DictFieldData({'data': ''}), ScopeIds(None, None, None, None))
|
html_module = HtmlDescriptor(course.system, DictFieldData({'data': ''}), ScopeIds(None, None, None, None))
|
||||||
|
fragment = course.system.render(html_module, None, 'studio_view')
|
||||||
|
fragment = wrap_xmodule('xmodule_edit.html', html_module, 'studio_view', fragment, None)
|
||||||
|
email_editor = fragment.content
|
||||||
section_data = {
|
section_data = {
|
||||||
'section_key': 'send_email',
|
'section_key': 'send_email',
|
||||||
'section_display_name': _('Email'),
|
'section_display_name': _('Email'),
|
||||||
'access': access,
|
'access': access,
|
||||||
'send_email': reverse('send_email',kwargs={'course_id': course_id}),
|
'send_email': reverse('send_email',kwargs={'course_id': course_id}),
|
||||||
'editor': wrap_xmodule(html_module.get_html, html_module, 'xmodule_edit.html')()
|
'editor': email_editor
|
||||||
}
|
}
|
||||||
return section_data
|
return section_data
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD'] = True
|
|||||||
MITX_FEATURES['ENABLE_PSYCHOMETRICS'] = False # real-time psychometrics (eg item response theory analysis in instructor dashboard)
|
MITX_FEATURES['ENABLE_PSYCHOMETRICS'] = False # real-time psychometrics (eg item response theory analysis in instructor dashboard)
|
||||||
MITX_FEATURES['ENABLE_INSTRUCTOR_ANALYTICS'] = True
|
MITX_FEATURES['ENABLE_INSTRUCTOR_ANALYTICS'] = True
|
||||||
MITX_FEATURES['ENABLE_SERVICE_STATUS'] = True
|
MITX_FEATURES['ENABLE_SERVICE_STATUS'] = True
|
||||||
|
MITX_FEATURES['ENABLE_INSTRUCTOR_EMAIL'] = True
|
||||||
MITX_FEATURES['ENABLE_HINTER_INSTRUCTOR_VIEW'] = True
|
MITX_FEATURES['ENABLE_HINTER_INSTRUCTOR_VIEW'] = True
|
||||||
MITX_FEATURES['ENABLE_INSTRUCTOR_BETA_DASHBOARD'] = True
|
MITX_FEATURES['ENABLE_INSTRUCTOR_BETA_DASHBOARD'] = True
|
||||||
MITX_FEATURES['MULTIPLE_ENROLLMENT_ROLES'] = True
|
MITX_FEATURES['MULTIPLE_ENROLLMENT_ROLES'] = True
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ class SendEmail
|
|||||||
# attach click handlers
|
# attach click handlers
|
||||||
|
|
||||||
@$btn_send.click =>
|
@$btn_send.click =>
|
||||||
|
|
||||||
|
success_message = gettext('Your email was successfully queued for sending.')
|
||||||
|
|
||||||
send_data =
|
send_data =
|
||||||
action: 'send'
|
action: 'send'
|
||||||
@@ -30,10 +32,11 @@ class SendEmail
|
|||||||
message: @$emailEditor.save()['data']
|
message: @$emailEditor.save()['data']
|
||||||
|
|
||||||
$.ajax
|
$.ajax
|
||||||
|
type: 'POST'
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
url: @$btn_send.data 'endpoint'
|
url: @$btn_send.data 'endpoint'
|
||||||
data: send_data
|
data: send_data
|
||||||
success: (data) => @display_response gettext('Your email was successfully queued for sending.')
|
success: (data) => @display_response ("<div class=\"msg msg-confirm\"><p class=\"copy\">" + success_message + "</p></div>")
|
||||||
error: std_ajax_err => @fail_with_error gettext('Error sending email.')
|
error: std_ajax_err => @fail_with_error gettext('Error sending email.')
|
||||||
|
|
||||||
fail_with_error: (msg) ->
|
fail_with_error: (msg) ->
|
||||||
|
|||||||
@@ -241,6 +241,60 @@ section.instructor-dashboard-content-2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instructor-dashboard-wrapper-2 section.idash-section#send_email {
|
||||||
|
// form fields
|
||||||
|
.list-fields {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.field {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// system feedback - messages
|
||||||
|
.msg {
|
||||||
|
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg-confirm {
|
||||||
|
background: tint(green,90%);
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-advice {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 20px 0;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.msg .copy {
|
||||||
|
font-weight: 600; }
|
||||||
|
.msg-confirm {
|
||||||
|
background: #e5f2e5; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.instructor-dashboard-wrapper-2 section.idash-section#membership {
|
.instructor-dashboard-wrapper-2 section.idash-section#membership {
|
||||||
$half_width: $baseline * 20;
|
$half_width: $baseline * 20;
|
||||||
@@ -538,3 +592,7 @@ section.instructor-dashboard-content-2 {
|
|||||||
right: $baseline;
|
right: $baseline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[name="subject"] {
|
||||||
|
width:600px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,38 +6,44 @@
|
|||||||
<script type="text/javascript" src="jsi18n/"></script>
|
<script type="text/javascript" src="jsi18n/"></script>
|
||||||
<div class="vert-left send-email">
|
<div class="vert-left send-email">
|
||||||
<h2> ${_("Send Email")} </h2>
|
<h2> ${_("Send Email")} </h2>
|
||||||
<label for="id_to">${_("Send to:")}</label>
|
<div class="request-response msg msg-confirm"></div>
|
||||||
<select id="id_to" name="send_to">
|
<ul class="list-fields">
|
||||||
<option value="myself">${_("Myself")}</option>
|
<li class="field">
|
||||||
%if to_option == "staff":
|
<label for="id_to">${_("Send to:")}</label><br/>
|
||||||
<option value="staff" selected="selected">${_("Staff and instructors")}</option>
|
<select id="id_to" name="send_to">
|
||||||
%else:
|
<option value="myself">${_("Myself")}</option>
|
||||||
<option value="staff">${_("Staff and instructors")}</option>
|
%if to_option == "staff":
|
||||||
%endif
|
<option value="staff" selected="selected">${_("Staff and instructors")}</option>
|
||||||
%if to_option == "all":
|
%else:
|
||||||
<option value="all" selected="selected">${_("All (students, staff and instructors)")}</option>
|
<option value="staff">${_("Staff and instructors")}</option>
|
||||||
%else:
|
%endif
|
||||||
|
%if to_option == "all":
|
||||||
|
<option value="all" selected="selected">${_("All (students, staff and instructors)")}</option>
|
||||||
|
%else:
|
||||||
<option value="all">${_("All (students, staff and instructors)")}</option>
|
<option value="all">${_("All (students, staff and instructors)")}</option>
|
||||||
%endif
|
%endif
|
||||||
</select>
|
</select>
|
||||||
<br/>
|
</li>
|
||||||
<label for="id_subject">${_("Subject: ")}</label>
|
|
||||||
<input type="text" id="id_subject" name="subject">
|
|
||||||
<br/>
|
|
||||||
<label>Message:</label>
|
|
||||||
<div class="email-editor">
|
|
||||||
${ section_data['editor'] }
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="message" value="">
|
|
||||||
<br/>
|
<br/>
|
||||||
|
<li class="field">
|
||||||
|
<label for="id_subject">${_("Subject: ")}</label><br/>
|
||||||
|
<input type="text" id="id_subject" name="subject">
|
||||||
|
</li>
|
||||||
|
<li class="field">
|
||||||
|
<label>Message:</label>
|
||||||
|
<div class="email-editor">
|
||||||
|
${ section_data['editor'] }
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="message" value="">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<div class="submit-email-action">
|
<div class="submit-email-action">
|
||||||
${_("Please try not to email students more than once a day. Before sending your email, consider:")}
|
${_("Please try not to email students more than once a day. Before sending your email, consider:")}
|
||||||
<ul>
|
<ul class="list-advice">
|
||||||
<li class="item">${_("Have you read over the email to make sure it says everything you want to say?")}</li>
|
<li class="item">${_("Have you read over the email to make sure it says everything you want to say?")}</li>
|
||||||
<li class="item">${_("Have you sent the email to yourself first to make sure you're happy with how it's displayed?")}</li>
|
<li class="item">${_("Have you sent the email to yourself first to make sure you're happy with how it's displayed?")}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<input type="button" name="send" value="${_("Send")}" data-endpoint="${ section_data['send_email'] }" >
|
<input type="button" name="send" value="${_("Send Email")}" data-endpoint="${ section_data['send_email'] }" >
|
||||||
<div class="request-response"></div>
|
|
||||||
<div class="request-response-error"></div>
|
<div class="request-response-error"></div>
|
||||||
</div>
|
</div>
|
||||||
Reference in New Issue
Block a user