894 lines
32 KiB
HTML
894 lines
32 KiB
HTML
<%! from django.utils.translation import ugettext as _ %>
|
|
<%inherit file="/main.html" />
|
|
<%! from django.core.urlresolvers import reverse %>
|
|
<%namespace name='static' file='/static_content.html'/>
|
|
|
|
<%block name="headextra">
|
|
<%static:css group='style-course-vendor'/>
|
|
<%static:css group='style-course'/>
|
|
|
|
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script>
|
|
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.axislabels.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/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>
|
|
<script type="text/javascript">
|
|
(function() {window.baseUrl = "${settings.STATIC_URL}";})(this);
|
|
</script>
|
|
<%static:js group='module-descriptor-js'/>
|
|
%if instructor_tasks is not None:
|
|
<script type="text/javascript" src="${static.url('js/pending_tasks.js')}"></script>
|
|
%endif
|
|
</%block>
|
|
|
|
<%include file="/courseware/course_navigation.html" args="active_page='instructor'" />
|
|
|
|
<style type="text/css">
|
|
table.stat_table {
|
|
font-family: verdana,arial,sans-serif;
|
|
font-size:11px;
|
|
color:#333333;
|
|
border-width: 1px;
|
|
border-color: #666666;
|
|
border-collapse: collapse;
|
|
}
|
|
table.stat_table th {
|
|
border-width: 1px;
|
|
padding: 8px;
|
|
border-style: solid;
|
|
border-color: #666666;
|
|
background-color: #dedede;
|
|
}
|
|
table.stat_table td {
|
|
border-width: 1px;
|
|
padding: 8px;
|
|
border-style: solid;
|
|
border-color: #666666;
|
|
background-color: #ffffff;
|
|
}
|
|
.divScroll {
|
|
height: 200px;
|
|
overflow: scroll;
|
|
}
|
|
|
|
a.selectedmode { background-color: yellow; }
|
|
|
|
textarea {
|
|
height: 200px;
|
|
}
|
|
|
|
.jvectormap-label {
|
|
position: absolute;
|
|
display: none;
|
|
border: solid 1px #CDCDCD;
|
|
-webkit-border-radius: 3px;
|
|
-moz-border-radius: 3px;
|
|
border-radius: 3px;
|
|
background: #292929;
|
|
color: white;
|
|
font-family: sans-serif, Verdana;
|
|
font-size: smaller;
|
|
padding: 3px;
|
|
}
|
|
|
|
.jvectormap-zoomin, .jvectormap-zoomout {
|
|
position: absolute;
|
|
left: 10px;
|
|
-webkit-border-radius: 3px;
|
|
-moz-border-radius: 3px;
|
|
border-radius: 3px;
|
|
background: #292929;
|
|
padding: 3px;
|
|
color: white;
|
|
width: 10px;
|
|
height: 10px;
|
|
cursor: pointer;
|
|
line-height: 10px;
|
|
text-align: center;
|
|
}
|
|
|
|
.jvectormap-zoomin {
|
|
top: 10px;
|
|
}
|
|
|
|
.jvectormap-zoomout {
|
|
top: 30px;
|
|
}
|
|
|
|
</style>
|
|
|
|
<script language="JavaScript" type="text/javascript">
|
|
function goto( mode)
|
|
{
|
|
document.idashform.idash_mode.value = mode;
|
|
document.idashform.submit() ;
|
|
}
|
|
</script>
|
|
|
|
<section class="container">
|
|
<div class="instructor-dashboard-wrapper">
|
|
|
|
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BETA_DASHBOARD'):
|
|
<div class="beta-button-wrapper"><a href="${ beta_dashboard_url }">${_("Try New Beta Dashboard")}</a></div>
|
|
%endif
|
|
%if studio_url:
|
|
## not checking access because if user can see this, they are at least course staff (with studio edit access)
|
|
<div class="studio-edit-link"><a href="${studio_url}" target="_blank">${_('Edit Course In Studio')}</a></div>
|
|
%endif
|
|
|
|
|
|
<section class="instructor-dashboard-content">
|
|
<h1>${_("Instructor Dashboard")}</h1>
|
|
|
|
<h2 class="navbar">[ <a href="#" onclick="goto('Grades');" class="${modeflag.get('Grades')}">Grades</a> |
|
|
%if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'):
|
|
<a href="#" onclick="goto('Psychometrics');" class="${modeflag.get('Psychometrics')}">${_("Psychometrics")}</a> |
|
|
%endif
|
|
<a href="#" onclick="goto('Admin');" class="${modeflag.get('Admin')}">${_("Admin")}</a> |
|
|
<a href="#" onclick="goto('Forum Admin');" class="${modeflag.get('Forum Admin')}">${_("Forum Admin")}</a> |
|
|
<a href="#" onclick="goto('Enrollment');" class="${modeflag.get('Enrollment')}">${_("Enrollment")}</a> |
|
|
<a href="#" onclick="goto('Data');" class="${modeflag.get('Data')}">${_("DataDump")}</a> |
|
|
<a href="#" onclick="goto('Manage Groups');" class="${modeflag.get('Manage Groups')}">${_("Manage Groups")}</a>
|
|
%if show_email_tab:
|
|
| <a href="#" onclick="goto('Email')" class="${modeflag.get('Email')}">${_("Email")}</a>
|
|
%endif
|
|
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_ANALYTICS'):
|
|
| <a href="#" onclick="goto('Analytics');" class="${modeflag.get('Analytics')}">${_("Analytics")}</a>
|
|
%endif
|
|
]
|
|
</h2>
|
|
|
|
<form name="idashform" method="POST">
|
|
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
|
|
<input type="hidden" name="idash_mode" value="">
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Grades'):
|
|
|
|
%if offline_grade_log:
|
|
<p>
|
|
<span class="copy-warning">Pre-computed grades ${offline_grade_log} available: Use?
|
|
<input type='checkbox' name='use_offline_grades' value='${_("yes")}'>
|
|
</span>
|
|
</p>
|
|
%endif
|
|
|
|
|
|
<hr width="40%" style="align:left">
|
|
<h2>${_("Grade Downloads")}</h2>
|
|
% if disable_buttons:
|
|
|
|
<div class="msg msg-warning">
|
|
|
|
<div class="copy">
|
|
<p>
|
|
${_("Note: some of these buttons are known to time out for larger "
|
|
"courses. We have temporarily disabled those features for courses "
|
|
"with more than {max_enrollment} students. We are urgently working on "
|
|
"fixing this issue. Thank you for your patience as we continue "
|
|
"working to improve the platform!").format(
|
|
max_enrollment=settings.MITX_FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
|
|
)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
<p>
|
|
<a href="${reverse('gradebook', kwargs=dict(course_id=course.id))}" class="${'is-disabled' if disable_buttons else ''}">${_("Gradebook")}</a>
|
|
</p>
|
|
|
|
<p>
|
|
<a href="${reverse('grade_summary', kwargs=dict(course_id=course.id))}" class="${'is-disabled' if disable_buttons else ''}">${_("Grade summary")}</a>
|
|
</p>
|
|
|
|
<p>
|
|
<input type="submit" name="action" value="Dump list of enrolled students" class="${'is-disabled' if disable_buttons else ''}">
|
|
</p>
|
|
|
|
<p>
|
|
<input type="submit" name="action" value="Dump Grades for all students in this course" class="${'is-disabled' if disable_buttons else ''}">
|
|
<input type="submit" name="action" value="Download CSV of all student grades for this course" class="${'is-disabled' if disable_buttons else ''}">
|
|
</p>
|
|
|
|
<p>
|
|
<input type="submit" name="action" value="Dump all RAW grades for all students in this course" class="${'is-disabled' if disable_buttons else ''}">
|
|
<input type="submit" name="action" value="Download CSV of all RAW grades" class="${'is-disabled' if disable_buttons else ''}">
|
|
</p>
|
|
|
|
<p>
|
|
<input type="submit" name="action" value="Download CSV of answer distributions" class="${'is-disabled' if disable_buttons else ''}">
|
|
<input type="submit" name="action" value="Dump description of graded assignments configuration">
|
|
</p>
|
|
<hr width="40%" style="align:left">
|
|
|
|
%if settings.MITX_FEATURES.get('REMOTE_GRADEBOOK_URL','') and instructor_access:
|
|
|
|
<%
|
|
rg = course.remote_gradebook
|
|
%>
|
|
|
|
<h3>${_("Export grades to remote gradebook")}</h3>
|
|
<p>${_("The assignments defined for this course should match the ones stored in the gradebook, for this to work properly!")}</p>
|
|
|
|
<ul>
|
|
<li>${_("Gradebook name:")} <span class="copy-confirm">${rg.get('name','None defined!')}</span>
|
|
<br/>
|
|
<br/>
|
|
<input type="submit" name="action" value="List assignments available in remote gradebook">
|
|
<input type="submit" name="action" value="List enrolled students matching remote gradebook">
|
|
<br/>
|
|
<br/>
|
|
</li>
|
|
<li><input type="submit" name="action" value="List assignments available for this course">
|
|
<br/>
|
|
<br/>
|
|
</li>
|
|
<li>${_("Assignment name:")} <input type="text" name="assignment_name" size=40 >
|
|
<br/>
|
|
<br/>
|
|
<input type="submit" name="action" value="Display grades for assignment">
|
|
<input type="submit" name="action" value="Export grades for assignment to remote gradebook">
|
|
<input type="submit" name="action" value="Export CSV file of grades for assignment">
|
|
</li>
|
|
</ul>
|
|
<hr width="40%" style="align:left">
|
|
|
|
%endif
|
|
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
|
|
<H2>${_("Course-specific grade adjustment")}</h2>
|
|
|
|
<p>
|
|
${_("Specify a particular problem in the course here by its url:")}
|
|
<input type="text" name="problem_for_all_students" size="60">
|
|
</p>
|
|
<p>
|
|
${_('You may use just the "urlname" if a problem, or "modulename/urlname" if not. '
|
|
'(For example, if the location is <tt>i4x://university/course/problem/problemname</tt>, '
|
|
'then just provide the <tt>problemname</tt>. '
|
|
'If the location is <tt>i4x://university/course/notaproblem/someothername</tt>, then '
|
|
'provide <tt>notaproblem/someothername</tt>.)')}
|
|
</p>
|
|
<p>
|
|
${_("Then select an action:")}
|
|
<input type="submit" name="action" value="Reset ALL students' attempts">
|
|
<input type="submit" name="action" value="Rescore ALL students' problem submissions">
|
|
</p>
|
|
<p>
|
|
<p>${_("These actions run in the background, and status for active tasks will appear in a table below. To see status for all tasks submitted for this problem, click on this button:")}
|
|
</p>
|
|
<p>
|
|
<input type="submit" name="action" value="Show Background Task History">
|
|
</p>
|
|
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
<h2>${_("Student-specific grade inspection and adjustment")}</h2>
|
|
<p>
|
|
${_("Specify the {platform_name} email address or username of a student here:").format(platform_name=settings.PLATFORM_NAME)}
|
|
<input type="text" name="unique_student_identifier">
|
|
</p>
|
|
<p>
|
|
${_("Click this, and a link to student's progress page will appear below:")}
|
|
<input type="submit" name="action" value="Get link to student's progress page">
|
|
</p>
|
|
<p>
|
|
${_("Specify a particular problem in the course here by its url:")}
|
|
<input type="text" name="problem_for_student" size="60">
|
|
</p>
|
|
<p>
|
|
${_('You may use just the "urlname" if a problem, or "modulename/urlname" if not. '
|
|
'(For example, if the location is <tt>i4x://university/course/problem/problemname</tt>, '
|
|
'then just provide the <tt>problemname</tt>. '
|
|
'If the location is <tt>i4x://university/course/notaproblem/someothername</tt>, then '
|
|
'provide <tt>notaproblem/someothername</tt>.)')}
|
|
</p>
|
|
<p>
|
|
${_("Then select an action:")}
|
|
<input type="submit" name="action" value="Reset student's attempts">
|
|
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
|
|
<input type="submit" name="action" value="Rescore student's problem submission">
|
|
%endif
|
|
</p>
|
|
|
|
%if instructor_access:
|
|
<p>
|
|
${_("You may also delete the entire state of a student for the specified module:")}
|
|
<input type="submit" name="action" value="Delete student state for module">
|
|
</p>
|
|
%endif
|
|
%if settings.MITX_FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
|
|
<p>${_("Rescoring runs in the background, and status for active tasks will appear in a table below. "
|
|
"To see status for all tasks submitted for this problem and student, click on this button:")}
|
|
</p>
|
|
<p>
|
|
<input type="submit" name="action" value="Show Background Task History for Student">
|
|
</p>
|
|
%endif
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Psychometrics'):
|
|
|
|
<p>${_("Select a problem and an action:")}
|
|
</p>
|
|
|
|
<p>
|
|
<select name="Problem">
|
|
%for problem, count in sorted(problems.items(), key=lambda x: x[0]):
|
|
<option value="${problem}">${problem} [${count}]</option>
|
|
%endfor
|
|
</select>
|
|
</p>
|
|
<p>
|
|
<input type="submit" name="action" value="Generate Histogram and IRT Plot">
|
|
</p>
|
|
|
|
<p></p>
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Admin'):
|
|
|
|
%if instructor_access:
|
|
<hr width="40%" style="align:left">
|
|
<p>
|
|
<input type="submit" name="action" value="List course staff members">
|
|
<p>
|
|
<input type="text" name="staffuser">
|
|
<input type="submit" name="action" value="Remove course staff">
|
|
<input type="submit" name="action" value="Add course staff">
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
%if admin_access:
|
|
<hr width="40%" style="align:left">
|
|
<p>
|
|
<input type="submit" name="action" value="List course instructors">
|
|
<p>
|
|
<input type="text" name="instructor"> <input type="submit" name="action" value="Remove instructor">
|
|
<input type="submit" name="action" value="Add instructor">
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
%if settings.MITX_FEATURES['ENABLE_MANUAL_GIT_RELOAD'] and admin_access:
|
|
<p>
|
|
<input type="submit" name="action" value="Reload course from XML files">
|
|
<input type="submit" name="action" value="GIT pull and Reload course">
|
|
%endif
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Forum Admin'):
|
|
%if instructor_access:
|
|
<hr width="40%" style="align:left">
|
|
<p>
|
|
<input type="submit" name="action" value="List course forum admins">
|
|
<p>
|
|
<input type="text" name="forumadmin"> <input type="submit" name="action" value="Remove forum admin">
|
|
<input type="submit" name="action" value="Add forum admin">
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
%if instructor_access or forum_admin_access:
|
|
<p>
|
|
<input type="submit" name="action" value="List course forum moderators">
|
|
<input type="submit" name="action" value="List course forum community TAs">
|
|
<p>
|
|
<input type="text" name="forummoderator">
|
|
<input type="submit" name="action" value="Remove forum moderator">
|
|
<input type="submit" name="action" value="Add forum moderator">
|
|
<input type="submit" name="action" value="Remove forum community TA">
|
|
<input type="submit" name="action" value="Add forum community TA">
|
|
<hr width="40%" style="align:left">
|
|
%else:
|
|
<p>${_("User requires forum administrator privileges to perform administration tasks. See instructor.")}</p>
|
|
%endif
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Enrollment'):
|
|
|
|
<hr width="40%" style="align:left">
|
|
<h2>${_("Enrollment Data")}</h2>
|
|
% if disable_buttons:
|
|
|
|
<div class="msg msg-warning">
|
|
<div class="copy">
|
|
<p>
|
|
${_("Note: some of these buttons are known to time out for larger "
|
|
"courses. We have temporarily disabled those features for courses "
|
|
"with more than {max_enrollment} students. We are urgently working on "
|
|
"fixing this issue. Thank you for your patience as we continue "
|
|
"working to improve the platform!").format(
|
|
max_enrollment=settings.MITX_FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
|
|
)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
<input type="submit" name="action" value="List enrolled students" class="${'is-disabled' if disable_buttons else ''}">
|
|
<input type="submit" name="action" value="List students who may enroll but may not have yet signed up" class="${'is-disabled' if disable_buttons else ''}">
|
|
<hr width="40%" style="align:left">
|
|
|
|
%if settings.MITX_FEATURES.get('REMOTE_GRADEBOOK_URL','') and instructor_access:
|
|
|
|
<%
|
|
rg = course.remote_gradebook
|
|
%>
|
|
|
|
<p>${_("Pull enrollment from remote gradebook")}</p>
|
|
<ul>
|
|
<li>${_("Gradebook name:")} <span class="copy-confirm">${rg.get('name','None defined!')}</span>
|
|
<li>${_("Section:")} <input type="text" name="gradebook_section" size=40 value="${rg.get('section','')}"></li>
|
|
</ul>
|
|
<input type="submit" name="action" value="List sections available in remote gradebook">
|
|
<input type="submit" name="action" value="List students in section in remote gradebook">
|
|
<input type="submit" name="action" value="Overload enrollment list using remote gradebook">
|
|
<input type="submit" name="action" value="Merge enrollment list with remote gradebook">
|
|
<hr width="40%" style="align:left">
|
|
|
|
%endif
|
|
<h2>${_("Batch Enrollment")}</h2>
|
|
<p>${_("Enroll or un-enroll one or many students: enter emails, separated by new lines or commas;")}</p>
|
|
<textarea rows="6" cols="70" name="multiple_students"></textarea>
|
|
<p>
|
|
<input type="checkbox" name="email_students"> ${_("Notify students by email")}
|
|
<p>
|
|
<input type="checkbox" name="auto_enroll"> ${_("Auto-enroll students when they activate")}
|
|
<input type="submit" name="action" value="Enroll multiple students">
|
|
<p>
|
|
<input type="submit" name="action" value="Unenroll multiple students">
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Data'):
|
|
<hr width="40%" style="align:left">
|
|
<p>
|
|
<input type="submit" name="action" value="Download CSV of all student profile data">
|
|
</p>
|
|
<p> ${_("Problem urlname:")}
|
|
<input type="text" name="problem_to_dump" size="40">
|
|
<input type="submit" name="action" value="Download CSV of all responses to problem">
|
|
</p>
|
|
<p>
|
|
<input type="submit" name="action" value="Download CSV of all student anonymized IDs">
|
|
</p>
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Manage Groups'):
|
|
%if instructor_access:
|
|
<hr width="40%" style="align:left">
|
|
<p>
|
|
<input type="submit" name="action" value="List beta testers">
|
|
<p>
|
|
## Translators: days_early_for_beta should not be translated
|
|
${_("Enter usernames or emails for students who should be beta-testers, one per line, or separated by commas. They will get to "
|
|
"see course materials early, as configured via the <tt>days_early_for_beta</tt> option in the course policy.")}
|
|
</p>
|
|
<p>
|
|
<textarea cols="50" row="30" name="betausers"></textarea>
|
|
<input type="submit" name="action" value="Remove beta testers">
|
|
<input type="submit" name="action" value="Add beta testers">
|
|
</p>
|
|
<hr width="40%" style="align:left">
|
|
|
|
%if course.is_cohorted:
|
|
<%include file="/course_groups/cohort_management.html" />
|
|
%endif
|
|
|
|
%endif
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Email'):
|
|
%if email_msg:
|
|
<p></p><p>${email_msg}</p>
|
|
%endif
|
|
|
|
<ul class="list-fields">
|
|
<li class="field">
|
|
<label for="id_to">${_("Send to:")}</label>
|
|
<select id="id_to" name="to_option">
|
|
<option value="myself">${_("Myself")}</option>
|
|
%if to_option == "staff":
|
|
<option value="staff" selected="selected">${_("Staff and instructors")}</option>
|
|
%else:
|
|
<option value="staff">${_("Staff and instructors")}</option>
|
|
%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>
|
|
%endif
|
|
</select>
|
|
</li>
|
|
|
|
<li class="field">
|
|
<label for="id_subject">${_("Subject: ")}</label>
|
|
%if subject:
|
|
<input type="text" id="id_subject" name="subject" maxlength="128" size="75" value="${subject}">
|
|
%else:
|
|
<input type="text" id="id_subject" name="subject" maxlength="128" size="75">
|
|
%endif
|
|
<span class="tip">${_("(Max 128 characters)")}</span>
|
|
</li>
|
|
|
|
<li class="field">
|
|
<label>Message:</label>
|
|
<div class="email-editor">
|
|
${editor}
|
|
</div>
|
|
<input type="hidden" name="message" value="">
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="submit-email-action">
|
|
<p class="copy">${_("Please try not to email students more than once per week. Important things to consider before sending:")}</p>
|
|
<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 sent the email to yourself first to make sure you're happy with how it's displayed, and that embedded links and images work properly?")}</li>
|
|
</ul>
|
|
<div class="submit-email-warning">
|
|
<p class="copy"><span style="color: red;"><b>${_("CAUTION!")}</b></span>
|
|
${_("Once the 'Send Email' button is clicked, your email will be queued for sending.")}
|
|
<b>${_("A queued email CANNOT be cancelled.")}</b></p>
|
|
</div>
|
|
<br />
|
|
<input type="submit" name="action" value="Send email">
|
|
</div>
|
|
<script type="text/javascript">
|
|
$(document).ready(function(){
|
|
var emailEditor = XBlock.initializeBlock($('.xblock-studio_view'));
|
|
document.idashform.onsubmit = function() {
|
|
this.message.value = emailEditor.save()['data'];
|
|
return true;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<br />
|
|
<p>These email actions run in the background, and status for active email tasks will appear in a table below.
|
|
To see status for all bulk email tasks submitted for this course, click on this button:
|
|
</p>
|
|
<p>
|
|
<input type="submit" name="action" value="Show Background Email Task History">
|
|
</p>
|
|
%endif
|
|
|
|
</form>
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if msg:
|
|
<p></p><p>${msg}</p>
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Analytics'):
|
|
|
|
%if not any(analytics_results.values()):
|
|
<p>${_("No Analytics are available at this time.")}</p>
|
|
%endif
|
|
|
|
%if analytics_results.get("StudentsEnrolled"):
|
|
<p>
|
|
${_("Students enrolled:")}
|
|
${analytics_results["StudentsEnrolled"]['data'][0]['students']}
|
|
(${analytics_results["StudentsEnrolled"]['time']})
|
|
</p>
|
|
%endif
|
|
|
|
%if analytics_results.get("StudentsActive"):
|
|
<p>
|
|
${_("Students active in the last week:")}
|
|
${analytics_results["StudentsActive"]['data'][0]['active']}
|
|
(${analytics_results["StudentsActive"]['time']})
|
|
</p>
|
|
%endif
|
|
|
|
%if analytics_results.get("StudentsDropoffPerDay"):
|
|
<p>
|
|
${_("Student activity day by day")}
|
|
(${analytics_results["StudentsDropoffPerDay"]['time']})
|
|
</p>
|
|
<div>
|
|
<table class="stat_table">
|
|
<tr>
|
|
<th>${_("Day")}</th>
|
|
<th>${_("Students")}</th>
|
|
</tr>
|
|
%for row in analytics_results['StudentsDropoffPerDay']['data']:
|
|
<tr>
|
|
## For now, just discard the non-date portion
|
|
<td>${row['last_day'].split("T")[0]}</td>
|
|
<td>${row['num_students']}</td>
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</div>
|
|
%endif
|
|
<br/>
|
|
%if analytics_results.get("ProblemGradeDistribution"):
|
|
<p>
|
|
${_("Answer distribution for problems")}
|
|
(${analytics_results["ProblemGradeDistribution"]['time']})
|
|
</p>
|
|
<div>
|
|
<table class="stat_table">
|
|
<tr>
|
|
<th>${_("Problem")}</th>
|
|
<th>${_("Max")}</th>
|
|
<th colspan="99">${_("Points Earned (Num Students)")}</th>
|
|
</tr>
|
|
%for row in analytics_results['ProblemGradeDistribution']['data']:
|
|
<tr>
|
|
<td>${row['module_id'].split('/')[-1]}</td>
|
|
<td>${max(grade_record['max_grade'] for grade_record in row["grade_info"])}
|
|
%for grade_record in row["grade_info"]:
|
|
<td>
|
|
%if isinstance(grade_record["grade"], float):
|
|
${"{grade:.2f}".format(**grade_record)}
|
|
%else:
|
|
${"{grade}".format(**grade_record)}
|
|
%endif
|
|
(${grade_record["num_students"]})
|
|
</td>
|
|
%endfor
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</div>
|
|
%endif
|
|
%endif
|
|
|
|
%if modeflag.get('Analytics In Progress'):
|
|
|
|
##This is not as helpful as it could be -- let's give full point distribution
|
|
##instead.
|
|
%if analytics_results.get("StudentsPerProblemCorrect"):
|
|
<p>
|
|
${_("Students answering correctly")}
|
|
(${analytics_results["StudentsPerProblemCorrect"]['time']})
|
|
</p>
|
|
<div class="divScroll">
|
|
<table class="stat_table">
|
|
<tr>
|
|
<th>${_("Problem")}</th>
|
|
<th>${_("Number of students")}</th>
|
|
</tr>
|
|
%for row in analytics_results['StudentsPerProblemCorrect']['data']:
|
|
<tr>
|
|
<td>${row['module_id'].split('/')[-1]}</td>
|
|
<td>${row['count']}</td>
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</div>
|
|
%endif
|
|
|
|
<p>
|
|
${_("Student distribution per country, all courses, Sep-12 to Oct-17, 1 server (shown here as an example):")}
|
|
</p>
|
|
|
|
<div id="posts-list" class="clearfix">
|
|
<figure>
|
|
<div id="world-map-students" style="width: 720px; height: 400px"></div>
|
|
<script>
|
|
var student_data = {BD : '300', BE : '156', BF : '7', BG : '246', BA : '62', BB : '1', BN : '7', BO : '61', JP : '153', BI : '4', BJ : '6', BT : '11', JM : '32', JO : '67', WS : '1', BR : '1941', BS : '5', JE : '6', BY : '166', BZ : '4', RU : '1907', RW : '50', RS : '128', TL : '1', RE : '2', A2 : '59', TJ : '9', RO : '232', GU : '3', GT : '76', GR : '565', BH : '22', GY : '6', GG : '2', GF : '1', GE : '22', GD : '7', GB : '2023', GA : '4', GM : '18', GL : '2', GI : '1', GH : '393', OM : '25', TN : '143', BW : '26', HR : '76', HT : '38', HU : '259', HK : '103', HN : '51', AD : '1', PR : '40', PS : '38', PT : '487', PY : '38', PA : '21', PG : '11', PE : '342', PK : '1833', PH : '571', TM : '1', PL : '736', ZM : '61', EE : '67', EG : '961', ZA : '184', EC : '118', AL : '44', AO : '10', SB : '2', EU : '183', ET : '153', SO : '1', ZW : '42', KY : '3', ES : '1954', ER : '3', ME : '6', MD : '26', MG : '10', UY : '64', UZ : '40', MM : '21', ML : '4', MO : '3', MN : '49', US : '11899', MU : '11', MT : '15', MW : '41', MV : '5', MP : '4', MR : '1', IM : '2', UG : '133', MY : '207', MX : '844', AT : '83', FR : '446', MA : '175', A1 : '167', AX : '1', FI : '97', FJ : '9', NI : '23', NL : '240', NO : '110', NA : '27', NC : '1', NE : '4', NG : '753', NZ : '98', NP : '200', CI : '9', CH : '144', CO : '851', CN : '282', CM : '82', CL : '243', CA : '1129', CD : '7', CZ : '161', CY : '26', CR : '137', CV : '11', CU : '15', SZ : '6', SY : '58', KG : '47', KE : '282', SR : '5', KI : '1', KH : '40', SV : '155', KM : '1', ST : '1', SK : '66', KR : '141', SI : '70', KP : '1', KW : '28', SN : '16', SL : '11', KZ : '174', SA : '352', SG : '217', SE : '172', SD : '61', DO : '104', DM : '5', DJ : '6', DK : '105', DE : '941', YE : '90', DZ : '281', MK : '28', TZ : '124', LC : '5', LA : '7', TW : '115', TT : '33', TR : '288', LK : '96', LV : '52', TO : '2', LT : '114', LU : '21', LR : '9', LS : '9', TH : '84', TG : '11', LY : '15', VC : '6', AE : '151', VE : '180', AG : '1', AF : '21', IQ : '29', VI : '1', IS : '14', IR : '153', AM : '37', IT : '365', VN : '269', AP : '23', AR : '258', AU : '661', IL : '159', AW : '3', IN : '7836', LB : '28', AZ : '22', IE : '210', ID : '382', UA : '860', QA : '23', MZ : '8'};
|
|
$(function(){
|
|
$('#world-map-students').vectorMap({
|
|
map: 'world_mill_en',
|
|
backgroundColor: '#eeeeee',
|
|
series: {
|
|
regions: [{
|
|
values: student_data,
|
|
scale: ['#C8EEFF', '#0071A4'],
|
|
normalizeFunction: 'polynomial'
|
|
}]
|
|
},
|
|
onRegionLabelShow: function(event, label, code){
|
|
label.text(label.text() + ': ' + (student_data[code] != null ? student_data[code] : 0));
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</figure>
|
|
</div>
|
|
|
|
|
|
## <p>Number of students who dropped off per day before becoming inactive:</p>
|
|
##
|
|
## % if dropoff_per_day is not None:
|
|
## % if dropoff_per_day['status'] == 'success':
|
|
## <div class="divScroll">
|
|
## <table class="stat_table">
|
|
## <tr><th>Day</th><th>Number of students</th></tr>
|
|
## % for k,v in dropoff_per_day['data'].items():
|
|
## <tr> <td>${k}</td> <td>${v}</td> </tr>
|
|
## % endfor
|
|
## </table>
|
|
## </div>
|
|
## % else:
|
|
## <i> ${dropoff_per_day['error']}</i>
|
|
## % endif
|
|
## % else:
|
|
## <i> null data </i>
|
|
## % endif
|
|
## </p>
|
|
##
|
|
|
|
|
|
## <p>
|
|
## <h2>Daily activity (online version):</h2>
|
|
## <table class="stat_table">
|
|
## <tr><th>Day</td><th>Number of students</td></tr>
|
|
## % for k,v in daily_activity_json['data'].items():
|
|
## <tr>
|
|
## <td>${k}</td> <td>${v}</td>
|
|
## </tr>
|
|
## % endfor
|
|
## </table>
|
|
## </p>
|
|
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if datatable and modeflag.get('Psychometrics') is None:
|
|
|
|
<br/>
|
|
<br/>
|
|
<p>
|
|
<hr width="100%">
|
|
<h2>${datatable['title'] | h}</h2>
|
|
<table class="stat_table">
|
|
<tr>
|
|
%for hname in datatable['header']:
|
|
<th>${hname | h}</th>
|
|
%endfor
|
|
</tr>
|
|
%for row in datatable['data']:
|
|
<tr>
|
|
%for value in row:
|
|
<td>${value | h}</td>
|
|
%endfor
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</p>
|
|
%endif
|
|
|
|
## Output tasks in progress
|
|
|
|
%if instructor_tasks is not None and len(instructor_tasks) > 0:
|
|
<hr width="100%">
|
|
<h2>${_("Pending Instructor Tasks")}</h2>
|
|
<div id="task-progress-wrapper">
|
|
<table class="stat_table">
|
|
<tr>
|
|
<th>${_("Task Type")}</th>
|
|
<th>${_("Task inputs")}</th>
|
|
<th>${_("Task Id")}</th>
|
|
<th>${_("Requester")}</th>
|
|
<th>${_("Submitted")}</th>
|
|
<th>${_("Task State")}</th>
|
|
<th>${_("Duration (sec)")}</th>
|
|
<th>${_("Task Progress")}</th>
|
|
</tr>
|
|
%for tasknum, instructor_task in enumerate(instructor_tasks):
|
|
<tr id="task-progress-entry-${tasknum}" class="task-progress-entry"
|
|
data-task-id="${instructor_task.task_id}"
|
|
data-in-progress="true">
|
|
<td>${instructor_task.task_type}</td>
|
|
<td>${instructor_task.task_input}</td>
|
|
<td class="task-id">${instructor_task.task_id}</td>
|
|
<td>${instructor_task.requester}</td>
|
|
<td>${instructor_task.created}</td>
|
|
<td class="task-state">${instructor_task.task_state}</td>
|
|
<td class="task-duration">${_("unknown")}</td>
|
|
<td class="task-progress">${_("unknown")}</td>
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</div>
|
|
<br/>
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if course_stats and modeflag.get('Psychometrics') is None:
|
|
|
|
<br/>
|
|
<br/>
|
|
<p>
|
|
<hr width="100%">
|
|
<h2>${course_stats['title'] | h}</h2>
|
|
<table class="stat_table">
|
|
<tr>
|
|
%for hname in course_stats['header']:
|
|
<th>${hname | h}</th>
|
|
%endfor
|
|
</tr>
|
|
%for row in course_stats['data']:
|
|
<tr>
|
|
%for value in row:
|
|
<td>${value | h}</td>
|
|
%endfor
|
|
</tr>
|
|
%endfor
|
|
</table>
|
|
</p>
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Psychometrics'):
|
|
|
|
%for plot in plots:
|
|
<br/>
|
|
<h3>${plot['title']}</h3>
|
|
<br/>
|
|
<p>${plot['info']}</p>
|
|
<br/>
|
|
<div id="plot_${plot['id']}" style="width:600px;height:300px;"></div>
|
|
<script type="text/javascript">
|
|
$(function () {
|
|
${plot['data']}
|
|
$.plot($("#plot_${plot['id']}"), ${plot['cmd']} );
|
|
});
|
|
</script>
|
|
<br/>
|
|
<br/>
|
|
%endfor
|
|
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
## always show msg
|
|
|
|
|
|
##-----------------------------------------------------------------------------
|
|
%if modeflag.get('Admin'):
|
|
% if course_errors is not UNDEFINED:
|
|
<h2>${_("Course errors")}</h2>
|
|
<div id="course-errors">
|
|
%if not course_errors:
|
|
None
|
|
%else:
|
|
<ul>
|
|
% for (summary, err) in course_errors:
|
|
<li>${summary | h}
|
|
% if err:
|
|
<ul><li><pre>${err | h}</pre></li></ul>
|
|
% else:
|
|
<p> </p>
|
|
% endif
|
|
</li>
|
|
% endfor
|
|
</ul>
|
|
%endif
|
|
</div>
|
|
% endif
|
|
%endif
|
|
|
|
</section>
|
|
</div>
|
|
</section>
|