instructor_dashboard.html 36 KB
Newer Older
1 2 3
## 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 ##
4

5
<%! from django.utils.translation import ugettext as _ %>
6
<%! from django.core.urlresolvers import reverse %>
7 8

<%inherit file="../main.html" />
9
<%namespace name='static' file='/static_content.html'/>
10

11
<%block name="pagetitle">${_("Legacy Instructor Dashboard")}</%block>
12 13
<%block name="nav_skip">#instructor-dashboard-content</%block>

14
<%block name="headextra">
15
<%static:css group='style-course-vendor'/>
16 17
<%static:css group='style-vendor-tinymce-content'/>
<%static:css group='style-vendor-tinymce-skin'/>
18 19
<%static:css group='style-course'/>

20 21 22 23 24 25 26
  <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>
27 28
  <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>
29 30
  <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>
31
  <script type="text/javascript" src="${static.url('js/course_groups/cohorts.js')}"></script>
32
  <script type="text/javascript" src="${static.url('js/vendor/codemirror-compressed.js')}"></script>
33 34
  <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>
35 36 37
  <script type="text/javascript">
    (function() {window.baseUrl = "${settings.STATIC_URL}";})(this);
  </script>
38
  <%static:js group='module-descriptor-js'/>
39
%if instructor_tasks is not None:
40
  <script type="text/javascript" src="${static.url('js/pending_tasks.js')}"></script>
41
%endif
42 43
</%block>

44
<%include file="/courseware/course_navigation.html" args="active_page='instructor'" />
45

46 47
<style type="text/css">
table.stat_table {
48 49 50 51 52 53
    font-family: verdana,arial,sans-serif;
    font-size:11px;
    color:#333333;
    border-width: 1px;
    border-color: #666666;
    border-collapse: collapse;
54 55
}
table.stat_table th {
56 57 58 59 60
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #666666;
    background-color: #dedede;
61 62
}
table.stat_table td {
63 64 65 66 67
    border-width: 1px;
    padding: 8px;
    border-style: solid;
    border-color: #666666;
    background-color: #ffffff;
68
}
69
.divScroll {
70 71
    height: 200px;
    overflow: scroll;
72
}
73 74 75

a.selectedmode { background-color: yellow; }

76 77 78
textarea {
  height: 200px;
}
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

.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;
}

118 119
</style>

120 121 122 123 124 125 126 127
<script language="JavaScript" type="text/javascript">
function goto( mode)
{
  document.idashform.idash_mode.value = mode;
  document.idashform.submit() ;
}
</script>

128 129
<section class="container">
<div class="instructor-dashboard-wrapper">
130

131
  <section class="instructor-dashboard-content" id="instructor-dashboard-content">
132 133 134 135
    <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
136
      <a class="instructor-info-action beta-button" href="${ standard_dashboard_url }">${_("Back To Instructor Dashboard")}</a>
137
    </div>
138

139
    <h1>${_("Instructor Dashboard")}</h1>
140

141 142
    %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)
143
    <div class="wrapper-msg urgency-low msg-warning is-shown">
144 145
        <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-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>
146
    </div>
147
    %endif
148

149
    <h2 class="navbar">[ <a href="#" onclick="goto('Grades');" class="${modeflag.get('Grades')}">Grades</a> |
150
          %if settings.FEATURES.get('ENABLE_PSYCHOMETRICS'):
151
            <a href="#" onclick="goto('Psychometrics');" class="${modeflag.get('Psychometrics')}">${_("Psychometrics")}</a> |
152
          %endif
153 154 155 156 157
          <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>
158
          %if show_email_tab:
159
             | <a href="#" onclick="goto('Email')" class="${modeflag.get('Email')}">${_("Email")}</a>
160
          %endif
161
          %if settings.FEATURES.get('ENABLE_INSTRUCTOR_ANALYTICS'):
162
             | <a href="#" onclick="goto('Analytics');" class="${modeflag.get('Analytics')}">${_("Analytics")}</a>
163
          %endif
164 165 166
          %if settings.FEATURES.get('CLASS_DASHBOARD'):
             | <a href="#" onclick="goto('Metrics');" class="${modeflag.get('Metrics')}">${_("Metrics")}</a>
          %endif
167
      ]
168 169 170
    </h2>

    <form name="idashform" method="POST">
171
    <input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
172
    <input type="hidden" name="idash_mode" value="">
173

174
##-----------------------------------------------------------------------------
175
%if modeflag.get('Grades'):
176 177

    %if offline_grade_log:
178 179
      <p>
        <span class="copy-warning">Pre-computed grades ${offline_grade_log} available: Use?
180
          <input type='checkbox' name='use_offline_grades' value="yes">
181 182
        </span>
      </p>
183 184
    %endif

185 186 187 188

    <hr width="40%" style="align:left">
    <h2>${_("Grade Downloads")}</h2>
    % if disable_buttons:
189 190 191 192 193 194 195 196 197 198

    <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(
199
              max_enrollment=settings.FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
200 201 202 203
            )}
        </p>
      </div>
    </div>
204 205
    % endif

206
    <p>
207
    <a href="${reverse('spoc_gradebook', kwargs=dict(course_id=course.id.to_deprecated_string()))}" class="${'is-disabled' if disable_buttons else ''}">${_("Gradebook")}</a>
208
    </p>
209 210

    <p>
211
    <a href="${reverse('grade_summary_legacy', kwargs=dict(course_id=course.id.to_deprecated_string()))}" class="${'is-disabled' if disable_buttons else ''}">${_("Grade summary")}</a>
212
    </p>
213

214
    <p>
215
    <input type="submit" name="action" value="Dump list of enrolled students" class="${'is-disabled' if disable_buttons else ''}">
216
    </p>
217 218

    <p>
219 220
    <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 ''}">
221
    </p>
222 223

    <p>
224 225
    <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 ''}">
226
    </p>
227 228

    <p>
229
  %if not settings.FEATURES.get('ENABLE_ASYNC_ANSWER_DISTRIBUTION'):
230
    <input type="submit" name="action" value="Download CSV of answer distributions" class="${'is-disabled' if disable_buttons else ''}">
231
  %endif
232
    <input type="submit" name="action" value="Dump description of graded assignments configuration">
233
    </p>
234 235
    <hr width="40%" style="align:left">

236
  %if settings.FEATURES.get('REMOTE_GRADEBOOK_URL','') and instructor_access:
237

238
    <%
239
        rg = course.remote_gradebook
240 241
    %>

242 243
    <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>
244 245

    <ul>
246
    <li>${_("Gradebook name:")} <span class="copy-confirm">${rg.get('name','None defined!')}</span>
247 248
    <br/>
    <br/>
Adam Palay committed
249 250
    <input type="submit" name="action" value="List assignments available in remote gradebook">
    <input type="submit" name="action" value="List enrolled students matching remote gradebook">
251 252 253
    <br/>
    <br/>
    </li>
Adam Palay committed
254
    <li><input type="submit" name="action" value="List assignments available for this course">
255 256 257
    <br/>
    <br/>
    </li>
258
    <li>${_("Assignment name:")} <input type="text" name="assignment_name" size=40 >
259 260
    <br/>
    <br/>
Adam Palay committed
261 262 263
    <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">
264 265
    </li>
    </ul>
266
    <hr width="40%" style="align:left">
267 268

  %endif
269
  %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
270
    <H2>${_("Course-specific grade adjustment")}</h2>
271

272
    <p>
273
      ${_("Specify a problem in the course here with its complete location:")}
274
      <input type="text" name="problem_for_all_students" size="60">
275
    </p>
276 277 278
    ## Translators: A location (string of text) follows this sentence.
    <p>${_("You must provide the complete location of the problem. In the Staff Debug viewer, the location looks like this:")}<br/>
    <tt>i4x://edX/Open_DemoX/problem/78c98390884243b89f6023745231c525</tt></p>
279
    <p>
280
      ${_("Then select an action:")}
Adam Palay committed
281 282
      <input type="submit" name="action" value="Reset ALL students' attempts">
      <input type="submit" name="action" value="Rescore ALL students' problem submissions">
283 284
    </p>
    <p>
285
    <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:")}
286 287
    </p>
    <p>
Adam Palay committed
288
      <input type="submit" name="action" value="Show Background Task History">
289
    </p>
290

291 292 293
    <hr width="40%" style="align:left">
  %endif

294
    <h2>${_("Student-specific grade inspection and adjustment")}</h2>
295
    <p>
296
      ${_("Specify the {platform_name} email address or username of a student here:").format(platform_name=settings.PLATFORM_NAME)}
297
      <input type="text" name="unique_student_identifier">
298 299
    </p>
    <p>
300
      ${_("Click this, and a link to student's progress page will appear below:")}
Adam Palay committed
301
      <input type="submit" name="action" value="Get link to student's progress page">
302 303
    </p>
    <p>
304
      ${_("Specify a problem in the course here with its complete location:")}
305
      <input type="text" name="problem_for_student" size="60">
306
    </p>
307 308 309
    ## Translators: A location (string of text) follows this sentence.
    <p>${_("You must provide the complete location of the problem. In the Staff Debug viewer, the location looks like this:")}<br/>
    <tt>i4x://edX/Open_DemoX/problem/78c98390884243b89f6023745231c525</tt></p>
310

311
    <p>
312
      ${_("Then select an action:")}
Adam Palay committed
313
      <input type="submit" name="action" value="Reset student's attempts">
314
      %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
Adam Palay committed
315
      <input type="submit" name="action" value="Rescore student's problem submission">
316 317
      %endif
    </p>
318 319

    %if instructor_access:
320
    <p>
321
      ${_("You may also delete the entire state of a student for the specified module:")}
Adam Palay committed
322
      <input type="submit" name="action" value="Delete student state for module">
323 324
    </p>
    %endif
325
    %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):
326 327
    <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:")}
328 329
    </p>
    <p>
Adam Palay committed
330
      <input type="submit" name="action" value="Show Background Task History for Student">
331
    </p>
332 333
    %endif

334 335
 %endif

336
##-----------------------------------------------------------------------------
337 338
%if modeflag.get('Psychometrics'):

339
    <p>${_("Select a problem and an action:")}
340 341 342 343 344 345 346 347 348 349
    </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>
Adam Palay committed
350
    <input type="submit" name="action" value="Generate Histogram and IRT Plot">
351
    </p>
352

353 354 355 356
    <p></p>

%endif

357
##-----------------------------------------------------------------------------
358
%if modeflag.get('Admin'):
359

360
  %if instructor_access:
361 362
    <hr width="40%" style="align:left">
    <p>
Adam Palay committed
363
    <input type="submit" name="action" value="List course staff members">
364
    <p>
365
    <input type="text" name="staffuser">
Adam Palay committed
366 367
    <input type="submit" name="action" value="Remove course staff">
    <input type="submit" name="action" value="Add course staff">
368
    <hr width="40%" style="align:left">
369
  %endif
370

371 372 373
  %if admin_access:
    <hr width="40%" style="align:left">
    <p>
Adam Palay committed
374
    <input type="submit" name="action" value="List course instructors">
375
    <p>
Adam Palay committed
376 377
    <input type="text" name="instructor"> <input type="submit" name="action" value="Remove instructor">
    <input type="submit" name="action" value="Add instructor">
378 379 380
    <hr width="40%" style="align:left">
  %endif

381
  %if settings.FEATURES['ENABLE_MANUAL_GIT_RELOAD'] and admin_access:
382
    <p>
Adam Palay committed
383 384
    <input type="submit" name="action" value="Reload course from XML files">
    <input type="submit" name="action" value="GIT pull and Reload course">
385
  %endif
386 387
%endif

388
##-----------------------------------------------------------------------------
389 390 391 392
%if modeflag.get('Forum Admin'):
  %if instructor_access:
    <hr width="40%" style="align:left">
    <p>
Adam Palay committed
393
    <input type="submit" name="action" value="List course forum admins">
394
    <p>
Adam Palay committed
395 396
    <input type="text" name="forumadmin"> <input type="submit" name="action" value="Remove forum admin">
    <input type="submit" name="action" value="Add forum admin">
397 398 399 400 401
    <hr width="40%" style="align:left">
  %endif

  %if instructor_access or forum_admin_access:
    <p>
Adam Palay committed
402 403
    <input type="submit" name="action" value="List course forum moderators">
    <input type="submit" name="action" value="List course forum community TAs">
404
    <p>
405
    <input type="text" name="forummoderator">
Adam Palay committed
406 407 408 409
    <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">
410
    <hr width="40%" style="align:left">
411
  %else:
412
  <p>${_("User requires forum administrator privileges to perform administration tasks.  See instructor.")}</p>
413
  %endif
414

415 416 417 418 419 420 421
  <br />
  <h2>${_("Explanation of Roles:")}</h2>
  <p>${_("Forum Moderators: can edit or delete any post, remove misuse flags, close and re-open threads, endorse "
  "responses, and see posts from all cohorts (if the course is cohorted). Moderators' posts are marked as 'staff'.")}</p>
  <p>${_("Forum Admins: have moderator privileges, as well as the ability to edit the list of forum moderators "
  "(e.g. to appoint a new moderator). Admins' posts are marked as 'staff'.")}</p>
  <p>${_("Community TAs: have forum moderator privileges, and their posts are labelled 'Community TA'.")}</p>
422 423
%endif

424
##-----------------------------------------------------------------------------
425 426 427
%if modeflag.get('Enrollment'):

    <hr width="40%" style="align:left">
428 429
    <h2>${_("Enrollment Data")}</h2>
    % if disable_buttons:
430 431 432 433 434 435 436 437 438

    <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(
439
              max_enrollment=settings.FEATURES['MAX_ENROLLMENT_INSTR_BUTTONS']
440 441 442 443
            )}
        </p>
      </div>
    </div>
444 445 446 447
    % 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 ''}">
448 449
    <hr width="40%" style="align:left">

450
  %if settings.FEATURES.get('REMOTE_GRADEBOOK_URL','') and instructor_access:
451

452
    <%
453
        rg = course.remote_gradebook
454 455
    %>

456
    <p>${_("Pull enrollment from remote gradebook")}</p>
457
    <ul>
458
    <li>${_("Gradebook name:")} <span class="copy-confirm">${rg.get('name','None defined!')}</span>
459
    <li>${_("Section:")} <input type="text" name="gradebook_section" size=40 value="${rg.get('section','')}"></li>
460
    </ul>
Adam Palay committed
461 462 463 464
    <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">
465
    <hr width="40%" style="align:left">
466

467
  %endif
468
  <h2>${_("Batch Enrollment")}</h2>
469
  <p>${_("Enroll or un-enroll one or many students: enter emails, separated by new lines or commas;")}</p>
470 471
  <textarea rows="6" cols="70" name="multiple_students"></textarea>
  <p>
472
  <input type="checkbox" name="email_students"> ${_("Notify students by email")}
473
  <p>
474
  <input type="checkbox" name="auto_enroll"> ${_("Auto-enroll students when they activate")}
Adam Palay committed
475
  <input type="submit" name="action" value="Enroll multiple students">
476
  <p>
Adam Palay committed
477
  <input type="submit" name="action" value="Unenroll multiple students">
478 479 480

%endif

481
##-----------------------------------------------------------------------------
482

483 484 485
%if modeflag.get('Data'):
    <hr width="40%" style="align:left">
    <p>
Adam Palay committed
486
    <input type="submit" name="action" value="Download CSV of all student profile data">
487
    </p>
488
    <p> ${_("Problem urlname:")}
489
        <input type="text" name="problem_to_dump" size="40">
Adam Palay committed
490
        <input type="submit" name="action" value="Download CSV of all responses to problem">
491
    </p>
492 493 494
    <p>
    <input type="submit" name="action" value="Download CSV of all student anonymized IDs">
    </p>
495 496
    <hr width="40%" style="align:left">
%endif
497 498

##-----------------------------------------------------------------------------
499

500 501 502 503
%if modeflag.get('Manage Groups'):
  %if instructor_access:
    <hr width="40%" style="align:left">
    <p>
Adam Palay committed
504
    <input type="submit" name="action" value="List beta testers">
505
    <p>
506 507 508
    ## 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.")}
509
    </p>
510 511
    <p>
    <textarea cols="50" row="30" name="betausers"></textarea>
Adam Palay committed
512 513
    <input type="submit" name="action" value="Remove beta testers">
    <input type="submit" name="action" value="Add beta testers">
514
    </p>
515
    <hr width="40%" style="align:left">
516

517
    %if course.is_cohorted:
518
    <%include file="/course_groups/cohort_management.html" />
519
    %endif
520

521 522 523
  %endif
%endif

524 525 526
##-----------------------------------------------------------------------------

%if modeflag.get('Email'):
527 528
    %if email_msg:
        <p></p><p>${email_msg}</p>
529
    %endif
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551

    <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:
552
          <input type="text" id="id_subject" name="subject" maxlength="128" size="75" value="${subject}">
553
        %else:
554
          <input type="text" id="id_subject" name="subject" maxlength="128" size="75">
555
        %endif
556
        <span class="tip">${_("(Max 128 characters)")}</span>
557 558 559 560 561 562 563 564 565 566 567
      </li>

      <li class="field">
        <label>Message:</label>
        <div class="email-editor">
          ${editor}
        </div>
        <input type="hidden" name="message" value="">
      </li>
    </ul>

568
    <div class="submit-email-action">
569
      <p class="copy">${_("Please try not to email students more than once per week. Important things to consider before sending:")}</p>
570 571
      <ul class="list-advice">
        <li class="item">${_("Have you read over the email to make sure it says everything you want to say?")}</li>
572
        <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>
573
      </ul>
574
      <div class="submit-email-warning">
575 576 577
        <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>
578 579
      </div>
      <br />
580 581
      <input type="submit" name="action" value="Send email">
    </div>
582
    <script type="text/javascript">
Julia Hansbrough committed
583 584 585 586 587 588 589
      $(document).ready(function(){
        var emailEditor = XBlock.initializeBlock($('.xblock-studio_view'));
        document.idashform.onsubmit = function() {
          this.message.value = emailEditor.save()['data'];
          return true;
        }
      });
590
    </script>
591

592
    <br />
593 594 595 596 597 598
    <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>
599 600
%endif

601
    </form>
602
##-----------------------------------------------------------------------------
603

604
%if msg:
605
    <p></p><p id="idash_msg">${msg}</p>
606
%endif
607 608

##-----------------------------------------------------------------------------
609

610
%if modeflag.get('Analytics'):
611

612
  %if not any(analytics_results.values()):
613
    <p>${_("No Analytics are available at this time.")}</p>
614 615
  %endif

616 617
  %if analytics_results.get("StudentsEnrolled"):
    <p>
618
      ${_("Students enrolled (historical count, includes those who have since unenrolled):")}
619
      ${analytics_results["StudentsEnrolled"]['data'][0]['students']}
620
      (${analytics_results["StudentsEnrolled"]['time']})
621 622 623 624 625
    </p>
  %endif

  %if analytics_results.get("StudentsActive"):
    <p>
626
      ${_("Students active in the last week:")}
627
      ${analytics_results["StudentsActive"]['data'][0]['active']}
628
      (${analytics_results["StudentsActive"]['time']})
629
    </p>
630
  %endif
631

632
  %if analytics_results.get("StudentsDropoffPerDay"):
633
    <p>
634
      ${_("Student activity day by day")}
635 636
      (${analytics_results["StudentsDropoffPerDay"]['time']})
    </p>
637 638 639
    <div>
      <table class="stat_table">
        <tr>
640 641
          <th>${_("Day")}</th>
          <th>${_("Students")}</th>
642 643 644 645 646 647 648 649 650 651 652 653 654
        </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"):
655
    <p>
656
      ${_("Score distribution for problems")}
657 658
      (${analytics_results["ProblemGradeDistribution"]['time']})
    </p>
659 660 661
    <div>
      <table class="stat_table">
        <tr>
662 663 664
          <th>${_("Problem")}</th>
          <th>${_("Max")}</th>
          <th colspan="99">${_("Points Earned (Num Students)")}</th>
665 666 667
        </tr>
      %for row in analytics_results['ProblemGradeDistribution']['data']:
        <tr>
668
          <td>${row['block_id']}</td>
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
          <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>
684
  %endif
685 686
%endif

687 688 689 690 691 692 693 694 695 696 697 698
%if modeflag.get('Metrics'):
  %if not any (metrics_results.values()):
    <p>${_("There is no data available to display at this time.")}</p>
  %else:
    <%namespace name="d3_stacked_bar_graph" file="/class_dashboard/d3_stacked_bar_graph.js"/>
    <%namespace name="all_section_metrics" file="/class_dashboard/all_section_metrics.js"/>

    <script>
      ${d3_stacked_bar_graph.body()}
    </script>

    <div id="metrics"></div>
699

700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
    <h3 class="attention">${_("Loading the latest graphs for you; depending on your class size, this may take a few minutes.")}</h3>

    %for i in range(0,len(metrics_results['section_display_name'])):
        <div class="metrics-container" id="metrics_section_${i}">
          <h2>${_("Section:")} ${metrics_results['section_display_name'][i]}</h2>
          <div class="metrics-tooltip" id="metric_tooltip_${i}"></div>
          <div class="metrics-left" id="metric_opened_${i}">
            <h3>${_("Count of Students that Opened a Subsection")}</h3>
            <p class="loading"><i class="icon-spinner icon-spin icon-large"></i>${_("Loading...")}</p>
          </div>
          <div class="metrics-right" id="metric_grade_${i}">
            <h3>${_("Grade Distribution per Problem")}</h3>
            %if not metrics_results['section_has_problem'][i]:
              <p>${_("There are no problems in this section.")}</p>
            %else:
              <p class="loading"><i class="icon-spinner icon-spin icon-large"></i>${_("Loading...")}</p>
            %endif
          </div>
        </div>
    %endfor
      <script>
721 722 723
        var allSubsectionTooltipArr = new Array();
        var allProblemTooltipArr = new Array();
        ${all_section_metrics.body("metric_opened_","metric_grade_","metric_attempts_","metric_tooltip_",course.id, allSubsectionTooltipArr, allProblemTooltipArr)}
724 725 726 727 728
      </script>

  %endif
%endif

729
%if modeflag.get('Analytics In Progress'):
730 731 732 733

  ##This is not as helpful as it could be -- let's give full point distribution
  ##instead.
  %if analytics_results.get("StudentsPerProblemCorrect"):
734
    <p>
735
      ${_("Students answering correctly")}
736 737
      (${analytics_results["StudentsPerProblemCorrect"]['time']})
    </p>
738 739 740
    <div class="divScroll">
      <table class="stat_table">
        <tr>
741 742
          <th>${_("Problem")}</th>
          <th>${_("Number of students")}</th>
743 744 745 746 747 748 749 750 751 752
        </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
753

754
   <p>
755
     ${_("Student distribution per country, all courses, Sep 12 to Oct 17, 1 server (shown here as an example):")}
756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
   </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>

783

784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
##     <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>
817

818

819 820
%endif

821
##-----------------------------------------------------------------------------
jmvt committed
822

823 824 825 826 827 828 829 830 831
%if datatable and modeflag.get('Psychometrics') is None:

    <br/>
    <br/>
    <p>
      <hr width="100%">
      <h2>${datatable['title'] | h}</h2>
      <table class="stat_table">
        <tr>
832 833 834 835
        %for hname in datatable['header']:
          <th>${hname | h}</th>
        %endfor
        </tr>
836 837
        %for row in datatable['data']:
          <tr>
838 839 840 841
          %for value in row:
            <td>${value | h}</td>
          %endfor
          </tr>
842 843 844 845 846
        %endfor
      </table>
    </p>
%endif

847 848
## Output tasks in progress

849
%if instructor_tasks is not None and len(instructor_tasks) > 0:
850
    <hr width="100%">
851
    <h2>${_("Pending Instructor Tasks")}</h2>
852 853 854
    <div id="task-progress-wrapper">
      <table class="stat_table">
        <tr>
855 856 857 858 859 860 861 862
          <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>
863
        </tr>
864
      %for tasknum, instructor_task in enumerate(instructor_tasks):
865
        <tr id="task-progress-entry-${tasknum}" class="task-progress-entry"
866 867
            data-task-id="${instructor_task.task_id}"
            data-in-progress="true">
868 869 870 871 872 873
          <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>
874 875
          <td class="task-duration">${_("unknown")}</td>
          <td class="task-progress">${_("unknown")}</td>
876 877 878 879 880 881 882 883 884 885
        </tr>
      %endfor
      </table>
    </div>
  <br/>

%endif

##-----------------------------------------------------------------------------

886
%if course_stats and modeflag.get('Psychometrics') is None:
887

888 889 890 891
    <br/>
    <br/>
    <p>
      <hr width="100%">
892
      <h2>${course_stats['title'] | h}</h2>
893 894
      <table class="stat_table">
        <tr>
895 896 897 898
        %for hname in course_stats['header']:
          <th>${hname | h}</th>
        %endfor
        </tr>
899
        %for row in course_stats['data']:
900
          <tr>
901 902 903 904
            %for value in row:
              <td>${value | h}</td>
            %endfor
          </tr>
905 906 907
        %endfor
      </table>
    </p>
908 909
%endif

910
##-----------------------------------------------------------------------------
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
%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
931 932

##-----------------------------------------------------------------------------
933
## always show msg
934 935


936
##-----------------------------------------------------------------------------
937 938
%if modeflag.get('Admin'):
 % if course_errors is not UNDEFINED:
939
    <h2>${_("Course errors")}</h2>
Victor Shnayder committed
940
    <div id="course-errors">
941 942 943
    %if not course_errors:
          None
    %else:
Victor Shnayder committed
944 945 946
      <ul>
        % for (summary, err) in course_errors:
        <li>${summary | h}
947
        % if err:
Victor Shnayder committed
948
          <ul><li><pre>${err | h}</pre></li></ul>
949 950 951
        % else:
          <p>&nbsp;</p>
        % endif
Victor Shnayder committed
952 953 954
        </li>
        % endfor
        </ul>
955
      %endif
Victor Shnayder committed
956
      </div>
957
  % endif
958
%endif
959

960 961 962
  </section>
</div>
</section>