Commit 9bdff748 by Miles Steele

cleanup

- rename list copy
- add beta list
- fix forum and admin API's to be more similar
- add auto-enroll checkbox
- fix list reload
- remove extra js logging
- add course errors visibility toggle
- add underscore.js check
parent 83ff497e
...@@ -18,7 +18,16 @@ from django_comment_common.models import (Role, ...@@ -18,7 +18,16 @@ from django_comment_common.models import (Role,
def list_with_level(course, level): def list_with_level(course, level):
"""
List users who have 'level' access.
level is in ['instructor', 'staff', 'beta']
"""
if level in ['beta']:
grpname = course_beta_test_group_name(course.location)
else:
grpname = get_access_group_name(course, level) grpname = get_access_group_name(course, level)
try: try:
return Group.objects.get(name=grpname).user_set.all() return Group.objects.get(name=grpname).user_set.all()
except Group.DoesNotExist: except Group.DoesNotExist:
...@@ -52,7 +61,7 @@ def _change_access(course, user, level, mode): ...@@ -52,7 +61,7 @@ def _change_access(course, user, level, mode):
""" """
if level in ['beta']: if level in ['beta']:
grpname = course_beta_test_group_name(course) grpname = course_beta_test_group_name(course.location)
else: else:
grpname = get_access_group_name(course, level) grpname = get_access_group_name(course, level)
group, _ = Group.objects.get_or_create(name=grpname) group, _ = Group.objects.get_or_create(name=grpname)
......
...@@ -31,22 +31,33 @@ import analytics.csvs ...@@ -31,22 +31,33 @@ import analytics.csvs
@ensure_csrf_cookie @ensure_csrf_cookie
@cache_control(no_cache=True, no_store=True, must_revalidate=True) @cache_control(no_cache=True, no_store=True, must_revalidate=True)
def enroll_unenroll(request, course_id): def students_update_enrollment_email(request, course_id):
""" """
Enroll or unenroll students by email. Enroll or unenroll students by email.
Requires staff access. Requires staff access.
Query Parameters:
- action in ['enroll', 'unenroll']
- emails is string containing a list of emails separated by anything split_input_list can handle.
- auto_enroll is a boolean (defaults to false)
""" """
course = get_course_with_access(request.user, course_id, 'staff', depth=None) course = get_course_with_access(request.user, course_id, 'staff', depth=None)
emails_to_enroll = split_input_list(request.GET.get('enroll', '')) action = request.GET.get('action', '')
emails_to_unenroll = split_input_list(request.GET.get('unenroll', '')) emails = split_input_list(request.GET.get('emails', ''))
auto_enroll = request.GET.get('auto_enroll', '') in ['true', 'Talse', True]
enrolled_result = enroll_emails(course_id, emails_to_enroll) if action == 'enroll':
unenrolled_result = unenroll_emails(course_id, emails_to_unenroll) results = enroll_emails(course_id, emails, auto_enroll=auto_enroll)
elif action == 'unenroll':
results = unenroll_emails(course_id, emails)
else:
raise ValueError("unrecognized action '{}'".format(action))
response_payload = { response_payload = {
'enrolled': enrolled_result, 'action': action,
'unenrolled': unenrolled_result, 'results': results,
'auto_enroll': auto_enroll,
} }
response = HttpResponse(json.dumps(response_payload), content_type="application/json") response = HttpResponse(json.dumps(response_payload), content_type="application/json")
return response return response
......
...@@ -40,9 +40,15 @@ def instructor_dashboard_2(request, course_id): ...@@ -40,9 +40,15 @@ def instructor_dashboard_2(request, course_id):
if not staff_access: if not staff_access:
raise Http404 raise Http404
access = {
'instructor': instructor_access,
'staff': staff_access,
'forum_admin': forum_admin_access,
}
sections = [ sections = [
_section_course_info(course_id), _section_course_info(course_id),
_section_membership(course_id), _section_membership(course_id, access),
_section_student_admin(course_id), _section_student_admin(course_id),
_section_data_download(course_id), _section_data_download(course_id),
_section_analytics(course_id), _section_analytics(course_id),
...@@ -100,13 +106,16 @@ def _section_course_info(course_id): ...@@ -100,13 +106,16 @@ def _section_course_info(course_id):
return section_data return section_data
def _section_membership(course_id): def _section_membership(course_id, access):
""" Provide data for the corresponding dashboard section """ """ Provide data for the corresponding dashboard section """
section_data = { section_data = {
'section_key': 'membership', 'section_key': 'membership',
'section_display_name': 'Membership', 'section_display_name': 'Membership',
'enroll_button_url': reverse('enroll_unenroll', kwargs={'course_id': course_id}),
'unenroll_button_url': reverse('enroll_unenroll', kwargs={'course_id': course_id}), 'access': access,
'enroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}),
'unenroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}),
'list_course_role_members_url': reverse('list_course_role_members', kwargs={'course_id': course_id}), 'list_course_role_members_url': reverse('list_course_role_members', kwargs={'course_id': course_id}),
'access_allow_revoke_url': reverse('access_allow_revoke', kwargs={'course_id': course_id}), 'access_allow_revoke_url': reverse('access_allow_revoke', kwargs={'course_id': course_id}),
'list_forum_members_url': reverse('list_forum_members', kwargs={'course_id': course_id}), 'list_forum_members_url': reverse('list_forum_members', kwargs={'course_id': course_id}),
...@@ -121,7 +130,7 @@ def _section_student_admin(course_id): ...@@ -121,7 +130,7 @@ def _section_student_admin(course_id):
'section_key': 'student_admin', 'section_key': 'student_admin',
'section_display_name': 'Student Admin', 'section_display_name': 'Student Admin',
'get_student_progress_url': reverse('get_student_progress_url', kwargs={'course_id': course_id}), 'get_student_progress_url': reverse('get_student_progress_url', kwargs={'course_id': course_id}),
'unenroll_button_url': reverse('enroll_unenroll', kwargs={'course_id': course_id}), 'unenroll_button_url': reverse('students_update_enrollment_email', kwargs={'course_id': course_id}),
'reset_student_attempts_url': reverse('reset_student_attempts', kwargs={'course_id': course_id}), 'reset_student_attempts_url': reverse('reset_student_attempts', kwargs={'course_id': course_id}),
} }
return section_data return section_data
......
...@@ -23,7 +23,7 @@ class Analytics ...@@ -23,7 +23,7 @@ class Analytics
populate_selector: (cb) -> populate_selector: (cb) ->
@get_profile_distributions [], (data) => @get_profile_distributions [], (data) =>
@$distribution_select.find('option').eq(0).text "-- Select distribution" @$distribution_select.find('option').eq(0).text "-- Select Distribution --"
for feature in data.available_features for feature in data.available_features
opt = $ '<option/>', opt = $ '<option/>',
...@@ -107,7 +107,8 @@ class Analytics ...@@ -107,7 +107,8 @@ class Analytics
# exports # exports
_.defaults window, InstructorDashboard: {} if _?
_.defaults window.InstructorDashboard, sections: {} _.defaults window, InstructorDashboard: {}
_.defaults window.InstructorDashboard.sections, _.defaults window.InstructorDashboard, sections: {}
_.defaults window.InstructorDashboard.sections,
Analytics: Analytics Analytics: Analytics
log = -> console.log.apply console, arguments
plantTimeout = (ms, cb) -> setTimeout cb, ms
class CourseInfo
constructor: (@$section) ->
log "setting up instructor dashboard section - course info"
@$section.data 'wrapper', @
@$course_errors_wrapper = @$section.find '.course-errors-wrapper'
if @$course_errors_wrapper.length
@$course_error_toggle = @$course_errors_wrapper.find('h2').eq(0)
@$course_error_visibility_wrapper = @$course_errors_wrapper.find '.course-errors-visibility-wrapper'
@$course_errors = @$course_errors_wrapper.find('.course-error')
@$course_error_toggle.text @$course_error_toggle.text() + " (#{@$course_errors.length})"
@$course_error_toggle.click (e) =>
e.preventDefault()
@$course_error_visibility_wrapper.toggle()
# exports
if _?
_.defaults window, InstructorDashboard: {}
_.defaults window.InstructorDashboard, sections: {}
_.defaults window.InstructorDashboard.sections,
CourseInfo: CourseInfo
...@@ -48,7 +48,8 @@ class DataDownload ...@@ -48,7 +48,8 @@ class DataDownload
# exports # exports
_.defaults window, InstructorDashboard: {} if _?
_.defaults window.InstructorDashboard, sections: {} _.defaults window, InstructorDashboard: {}
_.defaults window.InstructorDashboard.sections, _.defaults window.InstructorDashboard, sections: {}
_.defaults window.InstructorDashboard.sections,
DataDownload: DataDownload DataDownload: DataDownload
...@@ -26,6 +26,7 @@ setup_instructor_dashboard = (idash_content) => ...@@ -26,6 +26,7 @@ setup_instructor_dashboard = (idash_content) =>
# setup section header click handlers # setup section header click handlers
for link in ($ link for link in links) for link in ($ link for link in links)
link.click (e) -> link.click (e) ->
e.preventDefault()
# deactivate (styling) all sections # deactivate (styling) all sections
idash_content.find(".#{CSS_IDASH_SECTION}").removeClass CSS_ACTIVE_SECTION idash_content.find(".#{CSS_IDASH_SECTION}").removeClass CSS_ACTIVE_SECTION
idash_content.find(".#{CSS_INSTRUCTOR_NAV}").children().removeClass CSS_ACTIVE_SECTION idash_content.find(".#{CSS_INSTRUCTOR_NAV}").children().removeClass CSS_ACTIVE_SECTION
...@@ -34,8 +35,6 @@ setup_instructor_dashboard = (idash_content) => ...@@ -34,8 +35,6 @@ setup_instructor_dashboard = (idash_content) =>
section_name = $(this).data 'section' section_name = $(this).data 'section'
section = idash_content.find "##{section_name}" section = idash_content.find "##{section_name}"
section.data('wrapper')?.onClickTitle?()
# activate (styling) active # activate (styling) active
section.addClass CSS_ACTIVE_SECTION section.addClass CSS_ACTIVE_SECTION
$(this).addClass CSS_ACTIVE_SECTION $(this).addClass CSS_ACTIVE_SECTION
...@@ -43,8 +42,7 @@ setup_instructor_dashboard = (idash_content) => ...@@ -43,8 +42,7 @@ setup_instructor_dashboard = (idash_content) =>
# write deep link # write deep link
location.hash = "#{HASH_LINK_PREFIX}#{section_name}" location.hash = "#{HASH_LINK_PREFIX}#{section_name}"
log "clicked #{section_name}" plantTimeout 0, -> section.data('wrapper')?.onClickTitle?()
e.preventDefault()
# recover deep link from url # recover deep link from url
# click default or go to section specified by hash # click default or go to section specified by hash
...@@ -62,6 +60,7 @@ setup_instructor_dashboard_sections = (idash_content) -> ...@@ -62,6 +60,7 @@ setup_instructor_dashboard_sections = (idash_content) ->
log "setting up instructor dashboard sections" log "setting up instructor dashboard sections"
# fault isolation # fault isolation
# an error thrown in one section will not block other sections from exectuing # an error thrown in one section will not block other sections from exectuing
plantTimeout 0, -> new window.InstructorDashboard.sections.CourseInfo idash_content.find ".#{CSS_IDASH_SECTION}#course_info"
plantTimeout 0, -> new window.InstructorDashboard.sections.DataDownload idash_content.find ".#{CSS_IDASH_SECTION}#data_download" plantTimeout 0, -> new window.InstructorDashboard.sections.DataDownload idash_content.find ".#{CSS_IDASH_SECTION}#data_download"
plantTimeout 0, -> new window.InstructorDashboard.sections.Membership idash_content.find ".#{CSS_IDASH_SECTION}#membership" plantTimeout 0, -> new window.InstructorDashboard.sections.Membership idash_content.find ".#{CSS_IDASH_SECTION}#membership"
plantTimeout 0, -> new window.InstructorDashboard.sections.StudentAdmin idash_content.find ".#{CSS_IDASH_SECTION}#student_admin" plantTimeout 0, -> new window.InstructorDashboard.sections.StudentAdmin idash_content.find ".#{CSS_IDASH_SECTION}#student_admin"
......
...@@ -9,6 +9,8 @@ class BatchEnrollment ...@@ -9,6 +9,8 @@ class BatchEnrollment
$emails_input = @$container.find("textarea[name='student-emails']'") $emails_input = @$container.find("textarea[name='student-emails']'")
$btn_enroll = @$container.find("input[name='enroll']'") $btn_enroll = @$container.find("input[name='enroll']'")
$btn_unenroll = @$container.find("input[name='unenroll']'") $btn_unenroll = @$container.find("input[name='unenroll']'")
$checkbox_autoenroll = @$container.find("input[name='auto-enroll']'")
window.autoenroll = $checkbox_autoenroll
$task_response = @$container.find(".task-response") $task_response = @$container.find(".task-response")
$emails_input.click -> log 'click $emails_input' $emails_input.click -> log 'click $emails_input'
...@@ -16,20 +18,27 @@ class BatchEnrollment ...@@ -16,20 +18,27 @@ class BatchEnrollment
$btn_unenroll.click -> log 'click $btn_unenroll' $btn_unenroll.click -> log 'click $btn_unenroll'
$btn_enroll.click -> $btn_enroll.click ->
$.getJSON $btn_enroll.data('endpoint'), enroll: $emails_input.val() , (data) -> send_data =
action: 'enroll'
emails: $emails_input.val()
auto_enroll: $checkbox_autoenroll.is(':checked')
$.getJSON $btn_enroll.data('endpoint'), send_data, (data) ->
log 'received response for enroll button', data log 'received response for enroll button', data
display_response(data) display_response(data)
$btn_unenroll.click -> $btn_unenroll.click ->
log 'VAL', $emails_input.val() send_data =
$.getJSON $btn_unenroll.data('endpoint'), unenroll: $emails_input.val() , (data) -> action: 'unenroll'
# log 'received response for unenroll button', data emails: $emails_input.val()
# display_response(data) auto_enroll: $checkbox_autoenroll.is(':checked')
$.getJSON $btn_unenroll.data('endpoint'), send_data, (data) ->
log 'received response for unenroll button', data
display_response(data)
display_response = (data_from_server) -> display_response = (data_from_server) ->
$task_response.empty() $task_response.empty()
response_code_dict = _.extend {}, data_from_server.enrolled, data_from_server.unenrolled response_code_dict = _.extend {}, data_from_server.results
# response_code_dict e.g. {'code': ['email1', 'email2'], ...} # response_code_dict e.g. {'code': ['email1', 'email2'], ...}
message_ordering = [ message_ordering = [
'msg_error_enroll' 'msg_error_enroll'
...@@ -77,13 +86,10 @@ class BatchEnrollment ...@@ -77,13 +86,10 @@ class BatchEnrollment
will_attach = false will_attach = false
for code in msg_to_codes[msg_symbol] for code in msg_to_codes[msg_symbol]
log 'logging code', code
emails = response_code_dict[code] emails = response_code_dict[code]
log 'emails', emails
if emails and emails.length if emails and emails.length
for email in emails for email in emails
log 'logging email', email
email_list.append $ '<li/>', text: email email_list.append $ '<li/>', text: email
will_attach = true will_attach = true
...@@ -114,7 +120,6 @@ class AuthList ...@@ -114,7 +120,6 @@ class AuthList
reload_auth_list: => reload_auth_list: =>
list_endpoint = @$display_table.data 'endpoint' list_endpoint = @$display_table.data 'endpoint'
$.getJSON list_endpoint, {rolename: @rolename}, (data) => $.getJSON list_endpoint, {rolename: @rolename}, (data) =>
log data
@$display_table.empty() @$display_table.empty()
...@@ -139,11 +144,9 @@ class AuthList ...@@ -139,11 +144,9 @@ class AuthList
] ]
table_data = data[@rolename] table_data = data[@rolename]
log 'table_data', table_data
$table_placeholder = $ '<div/>', class: 'slickgrid' $table_placeholder = $ '<div/>', class: 'slickgrid'
@$display_table.append $table_placeholder @$display_table.append $table_placeholder
log '@$display_table', $table_placeholder
grid = new Slick.Grid($table_placeholder, table_data, columns, options) grid = new Slick.Grid($table_placeholder, table_data, columns, options)
grid.autosizeColumns() grid.autosizeColumns()
...@@ -152,11 +155,16 @@ class AuthList ...@@ -152,11 +155,16 @@ class AuthList
if args.cell is 2 if args.cell is 2
@access_change(item.email, @rolename, 'revoke', @reload_auth_list) @access_change(item.email, @rolename, 'revoke', @reload_auth_list)
# slickgrid collapses when rendered in an invisible div
# use this method to reload the widget
refresh: ->
@$display_table.empty()
@reload_auth_list()
access_change: (email, rolename, mode, cb) -> access_change: (email, rolename, mode, cb) ->
access_change_endpoint = @$add_section.data 'endpoint' access_change_endpoint = @$add_section.data 'endpoint'
$.getJSON access_change_endpoint, {email: email, rolename: @rolename, mode: mode}, (data) -> $.getJSON access_change_endpoint, {email: email, rolename: @rolename, mode: mode}, (data) ->
log data cb?(data)
cb?()
class Membership class Membership
...@@ -164,36 +172,41 @@ class Membership ...@@ -164,36 +172,41 @@ class Membership
log "setting up instructor dashboard section - membership" log "setting up instructor dashboard section - membership"
@$section.data 'wrapper', @ @$section.data 'wrapper', @
# isolate sections from each other's errors. @$list_selector = @$section.find('select#member-lists-selector')
plantTimeout 0, => @batchenrollment = new BatchEnrollment @$section.find '.batch-enrollment'
plantTimeout 0, => @stafflist = new AuthList (@$section.find '.auth-list-container.auth-list-staff'), 'staff'
plantTimeout 0, => @instructorlist = new AuthList (@$section.find '.auth-list-container.auth-list-instructor'), 'instructor'
# TODO names like 'Administrator' should come from server through template. plantTimeout 0, => @batchenrollment = new BatchEnrollment @$section.find '.batch-enrollment'
plantTimeout 0, => @forum_admin_list = new AuthList (@$section.find '.auth-list-container.auth-list-forum-admin'), 'Administrator'
plantTimeout 0, => @forum_mod_list = new AuthList (@$section.find '.auth-list-container.auth-list-forum-moderator'), 'Moderator'
plantTimeout 0, => @forum_comta_list = new AuthList (@$section.find '.auth-list-container.auth-list-forum-community-ta'), 'Community TA'
onClickTitle: -> @auth_lists = _.map (@$section.find '.auth-list-container'), (auth_list_container) ->
@stafflist.$display_table.empty() rolename = $(auth_list_container).data 'rolename'
@stafflist.reload_auth_list() new AuthList $(auth_list_container), rolename
@instructorlist.$display_table.empty() # populate selector
@instructorlist.reload_auth_list() @$list_selector.empty()
for auth_list in @auth_lists
@$list_selector.append $ '<option/>',
text: auth_list.$container.data 'display-name'
data:
auth_list: auth_list
@forum_admin_list.$display_table.empty() @$list_selector.change =>
@forum_admin_list.reload_auth_list() $opt = @$list_selector.children('option:selected')
for auth_list in @auth_lists
auth_list.$container.removeClass 'active'
auth_list = $opt.data('auth_list')
auth_list.refresh()
auth_list.$container.addClass 'active'
@forum_mod_list.$display_table.empty() @$list_selector.change()
@forum_mod_list.reload_auth_list()
@forum_comta_list.$display_table.empty()
@forum_comta_list.reload_auth_list()
onClickTitle: ->
for auth_list in @auth_lists
auth_list.refresh()
# exports # exports
_.defaults window, InstructorDashboard: {} if _?
_.defaults window.InstructorDashboard, sections: {} _.defaults window, InstructorDashboard: {}
_.defaults window.InstructorDashboard.sections, _.defaults window.InstructorDashboard, sections: {}
_.defaults window.InstructorDashboard.sections,
Membership: Membership Membership: Membership
...@@ -24,8 +24,12 @@ class StudentAdmin ...@@ -24,8 +24,12 @@ class StudentAdmin
console.warn 'error getting student progress url for ' + email console.warn 'error getting student progress url for ' + email
@$unenroll_btn.click => @$unenroll_btn.click =>
$.getJSON @$unenroll_btn.data('endpoint'), unenroll: @$student_email_field.val(), (data) -> send_data =
log 'data' action: 'unenroll'
emails: @$student_email_field.val()
auto_enroll: false
$.getJSON @$unenroll_btn.data('endpoint'), send_data, (data) ->
log data
@$reset_attempts_btn.click => @$reset_attempts_btn.click =>
email = @$student_email_field.val() email = @$student_email_field.val()
...@@ -77,7 +81,8 @@ class StudentAdmin ...@@ -77,7 +81,8 @@ class StudentAdmin
# exports # exports
_.defaults window, InstructorDashboard: {} if _?
_.defaults window.InstructorDashboard, sections: {} _.defaults window, InstructorDashboard: {}
_.defaults window.InstructorDashboard.sections, _.defaults window.InstructorDashboard, sections: {}
_.defaults window.InstructorDashboard.sections,
StudentAdmin: StudentAdmin StudentAdmin: StudentAdmin
...@@ -63,11 +63,19 @@ ...@@ -63,11 +63,19 @@
.instructor-dashboard-wrapper-2 section.idash-section#course_info { .instructor-dashboard-wrapper-2 section.idash-section#course_info {
.error-log { .course-errors-wrapper {
margin-top: 1em; margin-top: 2em;
h2 {
color: #D60000;
}
.course-errors-visibility-wrapper {
display: none;
.course-error { .course-error {
margin-bottom: 1em; margin-bottom: 1em;
margin-left: 0.5em;
code { code {
&.course-error-first { &.course-error-first {
...@@ -75,7 +83,8 @@ ...@@ -75,7 +83,8 @@
} }
&.course-error-second { &.course-error-second {
color: black; color: #111;
}
} }
} }
} }
...@@ -86,17 +95,26 @@ ...@@ -86,17 +95,26 @@
.instructor-dashboard-wrapper-2 section.idash-section#membership { .instructor-dashboard-wrapper-2 section.idash-section#membership {
.vert-left { .vert-left {
float: left; float: left;
width: 45%; width: 47%;
} }
.vert-right { .vert-right {
float: right; float: right;
width: 45%; width: 47%;
}
select {
margin-bottom: 1em;
} }
.auth-list-container { .auth-list-container {
display: none;
margin-bottom: 1.5em; margin-bottom: 1.5em;
&.active {
display: block;
}
.auth-list-table { .auth-list-table {
.slickgrid { .slickgrid {
height: 250px; height: 250px;
...@@ -110,6 +128,9 @@ ...@@ -110,6 +128,9 @@
.batch-enrollment { .batch-enrollment {
textarea { textarea {
margin-top: 0.2em;
margin-bottom: 1em;
height: 100px; height: 100px;
width: 500px; width: 500px;
} }
...@@ -146,6 +167,7 @@ ...@@ -146,6 +167,7 @@
input { input {
// display: block; // display: block;
margin-bottom: 1em; margin-bottom: 1em;
line-height: 1.3em;
} }
.data-display { .data-display {
......
...@@ -37,14 +37,16 @@ ...@@ -37,14 +37,16 @@
${ section_data['offline_grades'] } ${ section_data['offline_grades'] }
</div> </div>
<div class="error-log"> %if len(section_data['course_errors']):
%if len(section_data['course_errors']): <div class="course-errors-wrapper">
<h2>Course Errors:</h2> <a href=""><h2 class="title">Course Warnings:</h2></a>
<div class="course-errors-visibility-wrapper">
%for error in section_data['course_errors']: %for error in section_data['course_errors']:
<div class="course-error"> <div class="course-error">
<code class=course-error-first> ${ error[0] } </code><br> <code class=course-error-first> ${ error[0] } </code><br>
<code class=course-error-second> ${ error[1] } </code> <code class=course-error-second> ${ error[1] } </code>
</div> </div>
%endfor %endfor
%endif </div>
</div> </div>
%endif
<%page args="section_data"/> <%page args="section_data"/>
<input type="button" name="list-profiles" value="List enrolled students with profile information" data-endpoint="${ section_data['enrolled_students_profiles_url'] }" > <input type="button" name="list-profiles" value="List enrolled students with profile information" data-endpoint="${ section_data['enrolled_students_profiles_url'] }" >
<input type="button" name="list-profiles" value="[CSV]" data-csv="true" data-endpoint="${ section_data['enrolled_students_profiles_url'] }" > <input type="button" name="list-profiles" value="CSV" data-csv="true" class="csv" data-endpoint="${ section_data['enrolled_students_profiles_url'] }" >
<br>
<input type="button" name="list-grades" value="Student grades"> <input type="button" name="list-grades" value="Student grades">
<br>
<input type="button" name="list-answer-distributions" value="Answer distributions (x students got y points)"> <input type="button" name="list-answer-distributions" value="Answer distributions (x students got y points)">
<br>
<input type="button" name="dump-gradeconf" value="Grading Configuration" data-endpoint="${ section_data['grading_config_url'] }"> <input type="button" name="dump-gradeconf" value="Grading Configuration" data-endpoint="${ section_data['grading_config_url'] }">
<div class="data-display"> <div class="data-display">
<div class="data-display-text"></div> <div class="data-display-text"></div>
<div class="data-display-table"></div> <div class="data-display-table"></div>
......
...@@ -7,52 +7,68 @@ ...@@ -7,52 +7,68 @@
<br> <br>
<input type="button" name="enroll" value="Enroll" data-endpoint="${ section_data['enroll_button_url'] }" > <input type="button" name="enroll" value="Enroll" data-endpoint="${ section_data['enroll_button_url'] }" >
<input type="button" name="unenroll" value="Unenroll" data-endpoint="${ section_data['unenroll_button_url'] }" > <input type="button" name="unenroll" value="Unenroll" data-endpoint="${ section_data['unenroll_button_url'] }" >
<input type="checkbox" name="auto-enroll" value="Auto-Enroll">
<label for="auto-enroll">Auto Enroll</label>
<div class="task-response"></div> <div class="task-response"></div>
</div>
<div class="auth-list-container auth-list-forum-admin"> <div class="vert-right member-lists-management">
<h2>Instructor Management</h2> <h2> Member List Management </h2>
<div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }"> <select id="member-lists-selector">
<option> Getting available lists... </option>
</select>
<div class="auth-list-container" data-rolename="staff" data-display-name="Staff">
<div class="auth-list-table" data-endpoint="${ section_data['list_course_role_members_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['access_allow_revoke_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false"> <input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Forum Admin"> <input type="button" name="allow" value="Grant Staff Access">
</div> </div>
</div> </div>
<div class="auth-list-container auth-list-forum-moderator"> %if section_data['access']['instructor']:
<h2>Instructor Management</h2> <div class="auth-list-container" data-rolename="instructor" data-display-name="Instructors">
<div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div> <div class="auth-list-table" data-endpoint="${ section_data['list_course_role_members_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }"> <div class="auth-list-add" data-endpoint="${ section_data['access_allow_revoke_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false"> <input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Forum Moderator"> <input type="button" name="allow" value="Grant Instructor Access">
</div>
</div>
%endif
<div class="auth-list-container" data-rolename="beta" data-display-name="Beta Testers">
<div class="auth-list-table" data-endpoint="${ section_data['list_course_role_members_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['access_allow_revoke_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Beta Tester Access">
</div> </div>
</div> </div>
<div class="auth-list-container auth-list-forum-community-ta"> %if section_data['access']['forum_admin']:
<h2>Instructor Management</h2> <div class="auth-list-container" data-rolename="Administrator" data-display-name="Forum Admins">
<div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div> <div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }"> <div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false"> <input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Community TA"> <input type="button" name="allow" value="Grant Forum Admin">
</div> </div>
</div> </div>
</div>
<div class="vert-right instructor-staff-management"> <div class="auth-list-container" data-rolename="Moderator" data-display-name="Forum Moderators">
<div class="auth-list-container auth-list-staff"> <div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div>
<h2>Staff Management</h2> <div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }">
<div class="auth-list-table" data-endpoint="${ section_data['list_instructors_staff_url'] }"></div>
<div class="auth-list-add" data-endpoint="${ section_data['access_allow_revoke_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false"> <input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Staff Access"> <input type="button" name="allow" value="Grant Forum Moderator">
</div> </div>
</div> </div>
<div class="auth-list-container auth-list-instructor"> <div class="auth-list-container" data-rolename="Community TA" data-display-name="Forum Community TAs">
<h2>Instructor Management</h2> <div class="auth-list-table" data-endpoint="${ section_data['list_forum_members_url'] }"></div>
<div class="auth-list-table" data-endpoint="${ section_data['list_instructors_staff_url'] }"></div> <div class="auth-list-add" data-endpoint="${ section_data['update_forum_role_membership_url'] }">
<div class="auth-list-add" data-endpoint="${ section_data['access_allow_revoke_url'] }">
<input type="text" name="email" placeholder="Enter Email" spellcheck="false"> <input type="text" name="email" placeholder="Enter Email" spellcheck="false">
<input type="button" name="allow" value="Grant Instructor Access"> <input type="button" name="allow" value="Grant Community TA">
</div> </div>
</div> </div>
%endif
</div> </div>
...@@ -255,8 +255,8 @@ if settings.COURSEWARE_ENABLED: ...@@ -255,8 +255,8 @@ if settings.COURSEWARE_ENABLED:
'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard_2"), 'instructor.views.instructor_dashboard.instructor_dashboard_2', name="instructor_dashboard_2"),
# api endpoints for instructor # api endpoints for instructor
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/enroll_unenroll$', url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/students_update_enrollment_email$',
'instructor.views.api.enroll_unenroll', name="enroll_unenroll"), 'instructor.views.api.students_update_enrollment_email', name="students_update_enrollment_email"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/list_course_role_members$', url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/list_course_role_members$',
'instructor.views.api.list_course_role_members', name="list_course_role_members"), 'instructor.views.api.list_course_role_members', name="list_course_role_members"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/access_allow_revoke$', url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/instructor_dashboard/api/access_allow_revoke$',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment