548 lines
18 KiB
HTML
548 lines
18 KiB
HTML
## NOTE: This is the template for the LEGACY instructor dashboard ##
|
|
## We are no longer supporting this file or accepting changes into it. ##
|
|
## Please see lms/templates/instructor for instructor dashboard templates ##
|
|
|
|
<%inherit file="../main.html" />
|
|
<%namespace name='static' file='/static_content.html'/>
|
|
<%!
|
|
from django.utils.translation import ugettext as _
|
|
from django.core.urlresolvers import reverse
|
|
%>
|
|
|
|
<%block name="pagetitle">${_("Legacy Instructor Dashboard")}</%block>
|
|
<%block name="nav_skip">#instructor-dashboard-content</%block>
|
|
|
|
<%block name="headextra">
|
|
<%static:css group='style-course-vendor'/>
|
|
<%static:css group='style-vendor-tinymce-content'/>
|
|
<%static:css group='style-vendor-tinymce-skin'/>
|
|
<%static:css group='style-course'/>
|
|
|
|
<script type="text/javascript">
|
|
// This is a hack to get tinymce to work correctly in Firefox until the annotator tool is refactored to not include
|
|
// tinymce globally.
|
|
if(typeof window.Range.prototype === "undefined") {
|
|
window.Range.prototype = { };
|
|
}
|
|
</script>
|
|
<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/tinymce/js/tinymce/tinymce.full.min.js')}"></script>
|
|
<script type="text/javascript" src="${static.url('js/vendor/tinymce/js/tinymce/jquery.tinymce.min.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">
|
|
|
|
<section class="instructor-dashboard-content" id="instructor-dashboard-content">
|
|
<div class="wrap-instructor-info studio-view beta-button-wrapper">
|
|
%if studio_url:
|
|
<a class="instructor-info-action" href="${studio_url}">${_("View Course in Studio")}</a>
|
|
%endif
|
|
<a class="instructor-info-action beta-button" href="${ standard_dashboard_url }">${_("Back To Instructor Dashboard")}</a>
|
|
</div>
|
|
|
|
<h1>${_("Legacy Instructor Dashboard")}</h1>
|
|
|
|
%if settings.FEATURES.get('IS_EDX_DOMAIN', False):
|
|
## Only show this banner on the edx.org website (other sites may choose to show this if they wish)
|
|
<div class="wrapper-msg urgency-low msg-warning is-shown">
|
|
<p>${_("You are using the legacy instructor dashboard, which we will retire in the near future.")} <a href="${ standard_dashboard_url }">${_("Return to the Instructor Dashboard")} <i class="icon fa fa-double-angle-right"></i></a></p>
|
|
<p class="note">${_("If the Instructor Dashboard is missing functionality, please contact your PM to let us know.")}</p>
|
|
</div>
|
|
%endif
|
|
|
|
<h2 class="navbar">[ <a href="#" onclick="goto('Grades');" class="${modeflag.get('Grades')}">Grades</a> |
|
|
%if settings.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.FEATURES.get('CLASS_DASHBOARD'):
|
|
| <a href="#" onclick="goto('Metrics');" class="${modeflag.get('Metrics')}">${_("Metrics")}</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 disabled those features for courses "
|
|
"with more than {max_enrollment} students.").format(
|
|
max_enrollment=settings.FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
|
|
)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
<p>
|
|
<input type="submit" name="action" value="Dump list of enrolled students" class="${'is-disabled' if disable_buttons else ''}" aria-disabled="${'true' if disable_buttons else 'false'}">
|
|
</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 ''}" aria-disabled="${'true' if disable_buttons else 'false'}">
|
|
<input type="submit" name="action" value="Download CSV of all RAW grades" class="${'is-disabled' if disable_buttons else ''}" aria-disabled="${'true' if disable_buttons else 'false'}" >
|
|
</p>
|
|
|
|
<p>
|
|
%if not settings.FEATURES.get('ENABLE_ASYNC_ANSWER_DISTRIBUTION'):
|
|
<input type="submit" name="action" value="Download CSV of answer distributions" class="${'is-disabled' if disable_buttons else ''}" aria-disabled="${'true' if disable_buttons else 'false'}" >
|
|
%endif
|
|
<p class="is-deprecated">
|
|
${_("To download student grades and view the grading configuration for your course, visit the Data Download section of the Instructor Dashboard.")}
|
|
</p>
|
|
<p class="is-deprecated">
|
|
${_("To view the Gradebook (only available for courses with a small number of enrolled students), visit the Student Admin section of the Instructor Dashboard.")}
|
|
</p>
|
|
</p>
|
|
<hr width="40%" style="align:left">
|
|
|
|
%if settings.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.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
|
|
<H2>${_("Course-specific grade adjustment")}</h2>
|
|
|
|
<p class="is-deprecated">${_("To perform these actions, visit the Student Admin section of the Instructor Dashboard.")}</p>
|
|
|
|
%endif
|
|
|
|
<h2>${_("Student-specific grade inspection and adjustment")}</h2>
|
|
|
|
<p class="is-deprecated">${_("To perform these actions, visit the Student Admin section of the Instructor Dashboard.")}</p>
|
|
|
|
%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 or admin_access:
|
|
<p class="is-deprecated">${_("To add or remove course staff or instructors, visit the Membership section of the Instructor Dashboard.")}</p>
|
|
%endif
|
|
|
|
%if settings.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'):
|
|
<p class="is-deprecated">${_("To manage forum roles, visit the Membership section of the Instructor Dashboard.")}</p>
|
|
%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 disabled those features for courses "
|
|
"with more than {max_enrollment} students.").format(
|
|
max_enrollment=settings.FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
|
|
)}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
% endif
|
|
|
|
<p class="is-deprecated">
|
|
${_("To download a CSV file containing profile information for students who are enrolled in this course, visit the Data Download section of the Instructor Dashboard.")}
|
|
</p>
|
|
|
|
<p class="is-deprecated">
|
|
${_("To download a list of students who may enroll in this course but have not yet signed up for it, visit the Data Download section of the Instructor Dashboard.")}
|
|
</p>
|
|
|
|
<hr width="40%" style="align:left">
|
|
|
|
%if settings.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
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Data'):
|
|
<hr width="40%" style="align:left">
|
|
<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 class="is-deprecated">
|
|
${_("To download student profile data and anonymized IDs, visit the Data Download section of the Instructor Dashboard.")}
|
|
</p>
|
|
<hr width="40%" style="align:left">
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Manage Groups'):
|
|
%if instructor_access:
|
|
%if course_is_cohorted:
|
|
<p class="is-deprecated">${_("To manage beta tester roles and cohorts, visit the Membership section of the Instructor Dashboard.")}</p>
|
|
%else:
|
|
<p class="is-deprecated">${_("To manage beta tester roles, visit the Membership section of the Instructor Dashboard.")}</p>
|
|
%endif
|
|
%endif
|
|
%endif
|
|
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if modeflag.get('Email'):
|
|
<p class="is-deprecated">${_("To send email, visit the Email section of the Instructor Dashboard.")}</p>
|
|
%endif
|
|
|
|
</form>
|
|
##-----------------------------------------------------------------------------
|
|
|
|
%if msg:
|
|
<p></p><p id="idash_msg">${msg}</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 modeflag.get('Admin') and course_stats:
|
|
<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>
|
|
%else:
|
|
<br/>
|
|
<br/>
|
|
<h2>${_("Course Statistics At A Glance")}</h2>
|
|
<p class="is-deprecated">
|
|
${_("View course statistics in the Admin section of this legacy instructor dashboard.")}
|
|
</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>
|