Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
c341975b
Commit
c341975b
authored
Nov 26, 2012
by
brianhw
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1072 from MITx/feature/brian/dashboard-manage-mods
Feature/brian/dashboard manage mods
parents
706a8253
8d0eb7f1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
380 additions
and
96 deletions
+380
-96
lms/djangoapps/django_comment_client/models.py
+11
-5
lms/djangoapps/django_comment_client/utils.py
+19
-20
lms/djangoapps/instructor/tests.py
+144
-17
lms/djangoapps/instructor/views.py
+176
-53
lms/templates/courseware/instructor_dashboard.html
+30
-1
No files found.
lms/djangoapps/django_comment_client/models.py
View file @
c341975b
import
logging
from
django.db
import
models
from
django.db
import
models
from
django.contrib.auth.models
import
User
from
django.contrib.auth.models
import
User
import
logging
from
courseware.courses
import
get_course_by_id
from
courseware.courses
import
get_course_by_id
FORUM_ROLE_ADMINISTRATOR
=
'Administrator'
FORUM_ROLE_MODERATOR
=
'Moderator'
FORUM_ROLE_COMMUNITY_TA
=
'Community TA'
FORUM_ROLE_STUDENT
=
'Student'
class
Role
(
models
.
Model
):
class
Role
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
)
name
=
models
.
CharField
(
max_length
=
30
,
null
=
False
,
blank
=
False
)
users
=
models
.
ManyToManyField
(
User
,
related_name
=
"roles"
)
users
=
models
.
ManyToManyField
(
User
,
related_name
=
"roles"
)
...
@@ -15,8 +21,8 @@ class Role(models.Model):
...
@@ -15,8 +21,8 @@ class Role(models.Model):
def
inherit_permissions
(
self
,
role
):
# TODO the name of this method is a little bit confusing,
def
inherit_permissions
(
self
,
role
):
# TODO the name of this method is a little bit confusing,
# since it's one-off and doesn't handle inheritance later
# since it's one-off and doesn't handle inheritance later
if
role
.
course_id
and
role
.
course_id
!=
self
.
course_id
:
if
role
.
course_id
and
role
.
course_id
!=
self
.
course_id
:
logging
.
warning
(
"
%
s cannot inheret permissions from
%
s due to course_id inconsistency"
%
logging
.
warning
(
"
{0} cannot inherit permissions from {1} due to course_id inconsistency"
,
\
(
self
,
role
)
)
self
,
role
)
for
per
in
role
.
permissions
.
all
():
for
per
in
role
.
permissions
.
all
():
self
.
add_permission
(
per
)
self
.
add_permission
(
per
)
...
@@ -25,10 +31,10 @@ class Role(models.Model):
...
@@ -25,10 +31,10 @@ class Role(models.Model):
def
has_permission
(
self
,
permission
):
def
has_permission
(
self
,
permission
):
course
=
get_course_by_id
(
self
.
course_id
)
course
=
get_course_by_id
(
self
.
course_id
)
if
self
.
name
==
"Student"
and
\
if
self
.
name
==
FORUM_ROLE_STUDENT
and
\
(
permission
.
startswith
(
'edit'
)
or
permission
.
startswith
(
'update'
)
or
permission
.
startswith
(
'create'
))
and
\
(
permission
.
startswith
(
'edit'
)
or
permission
.
startswith
(
'update'
)
or
permission
.
startswith
(
'create'
))
and
\
(
not
course
.
forum_posts_allowed
):
(
not
course
.
forum_posts_allowed
):
return
False
return
False
return
self
.
permissions
.
filter
(
name
=
permission
)
.
exists
()
return
self
.
permissions
.
filter
(
name
=
permission
)
.
exists
()
...
...
lms/djangoapps/django_comment_client/utils.py
View file @
c341975b
import
time
from
collections
import
defaultdict
from
collections
import
defaultdict
from
importlib
import
import_module
import
logging
import
time
import
urllib
from
courseware.models
import
StudentModuleCache
from
django.contrib.auth.models
import
User
from
courseware.module_render
import
get_module
from
django.core.urlresolvers
import
reverse
from
xmodule.modulestore
import
Location
from
django.db
import
connection
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.search
import
path_to_location
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
from
django.utils
import
simplejson
from
django.utils
import
simplejson
from
django.db
import
connection
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
User
from
django_comment_client.permissions
import
check_permissions_by_view
from
django_comment_client.models
import
Role
from
django_comment_client.models
import
Role
from
django_comment_client.permissions
import
check_permissions_by_view
from
mitxmako
import
middleware
from
mitxmako
import
middleware
import
logging
import
operator
import
itertools
import
urllib
import
pystache_custom
as
pystache
import
pystache_custom
as
pystache
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.search
import
path_to_location
# TODO these should be cached via django's caching rather than in-memory globals
# TODO these should be cached via django's caching rather than in-memory globals
_FULLMODULES
=
None
_FULLMODULES
=
None
...
@@ -47,9 +41,16 @@ def get_role_ids(course_id):
...
@@ -47,9 +41,16 @@ def get_role_ids(course_id):
staff
=
list
(
User
.
objects
.
filter
(
is_staff
=
True
)
.
values_list
(
'id'
,
flat
=
True
))
staff
=
list
(
User
.
objects
.
filter
(
is_staff
=
True
)
.
values_list
(
'id'
,
flat
=
True
))
roles_with_ids
=
{
'Staff'
:
staff
}
roles_with_ids
=
{
'Staff'
:
staff
}
for
role
in
roles
:
for
role
in
roles
:
roles_with_ids
[
role
.
name
]
=
list
(
role
.
users
.
values_list
(
'id'
,
flat
=
True
))
roles_with_ids
[
role
.
name
]
=
list
(
role
.
users
.
values_list
(
'id'
,
flat
=
True
))
return
roles_with_ids
return
roles_with_ids
def
has_forum_access
(
uname
,
course_id
,
rolename
):
try
:
role
=
Role
.
objects
.
get
(
name
=
rolename
,
course_id
=
course_id
)
except
Role
.
DoesNotExist
:
return
False
return
role
.
users
.
filter
(
username
=
uname
)
.
exists
()
def
get_full_modules
():
def
get_full_modules
():
global
_FULLMODULES
global
_FULLMODULES
if
not
_FULLMODULES
:
if
not
_FULLMODULES
:
...
@@ -132,8 +133,6 @@ def initialize_discussion_info(course):
...
@@ -132,8 +133,6 @@ def initialize_discussion_info(course):
return
return
course_id
=
course
.
id
course_id
=
course
.
id
url_course_id
=
course_id
.
replace
(
'/'
,
'_'
)
.
replace
(
'.'
,
'_'
)
all_modules
=
get_full_modules
()[
course_id
]
all_modules
=
get_full_modules
()[
course_id
]
discussion_id_map
=
{}
discussion_id_map
=
{}
...
...
lms/djangoapps/instructor/tests.py
View file @
c341975b
...
@@ -8,21 +8,19 @@ Notes for running by hand:
...
@@ -8,21 +8,19 @@ Notes for running by hand:
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor
"""
"""
import
courseware.tests.tests
as
ct
from
nose
import
SkipTest
from
mock
import
patch
,
Mock
from
override_settings
import
override_settings
from
override_settings
import
override_settings
# Need access to internal func to put users in the right group
from
django.contrib.auth.models
import
\
from
courseware.access
import
_course_staff_group_name
Group
# Need access to internal func to put users in the right group
from
django.contrib.auth.models
import
User
,
Group
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django_comment_client.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
\
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_STUDENT
from
django_comment_client.utils
import
has_forum_access
import
xmodule.modulestore.django
from
courseware.access
import
_course_staff_group_name
import
courseware.tests.tests
as
ct
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
import
xmodule.modulestore.django
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
...
@@ -61,24 +59,153 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
...
@@ -61,24 +59,153 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
def
test_download_grades_csv
(
self
):
def
test_download_grades_csv
(
self
):
print
"running test_download_grades_csv"
course
=
self
.
toy
course
=
self
.
toy
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
msg
=
"url =
%
s
\n
"
%
url
msg
=
"url = {0}
\n
"
.
format
(
url
)
response
=
self
.
client
.
post
(
url
,
{
'action'
:
'Download CSV of all student grades for this course'
,
response
=
self
.
client
.
post
(
url
,
{
'action'
:
'Download CSV of all student grades for this course'
})
})
msg
+=
"instructor dashboard download csv grades: response = '{0}'
\n
"
.
format
(
response
)
msg
+=
"instructor dashboard download csv grades: response = '
%
s'
\n
"
%
response
self
.
assertEqual
(
response
[
'Content-Type'
],
'text/csv'
,
msg
)
self
.
assertEqual
(
response
[
'Content-Type'
],
'text/csv'
,
msg
)
cdisp
=
response
[
'Content-Disposition'
]
.
replace
(
'TT_2012'
,
'2012'
)
# jenkins course_id is TT_2012_Fall instead of 2012_Fall?
cdisp
=
response
[
'Content-Disposition'
]
.
replace
(
'TT_2012'
,
'2012'
)
# jenkins course_id is TT_2012_Fall instead of 2012_Fall?
msg
+=
"cdisp = '
%
s'
\n
"
%
cdisp
msg
+=
"cdisp = '
{0}'
\n
"
.
format
(
cdisp
)
self
.
assertEqual
(
cdisp
,
'attachment; filename=grades_edX/toy/2012_Fall.csv'
,
msg
)
self
.
assertEqual
(
cdisp
,
'attachment; filename=grades_edX/toy/2012_Fall.csv'
,
msg
)
body
=
response
.
content
.
replace
(
'
\r
'
,
''
)
body
=
response
.
content
.
replace
(
'
\r
'
,
''
)
msg
+=
"body = '
%
s'
\n
"
%
body
msg
+=
"body = '
{0}'
\n
"
.
format
(
body
)
expected_body
=
'''"ID","Username","Full Name","edX email","External email","HW 01","HW 02","HW 03","HW 04","HW 05","HW 06","HW 07","HW 08","HW 09","HW 10","HW 11","HW 12","HW Avg","Lab 01","Lab 02","Lab 03","Lab 04","Lab 05","Lab 06","Lab 07","Lab 08","Lab 09","Lab 10","Lab 11","Lab 12","Lab Avg","Midterm","Final"
expected_body
=
'''"ID","Username","Full Name","edX email","External email","HW 01","HW 02","HW 03","HW 04","HW 05","HW 06","HW 07","HW 08","HW 09","HW 10","HW 11","HW 12","HW Avg","Lab 01","Lab 02","Lab 03","Lab 04","Lab 05","Lab 06","Lab 07","Lab 08","Lab 09","Lab 10","Lab 11","Lab 12","Lab Avg","Midterm","Final"
"2","u2","Fred Weasley","view2@test.com","","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0.0","0.0"
"2","u2","Fred Weasley","view2@test.com","","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0.0","0.0"
'''
'''
self
.
assertEqual
(
body
,
expected_body
,
msg
)
self
.
assertEqual
(
body
,
expected_body
,
msg
)
FORUM_ROLES
=
[
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
]
FORUM_ADMIN_ACTION_SUFFIX
=
{
FORUM_ROLE_ADMINISTRATOR
:
'admin'
,
FORUM_ROLE_MODERATOR
:
'moderator'
,
FORUM_ROLE_COMMUNITY_TA
:
'community TA'
}
FORUM_ADMIN_USER
=
{
FORUM_ROLE_ADMINISTRATOR
:
'forumadmin'
,
FORUM_ROLE_MODERATOR
:
'forummoderator'
,
FORUM_ROLE_COMMUNITY_TA
:
'forummoderator'
}
def
action_name
(
operation
,
rolename
):
if
operation
==
'List'
:
return
'{0} course forum {1}s'
.
format
(
operation
,
FORUM_ADMIN_ACTION_SUFFIX
[
rolename
])
else
:
return
'{0} forum {1}'
.
format
(
operation
,
FORUM_ADMIN_ACTION_SUFFIX
[
rolename
])
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestInstructorDashboardForumAdmin
(
ct
.
PageLoader
):
'''
Check for change in forum admin role memberships
'''
def
setUp
(
self
):
xmodule
.
modulestore
.
django
.
_MODULESTORES
=
{}
courses
=
modulestore
()
.
get_courses
()
def
find_course
(
name
):
"""Assumes the course is present"""
return
[
c
for
c
in
courses
if
c
.
location
.
course
==
name
][
0
]
self
.
full
=
find_course
(
"full"
)
self
.
toy
=
find_course
(
"toy"
)
# Create two accounts
self
.
student
=
'view@test.com'
self
.
instructor
=
'view2@test.com'
self
.
password
=
'foo'
self
.
create_account
(
'u1'
,
self
.
student
,
self
.
password
)
self
.
create_account
(
'u2'
,
self
.
instructor
,
self
.
password
)
self
.
activate_user
(
self
.
student
)
self
.
activate_user
(
self
.
instructor
)
group_name
=
_course_staff_group_name
(
self
.
toy
.
location
)
g
=
Group
.
objects
.
create
(
name
=
group_name
)
g
.
user_set
.
add
(
ct
.
user
(
self
.
instructor
))
self
.
logout
()
self
.
login
(
self
.
instructor
,
self
.
password
)
self
.
enroll
(
self
.
toy
)
def
initialize_roles
(
self
,
course_id
):
self
.
admin_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_ADMINISTRATOR
,
course_id
=
course_id
)[
0
]
self
.
moderator_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_MODERATOR
,
course_id
=
course_id
)[
0
]
self
.
community_ta_role
=
Role
.
objects
.
get_or_create
(
name
=
FORUM_ROLE_COMMUNITY_TA
,
course_id
=
course_id
)[
0
]
def
test_add_forum_admin_users_for_unknown_user
(
self
):
course
=
self
.
toy
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'unknown'
for
action
in
[
'Add'
,
'Remove'
]:
for
rolename
in
FORUM_ROLES
:
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
action
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Error: unknown username "{0}"'
.
format
(
username
))
>=
0
)
def
test_add_forum_admin_users_for_missing_roles
(
self
):
course
=
self
.
toy
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u1'
for
action
in
[
'Add'
,
'Remove'
]:
for
rolename
in
FORUM_ROLES
:
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
action
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Error: unknown rolename "{0}"'
.
format
(
rolename
))
>=
0
)
def
test_remove_forum_admin_users_for_missing_users
(
self
):
course
=
self
.
toy
self
.
initialize_roles
(
course
.
id
)
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u1'
action
=
'Remove'
for
rolename
in
FORUM_ROLES
:
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
action
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Error: user "{0}" does not have rolename "{1}"'
.
format
(
username
,
rolename
))
>=
0
)
def
test_add_and_remove_forum_admin_users
(
self
):
course
=
self
.
toy
self
.
initialize_roles
(
course
.
id
)
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u2'
for
rolename
in
FORUM_ROLES
:
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Add'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Added "{0}" to "{1}" forum role = "{2}"'
.
format
(
username
,
course
.
id
,
rolename
))
>=
0
)
self
.
assertTrue
(
has_forum_access
(
username
,
course
.
id
,
rolename
))
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Remove'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Removed "{0}" from "{1}" forum role = "{2}"'
.
format
(
username
,
course
.
id
,
rolename
))
>=
0
)
self
.
assertFalse
(
has_forum_access
(
username
,
course
.
id
,
rolename
))
def
test_add_and_readd_forum_admin_users
(
self
):
course
=
self
.
toy
self
.
initialize_roles
(
course
.
id
)
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u2'
for
rolename
in
FORUM_ROLES
:
# perform an add, and follow with a second identical add:
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Add'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Add'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Error: user "{0}" already has rolename "{1}", cannot add'
.
format
(
username
,
rolename
))
>=
0
)
self
.
assertTrue
(
has_forum_access
(
username
,
course
.
id
,
rolename
))
def
test_add_nonstaff_forum_admin_users
(
self
):
course
=
self
.
toy
self
.
initialize_roles
(
course
.
id
)
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u1'
rolename
=
FORUM_ROLE_ADMINISTRATOR
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Add'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
response
.
content
.
find
(
'Error: user "{0}" should first be added as staff'
.
format
(
username
))
>=
0
)
def
test_list_forum_admin_users
(
self
):
course
=
self
.
toy
self
.
initialize_roles
(
course
.
id
)
url
=
reverse
(
'instructor_dashboard'
,
kwargs
=
{
'course_id'
:
course
.
id
})
username
=
'u2'
added_roles
=
[
FORUM_ROLE_STUDENT
]
# u2 is already added as a student to the discussion forums
self
.
assertTrue
(
has_forum_access
(
username
,
course
.
id
,
'Student'
))
for
rolename
in
FORUM_ROLES
:
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'Add'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
self
.
assertTrue
(
has_forum_access
(
username
,
course
.
id
,
rolename
))
response
=
self
.
client
.
post
(
url
,
{
'action'
:
action_name
(
'List'
,
rolename
),
FORUM_ADMIN_USER
[
rolename
]:
username
})
for
header
in
[
'Username'
,
'Full name'
,
'Roles'
]:
self
.
assertTrue
(
response
.
content
.
find
(
'<th>{0}</th>'
.
format
(
header
))
>
0
)
self
.
assertTrue
(
response
.
content
.
find
(
'<td>{0}</td>'
.
format
(
username
))
>=
0
)
# concatenate all roles for user, in sorted order:
added_roles
.
append
(
rolename
)
added_roles
.
sort
()
roles
=
', '
.
join
(
added_roles
)
self
.
assertTrue
(
response
.
content
.
find
(
'<td>{0}</td>'
.
format
(
roles
))
>=
0
,
'not finding roles "{0}"'
.
format
(
roles
))
lms/djangoapps/instructor/views.py
View file @
c341975b
# ======== Instructor views =============================================================================
# ======== Instructor views =============================================================================
from
collections
import
defaultdict
import
csv
import
csv
import
itertools
import
json
import
logging
import
logging
import
os
import
os
import
urllib
import
urllib
import
track.views
from
functools
import
partial
from
collections
import
defaultdict
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.context_processors
import
csrf
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.decorators
import
login_required
from
django.http
import
HttpResponse
from
django.http
import
Http404
,
HttpResponse
from
django.shortcuts
import
redirect
from
mitxmako.shortcuts
import
render_to_response
,
render_to_string
#from django.views.decorators.csrf import ensure_csrf_cookie
from
django_future.csrf
import
ensure_csrf_cookie
from
django_future.csrf
import
ensure_csrf_cookie
from
django.views.decorators.cache
import
cache_control
from
django.views.decorators.cache
import
cache_control
from
mitxmako.shortcuts
import
render_to_response
from
courseware
import
grades
from
courseware
import
grades
from
courseware.access
import
has_access
,
get_access_group_name
from
courseware.access
import
has_access
,
get_access_group_name
from
courseware.courses
import
(
get_course_with_access
,
get_courses_by_university
)
from
courseware.courses
import
get_course_with_access
from
django_comment_client.models
import
Role
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
from
django_comment_client.utils
import
has_forum_access
from
psychometrics
import
psychoanalyze
from
psychometrics
import
psychoanalyze
from
student.models
import
UserProfile
from
student.models
import
CourseEnrollment
from
student.models
import
UserTestGroup
,
CourseEnrollment
from
util.cache
import
cache
,
cache_if_anonymous
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.course_module
import
CourseDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.exceptions
import
InvalidLocationError
,
ItemNotFoundError
,
NoPathToItem
from
xmodule.modulestore.exceptions
import
InvalidLocationError
,
ItemNotFoundError
,
NoPathToItem
from
xmodule.modulestore.search
import
path_to_location
from
xmodule.modulestore.search
import
path_to_location
import
track.views
log
=
logging
.
getLogger
(
"mitx.courseware"
)
log
=
logging
.
getLogger
(
"mitx.courseware"
)
template_imports
=
{
'urllib'
:
urllib
}
template_imports
=
{
'urllib'
:
urllib
}
# internal commands for managing forum roles:
FORUM_ROLE_ADD
=
'add'
FORUM_ROLE_REMOVE
=
'remove'
@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
instructor_dashboard
(
request
,
course_id
):
def
instructor_dashboard
(
request
,
course_id
):
"""Display the instructor dashboard for a course."""
"""Display the instructor dashboard for a course."""
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'staff'
)
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'staff'
)
instructor_access
=
has_access
(
request
.
user
,
course
,
'instructor'
)
# an instructor can manage staff lists
instructor_access
=
has_access
(
request
.
user
,
course
,
'instructor'
)
# an instructor can manage staff lists
forum_admin_access
=
has_forum_access
(
request
.
user
,
course_id
,
FORUM_ROLE_ADMINISTRATOR
)
msg
=
''
msg
=
''
#msg += ('POST=%s' % dict(request.POST)).replace('<','<')
problems
=
[]
problems
=
[]
plots
=
[]
plots
=
[]
...
@@ -81,7 +74,7 @@ def instructor_dashboard(request, course_id):
...
@@ -81,7 +74,7 @@ def instructor_dashboard(request, course_id):
def
return_csv
(
fn
,
datatable
):
def
return_csv
(
fn
,
datatable
):
response
=
HttpResponse
(
mimetype
=
'text/csv'
)
response
=
HttpResponse
(
mimetype
=
'text/csv'
)
response
[
'Content-Disposition'
]
=
'attachment; filename=
%
s'
%
fn
response
[
'Content-Disposition'
]
=
'attachment; filename=
{0}'
.
format
(
fn
)
writer
=
csv
.
writer
(
response
,
dialect
=
'excel'
,
quotechar
=
'"'
,
quoting
=
csv
.
QUOTE_ALL
)
writer
=
csv
.
writer
(
response
,
dialect
=
'excel'
,
quotechar
=
'"'
,
quoting
=
csv
.
QUOTE_ALL
)
writer
.
writerow
(
datatable
[
'header'
])
writer
.
writerow
(
datatable
[
'header'
])
for
datarow
in
datatable
[
'data'
]:
for
datarow
in
datatable
[
'data'
]:
...
@@ -104,75 +97,75 @@ def instructor_dashboard(request, course_id):
...
@@ -104,75 +97,75 @@ def instructor_dashboard(request, course_id):
if
settings
.
MITX_FEATURES
[
'ENABLE_MANUAL_GIT_RELOAD'
]:
if
settings
.
MITX_FEATURES
[
'ENABLE_MANUAL_GIT_RELOAD'
]:
if
'GIT pull'
in
action
:
if
'GIT pull'
in
action
:
data_dir
=
course
.
metadata
[
'data_dir'
]
data_dir
=
course
.
metadata
[
'data_dir'
]
log
.
debug
(
'git pull
%
s'
%
(
data_dir
))
log
.
debug
(
'git pull
{0}'
.
format
(
data_dir
))
gdir
=
settings
.
DATA_DIR
/
data_dir
gdir
=
settings
.
DATA_DIR
/
data_dir
if
not
os
.
path
.
exists
(
gdir
):
if
not
os
.
path
.
exists
(
gdir
):
msg
+=
"====> ERROR in gitreload - no such directory
%
s"
%
gdir
msg
+=
"====> ERROR in gitreload - no such directory
{0}"
.
format
(
gdir
)
else
:
else
:
cmd
=
"cd
%
s; git reset --hard HEAD; git clean -f -d; git pull origin; chmod g+w course.xml"
%
gdir
cmd
=
"cd
{0}; git reset --hard HEAD; git clean -f -d; git pull origin; chmod g+w course.xml"
.
format
(
gdir
)
msg
+=
"git pull on
%
s:<p>"
%
data_dir
msg
+=
"git pull on
{0}:<p>"
.
format
(
data_dir
)
msg
+=
"<pre>
%
s</pre></p>"
%
escape
(
os
.
popen
(
cmd
)
.
read
(
))
msg
+=
"<pre>
{0}</pre></p>"
.
format
(
escape
(
os
.
popen
(
cmd
)
.
read
()
))
track
.
views
.
server_track
(
request
,
'git pull
%
s'
%
data_dir
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'git pull
{0}'
.
format
(
data_dir
)
,
{},
page
=
'idashboard'
)
if
'Reload course'
in
action
:
if
'Reload course'
in
action
:
log
.
debug
(
'reloading
%
s (
%
s)'
%
(
course_id
,
course
))
log
.
debug
(
'reloading
{0} ({1})'
.
format
(
course_id
,
course
))
try
:
try
:
data_dir
=
course
.
metadata
[
'data_dir'
]
data_dir
=
course
.
metadata
[
'data_dir'
]
modulestore
()
.
try_load_course
(
data_dir
)
modulestore
()
.
try_load_course
(
data_dir
)
msg
+=
"<br/><p>Course reloaded from
%
s</p>"
%
data_dir
msg
+=
"<br/><p>Course reloaded from
{0}</p>"
.
format
(
data_dir
)
track
.
views
.
server_track
(
request
,
'reload
%
s'
%
data_dir
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'reload
{0}'
.
format
(
data_dir
)
,
{},
page
=
'idashboard'
)
course_errors
=
modulestore
()
.
get_item_errors
(
course
.
location
)
course_errors
=
modulestore
()
.
get_item_errors
(
course
.
location
)
msg
+=
'<ul>'
msg
+=
'<ul>'
for
cmsg
,
cerr
in
course_errors
:
for
cmsg
,
cerr
in
course_errors
:
msg
+=
"<li>
%
s: <pre>
%
s</pre>"
%
(
cmsg
,
escape
(
cerr
))
msg
+=
"<li>
{0}: <pre>{1}</pre>"
.
format
(
cmsg
,
escape
(
cerr
))
msg
+=
'</ul>'
msg
+=
'</ul>'
except
Exception
as
err
:
except
Exception
as
err
:
msg
+=
'<br/><p>Error:
%
s</p>'
%
escape
(
err
)
msg
+=
'<br/><p>Error:
{0}</p>'
.
format
(
escape
(
err
)
)
if
action
==
'Dump list of enrolled students'
:
if
action
==
'Dump list of enrolled students'
:
log
.
debug
(
action
)
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
False
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
False
)
datatable
[
'title'
]
=
'List of students enrolled in
%
s'
%
course_id
datatable
[
'title'
]
=
'List of students enrolled in
{0}'
.
format
(
course_id
)
track
.
views
.
server_track
(
request
,
'list-students'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'list-students'
,
{},
page
=
'idashboard'
)
elif
'Dump Grades'
in
action
:
elif
'Dump Grades'
in
action
:
log
.
debug
(
action
)
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
)
datatable
[
'title'
]
=
'Summary Grades of students enrolled in
%
s'
%
course_id
datatable
[
'title'
]
=
'Summary Grades of students enrolled in
{0}'
.
format
(
course_id
)
track
.
views
.
server_track
(
request
,
'dump-grades'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'dump-grades'
,
{},
page
=
'idashboard'
)
elif
'Dump all RAW grades'
in
action
:
elif
'Dump all RAW grades'
in
action
:
log
.
debug
(
action
)
log
.
debug
(
action
)
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
,
datatable
=
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
,
get_raw_scores
=
True
)
get_raw_scores
=
True
)
datatable
[
'title'
]
=
'Raw Grades of students enrolled in
%
s'
%
course_id
datatable
[
'title'
]
=
'Raw Grades of students enrolled in
{0}'
.
format
(
course_id
)
track
.
views
.
server_track
(
request
,
'dump-grades-raw'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'dump-grades-raw'
,
{},
page
=
'idashboard'
)
elif
'Download CSV of all student grades'
in
action
:
elif
'Download CSV of all student grades'
in
action
:
track
.
views
.
server_track
(
request
,
'dump-grades-csv'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'dump-grades-csv'
,
{},
page
=
'idashboard'
)
return
return_csv
(
'grades_
%
s.csv'
%
course_id
,
return
return_csv
(
'grades_
{0}.csv'
.
format
(
course_id
)
,
get_student_grade_summary_data
(
request
,
course
,
course_id
))
get_student_grade_summary_data
(
request
,
course
,
course_id
))
elif
'Download CSV of all RAW grades'
in
action
:
elif
'Download CSV of all RAW grades'
in
action
:
track
.
views
.
server_track
(
request
,
'dump-grades-csv-raw'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'dump-grades-csv-raw'
,
{},
page
=
'idashboard'
)
return
return_csv
(
'grades_
%
s_raw.csv'
%
course_id
,
return
return_csv
(
'grades_
{0}_raw.csv'
.
format
(
course_id
)
,
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_raw_scores
=
True
))
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_raw_scores
=
True
))
elif
'Download CSV of answer distributions'
in
action
:
elif
'Download CSV of answer distributions'
in
action
:
track
.
views
.
server_track
(
request
,
'dump-answer-dist-csv'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'dump-answer-dist-csv'
,
{},
page
=
'idashboard'
)
return
return_csv
(
'answer_dist_
%
s.csv'
%
course_id
,
get_answers_distribution
(
request
,
course_id
))
return
return_csv
(
'answer_dist_
{0}.csv'
.
format
(
course_id
)
,
get_answers_distribution
(
request
,
course_id
))
#----------------------------------------
#----------------------------------------
# Admin
# Admin
elif
'List course staff'
in
action
:
elif
'List course staff'
in
action
:
group
=
get_staff_group
(
course
)
group
=
get_staff_group
(
course
)
msg
+=
'Staff group =
%
s'
%
group
.
name
msg
+=
'Staff group =
{0}'
.
format
(
group
.
name
)
log
.
debug
(
'staffgrp=
%
s'
%
group
.
name
)
log
.
debug
(
'staffgrp=
{0}'
.
format
(
group
.
name
)
)
uset
=
group
.
user_set
.
all
()
uset
=
group
.
user_set
.
all
()
datatable
=
{
'header'
:
[
'Username'
,
'Full name'
]}
datatable
=
{
'header'
:
[
'Username'
,
'Full name'
]}
datatable
[
'data'
]
=
[[
x
.
username
,
x
.
profile
.
name
]
for
x
in
uset
]
datatable
[
'data'
]
=
[[
x
.
username
,
x
.
profile
.
name
]
for
x
in
uset
]
datatable
[
'title'
]
=
'List of Staff in course
%
s'
%
course_id
datatable
[
'title'
]
=
'List of Staff in course
{0}'
.
format
(
course_id
)
track
.
views
.
server_track
(
request
,
'list-staff'
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'list-staff'
,
{},
page
=
'idashboard'
)
elif
action
==
'Add course staff'
:
elif
action
==
'Add course staff'
:
...
@@ -180,28 +173,86 @@ def instructor_dashboard(request, course_id):
...
@@ -180,28 +173,86 @@ def instructor_dashboard(request, course_id):
try
:
try
:
user
=
User
.
objects
.
get
(
username
=
uname
)
user
=
User
.
objects
.
get
(
username
=
uname
)
except
User
.
DoesNotExist
:
except
User
.
DoesNotExist
:
msg
+=
'<font color="red">Error: unknown username "
%
s"</font>'
%
uname
msg
+=
'<font color="red">Error: unknown username "
{0}"</font>'
.
format
(
uname
)
user
=
None
user
=
None
if
user
is
not
None
:
if
user
is
not
None
:
group
=
get_staff_group
(
course
)
group
=
get_staff_group
(
course
)
msg
+=
'<font color="green">Added
%
s to staff group =
%
s</font>'
%
(
user
,
group
.
name
)
msg
+=
'<font color="green">Added
{0} to staff group = {1}</font>'
.
format
(
user
,
group
.
name
)
log
.
debug
(
'staffgrp=
%
s'
%
group
.
name
)
log
.
debug
(
'staffgrp=
{0}'
.
format
(
group
.
name
)
)
user
.
groups
.
add
(
group
)
user
.
groups
.
add
(
group
)
track
.
views
.
server_track
(
request
,
'add-staff
%
s'
%
user
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'add-staff
{0}'
.
format
(
user
)
,
{},
page
=
'idashboard'
)
elif
action
==
'Remove course staff'
:
elif
action
==
'Remove course staff'
:
uname
=
request
.
POST
[
'staffuser'
]
uname
=
request
.
POST
[
'staffuser'
]
try
:
try
:
user
=
User
.
objects
.
get
(
username
=
uname
)
user
=
User
.
objects
.
get
(
username
=
uname
)
except
User
.
DoesNotExist
:
except
User
.
DoesNotExist
:
msg
+=
'<font color="red">Error: unknown username "
%
s"</font>'
%
uname
msg
+=
'<font color="red">Error: unknown username "
{0}"</font>'
.
format
(
uname
)
user
=
None
user
=
None
if
user
is
not
None
:
if
user
is
not
None
:
group
=
get_staff_group
(
course
)
group
=
get_staff_group
(
course
)
msg
+=
'<font color="green">Removed
%
s from staff group =
%
s</font>'
%
(
user
,
group
.
name
)
msg
+=
'<font color="green">Removed
{0} from staff group = {1}</font>'
.
format
(
user
,
group
.
name
)
log
.
debug
(
'staffgrp=
%
s'
%
group
.
name
)
log
.
debug
(
'staffgrp=
{0}'
.
format
(
group
.
name
)
)
user
.
groups
.
remove
(
group
)
user
.
groups
.
remove
(
group
)
track
.
views
.
server_track
(
request
,
'remove-staff
%
s'
%
user
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'remove-staff {0}'
.
format
(
user
),
{},
page
=
'idashboard'
)
#----------------------------------------
# forum administration
elif
action
==
'List course forum admins'
:
rolename
=
FORUM_ROLE_ADMINISTRATOR
datatable
=
{}
msg
+=
_list_course_forum_members
(
course_id
,
rolename
,
datatable
)
track
.
views
.
server_track
(
request
,
'list-{0}'
.
format
(
rolename
),
{},
page
=
'idashboard'
)
elif
action
==
'Remove forum admin'
:
uname
=
request
.
POST
[
'forumadmin'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_REMOVE
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_REMOVE
,
uname
,
FORUM_ROLE_ADMINISTRATOR
,
course_id
),
{},
page
=
'idashboard'
)
elif
action
==
'Add forum admin'
:
uname
=
request
.
POST
[
'forumadmin'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_ADD
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_ADD
,
uname
,
FORUM_ROLE_ADMINISTRATOR
,
course_id
),
{},
page
=
'idashboard'
)
elif
action
==
'List course forum moderators'
:
rolename
=
FORUM_ROLE_MODERATOR
datatable
=
{}
msg
+=
_list_course_forum_members
(
course_id
,
rolename
,
datatable
)
track
.
views
.
server_track
(
request
,
'list-{0}'
.
format
(
rolename
),
{},
page
=
'idashboard'
)
elif
action
==
'Remove forum moderator'
:
uname
=
request
.
POST
[
'forummoderator'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_REMOVE
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_REMOVE
,
uname
,
FORUM_ROLE_MODERATOR
,
course_id
),
{},
page
=
'idashboard'
)
elif
action
==
'Add forum moderator'
:
uname
=
request
.
POST
[
'forummoderator'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_ADD
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_ADD
,
uname
,
FORUM_ROLE_MODERATOR
,
course_id
),
{},
page
=
'idashboard'
)
elif
action
==
'List course forum community TAs'
:
rolename
=
FORUM_ROLE_COMMUNITY_TA
datatable
=
{}
msg
+=
_list_course_forum_members
(
course_id
,
rolename
,
datatable
)
track
.
views
.
server_track
(
request
,
'list-{0}'
.
format
(
rolename
),
{},
page
=
'idashboard'
)
elif
action
==
'Remove forum community TA'
:
uname
=
request
.
POST
[
'forummoderator'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_REMOVE
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_REMOVE
,
uname
,
FORUM_ROLE_COMMUNITY_TA
,
course_id
),
{},
page
=
'idashboard'
)
elif
action
==
'Add forum community TA'
:
uname
=
request
.
POST
[
'forummoderator'
]
msg
+=
_update_forum_role_membership
(
uname
,
course
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_ADD
)
track
.
views
.
server_track
(
request
,
'{0} {1} as {2} for {3}'
.
format
(
FORUM_ROLE_ADD
,
uname
,
FORUM_ROLE_COMMUNITY_TA
,
course_id
),
{},
page
=
'idashboard'
)
#----------------------------------------
#----------------------------------------
# psychometrics
# psychometrics
...
@@ -210,17 +261,20 @@ def instructor_dashboard(request, course_id):
...
@@ -210,17 +261,20 @@ def instructor_dashboard(request, course_id):
problem
=
request
.
POST
[
'Problem'
]
problem
=
request
.
POST
[
'Problem'
]
nmsg
,
plots
=
psychoanalyze
.
generate_plots_for_problem
(
problem
)
nmsg
,
plots
=
psychoanalyze
.
generate_plots_for_problem
(
problem
)
msg
+=
nmsg
msg
+=
nmsg
track
.
views
.
server_track
(
request
,
'psychometrics
%
s'
%
problem
,
{},
page
=
'idashboard'
)
track
.
views
.
server_track
(
request
,
'psychometrics
{0}'
.
format
(
problem
)
,
{},
page
=
'idashboard'
)
if
idash_mode
==
'Psychometrics'
:
if
idash_mode
==
'Psychometrics'
:
problems
=
psychoanalyze
.
problems_with_psychometric_data
(
course_id
)
problems
=
psychoanalyze
.
problems_with_psychometric_data
(
course_id
)
#----------------------------------------
#----------------------------------------
# context for rendering
# context for rendering
context
=
{
'course'
:
course
,
context
=
{
'course'
:
course
,
'staff_access'
:
True
,
'staff_access'
:
True
,
'admin_access'
:
request
.
user
.
is_staff
,
'admin_access'
:
request
.
user
.
is_staff
,
'instructor_access'
:
instructor_access
,
'instructor_access'
:
instructor_access
,
'forum_admin_access'
:
forum_admin_access
,
'datatable'
:
datatable
,
'datatable'
:
datatable
,
'msg'
:
msg
,
'msg'
:
msg
,
'modeflag'
:
{
idash_mode
:
'selectedmode'
},
'modeflag'
:
{
idash_mode
:
'selectedmode'
},
...
@@ -232,6 +286,75 @@ def instructor_dashboard(request, course_id):
...
@@ -232,6 +286,75 @@ def instructor_dashboard(request, course_id):
return
render_to_response
(
'courseware/instructor_dashboard.html'
,
context
)
return
render_to_response
(
'courseware/instructor_dashboard.html'
,
context
)
def
_list_course_forum_members
(
course_id
,
rolename
,
datatable
):
'''
Fills in datatable with forum membership information, for a given role,
so that it will be displayed on instructor dashboard.
course_ID = course's ID string
rolename = one of "Administrator", "Moderator", "Community TA"
Returns message status string to append to displayed message, if role is unknown.
'''
# make sure datatable is set up properly for display first, before checking for errors
datatable
[
'header'
]
=
[
'Username'
,
'Full name'
,
'Roles'
]
datatable
[
'title'
]
=
'List of Forum {0}s in course {1}'
.
format
(
rolename
,
course_id
)
datatable
[
'data'
]
=
[];
try
:
role
=
Role
.
objects
.
get
(
name
=
rolename
,
course_id
=
course_id
)
except
Role
.
DoesNotExist
:
return
'<font color="red">Error: unknown rolename "{0}"</font>'
.
format
(
rolename
)
uset
=
role
.
users
.
all
()
.
order_by
(
'username'
)
msg
=
'Role = {0}'
.
format
(
rolename
)
log
.
debug
(
'role={0}'
.
format
(
rolename
))
datatable
[
'data'
]
=
[[
x
.
username
,
x
.
profile
.
name
,
', '
.
join
([
r
.
name
for
r
in
x
.
roles
.
filter
(
course_id
=
course_id
)
.
order_by
(
'name'
)])]
for
x
in
uset
]
return
msg
def
_update_forum_role_membership
(
uname
,
course
,
rolename
,
add_or_remove
):
'''
Supports adding a user to a course's forum role
uname = username string for user
course = course object
rolename = one of "Administrator", "Moderator", "Community TA"
add_or_remove = one of "add" or "remove"
Returns message status string to append to displayed message, Status is returned if user
or role is unknown, or if entry already exists when adding, or if entry doesn't exist when removing.
'''
# check that username and rolename are valid:
try
:
user
=
User
.
objects
.
get
(
username
=
uname
)
except
User
.
DoesNotExist
:
return
'<font color="red">Error: unknown username "{0}"</font>'
.
format
(
uname
)
try
:
role
=
Role
.
objects
.
get
(
name
=
rolename
,
course_id
=
course
.
id
)
except
Role
.
DoesNotExist
:
return
'<font color="red">Error: unknown rolename "{0}"</font>'
.
format
(
rolename
)
# check whether role already has the specified user:
alreadyexists
=
role
.
users
.
filter
(
username
=
uname
)
.
exists
()
msg
=
''
log
.
debug
(
'rolename={0}'
.
format
(
rolename
))
if
add_or_remove
==
FORUM_ROLE_REMOVE
:
if
not
alreadyexists
:
msg
=
'<font color="red">Error: user "{0}" does not have rolename "{1}", cannot remove</font>'
.
format
(
uname
,
rolename
)
else
:
user
.
roles
.
remove
(
role
)
msg
=
'<font color="green">Removed "{0}" from "{1}" forum role = "{2}"</font>'
.
format
(
user
,
course
.
id
,
rolename
)
else
:
if
alreadyexists
:
msg
=
'<font color="red">Error: user "{0}" already has rolename "{1}", cannot add</font>'
.
format
(
uname
,
rolename
)
else
:
if
(
rolename
==
FORUM_ROLE_ADMINISTRATOR
and
not
has_access
(
user
,
course
,
'staff'
)):
msg
=
'<font color="red">Error: user "{0}" should first be added as staff before adding as a forum administrator, cannot add</font>'
.
format
(
uname
)
else
:
user
.
roles
.
add
(
role
)
msg
=
'<font color="green">Added "{0}" to "{1}" forum role = "{2}"</font>'
.
format
(
user
,
course
.
id
,
rolename
)
return
msg
def
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
,
get_raw_scores
=
False
):
def
get_student_grade_summary_data
(
request
,
course
,
course_id
,
get_grades
=
True
,
get_raw_scores
=
False
):
'''
'''
...
@@ -257,7 +380,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
...
@@ -257,7 +380,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
if
get_grades
:
if
get_grades
:
# just to construct the header
# just to construct the header
gradeset
=
grades
.
grade
(
enrolled_students
[
0
],
request
,
course
,
keep_raw_scores
=
get_raw_scores
)
gradeset
=
grades
.
grade
(
enrolled_students
[
0
],
request
,
course
,
keep_raw_scores
=
get_raw_scores
)
# log.debug('student
%s gradeset %s' %
(enrolled_students[0], gradeset))
# log.debug('student
{0} gradeset {1}'.format
(enrolled_students[0], gradeset))
if
get_raw_scores
:
if
get_raw_scores
:
header
+=
[
score
.
section
for
score
in
gradeset
[
'raw_scores'
]]
header
+=
[
score
.
section
for
score
in
gradeset
[
'raw_scores'
]]
else
:
else
:
...
@@ -275,7 +398,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
...
@@ -275,7 +398,7 @@ def get_student_grade_summary_data(request, course, course_id, get_grades=True,
if
get_grades
:
if
get_grades
:
gradeset
=
grades
.
grade
(
student
,
request
,
course
,
keep_raw_scores
=
get_raw_scores
)
gradeset
=
grades
.
grade
(
student
,
request
,
course
,
keep_raw_scores
=
get_raw_scores
)
# log.debug('student=
%s, gradeset=%s' %
(student,gradeset))
# log.debug('student=
{0}, gradeset={1}'.format
(student,gradeset))
if
get_raw_scores
:
if
get_raw_scores
:
datarow
+=
[
score
.
earned
for
score
in
gradeset
[
'raw_scores'
]]
datarow
+=
[
score
.
earned
for
score
in
gradeset
[
'raw_scores'
]]
else
:
else
:
...
...
lms/templates/courseware/instructor_dashboard.html
View file @
c341975b
...
@@ -56,7 +56,8 @@ function goto( mode)
...
@@ -56,7 +56,8 @@ function goto( mode)
%if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'):
%if settings.MITX_FEATURES.get('ENABLE_PSYCHOMETRICS'):
<a
href=
"#"
onclick=
"goto('Psychometrics');"
class=
"${modeflag.get('Psychometrics')}"
>
Psychometrics
</a>
|
<a
href=
"#"
onclick=
"goto('Psychometrics');"
class=
"${modeflag.get('Psychometrics')}"
>
Psychometrics
</a>
|
%endif
%endif
<a
href=
"#"
onclick=
"goto('Admin');"
class=
"${modeflag.get('Admin')}"
>
Admin
</a>
]
<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>
]
</h2>
</h2>
<div
style=
"text-align:right"
id=
"djangopid"
>
${djangopid}
</div>
<div
style=
"text-align:right"
id=
"djangopid"
>
${djangopid}
</div>
...
@@ -134,6 +135,34 @@ function goto( mode)
...
@@ -134,6 +135,34 @@ function goto( mode)
%endif
%endif
%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
</form>
</form>
##-----------------------------------------------------------------------------
##-----------------------------------------------------------------------------
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment