Commit e325317b by Julia Hansbrough

Changed GET to POST and xmodule HTML editor call, section CSS

parent 75eddb6a
...@@ -89,3 +89,4 @@ Akshay Jagadeesh <akjags@gmail.com> ...@@ -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. ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -538,3 +592,7 @@ section.instructor-dashboard-content-2 {
right: $baseline; right: $baseline;
} }
} }
input[name="subject"] {
width:600px;
}
...@@ -6,38 +6,44 @@ ...@@ -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>
\ No newline at end of file
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