Commit b8d50e51 by Matthew Mongeau

Course navigation work

parent a63a9387
......@@ -67,7 +67,7 @@ def info(request, course_id=None):
# We're bypassing the templating system for this part. We should cache
# this.
sections = ["updates", "handouts", "guest_updates", "guest_handouts"]
sections_to_content = {}
sections_to_content = { 'course': course }
for section in sections:
filename = section + ".html"
with open(course.path / "info" / filename) as f:
......
......@@ -137,20 +137,20 @@ def user_groups(user):
# return [u.name for u in UserTestGroup.objects.raw("select * from auth_user, student_usertestgroup, student_usertestgroup_users where auth_user.id = student_usertestgroup_users.user_id and student_usertestgroup_users.usertestgroup_id = student_usertestgroup.id and auth_user.id = %s", [user.id])]
def replace_custom_tags(tree):
tags = os.listdir(settings.DATA_DIR+'/custom_tags')
def replace_custom_tags(course, tree):
tags = os.listdir(course.path+'/custom_tags')
for tag in tags:
for element in tree.iter(tag):
element.tag = 'customtag'
impl = etree.SubElement(element, 'impl')
impl.text = tag
def course_xml_process(tree):
def course_xml_process(course, tree):
''' Do basic pre-processing of an XML tree. Assign IDs to all
items without. Propagate due dates, grace periods, etc. to child
items.
'''
replace_custom_tags(tree)
replace_custom_tags(course, tree)
id_tag(tree)
propogate_downward_tag(tree, "due")
propogate_downward_tag(tree, "graded")
......@@ -159,18 +159,18 @@ def course_xml_process(tree):
propogate_downward_tag(tree, "rerandomize")
return tree
def course_file(user,coursename=None):
def course_file(user,course=None):
''' Given a user, return course.xml'''
if user.is_authenticated():
filename = UserProfile.objects.get(user=user).courseware # user.profile_cache.courseware
filename = os.path.basename(course.path)+"/"+UserProfile.objects.get(user=user).courseware # user.profile_cache.courseware
else:
filename = 'guest_course.xml'
# if a specific course is specified, then use multicourse to get the right path to the course XML directory
if coursename and settings.ENABLE_MULTICOURSE:
xp = multicourse_settings.get_course_xmlpath(coursename)
filename = xp + filename # prefix the filename with the path
# if coursename and settings.ENABLE_MULTICOURSE:
# xp = multicourse_settings.get_course_xmlpath(coursename)
# filename = xp + filename # prefix the filename with the path
groups = user_groups(user)
options = {'dev_content':settings.DEV_CONTENT,
......@@ -188,7 +188,7 @@ def course_file(user,coursename=None):
# print '[courseware.content_parser.course_file] tree_string = ',tree_string
if not tree_string:
tree = course_xml_process(etree.XML(render_to_string(filename, options, namespace = 'course')))
tree = course_xml_process(course, etree.XML(render_to_string(filename, options, namespace = 'course')))
tree_string = etree.tostring(tree)
cache.set(cache_key, tree_string, 60)
......@@ -197,7 +197,7 @@ def course_file(user,coursename=None):
return tree
def section_file(user, section, coursename=None, dironly=False):
def section_file(user, section, course=None, dironly=False):
'''
Given a user and the name of a section, return that section.
This is done specific to each course.
......@@ -221,7 +221,7 @@ def section_file(user, section, coursename=None, dironly=False):
options = {'dev_content':settings.DEV_CONTENT,
'groups' : user_groups(user)}
tree = course_xml_process(etree.XML(render_to_string(filename, options, namespace = 'sections')))
tree = course_xml_process(course, etree.XML(render_to_string(filename, options, namespace = 'sections')))
return tree
......
......@@ -67,7 +67,7 @@ course_settings = Settings()
def grade_sheet(student,coursename=None):
def grade_sheet(student,course=None):
"""
This pulls a summary of all problems in the course. It returns a dictionary with two datastructures:
......@@ -77,9 +77,9 @@ def grade_sheet(student,coursename=None):
- grade_summary is the output from the course grader. More information on the format is in the docstring for CourseGrader.
"""
dom=content_parser.course_file(student,coursename)
course = dom.xpath('//course/@name')[0]
xmlChapters = dom.xpath('//course[@name=$course]/chapter', course=course)
dom=content_parser.course_file(student,course)
dom_course = dom.xpath('//course/@name')[0]
xmlChapters = dom.xpath('//course[@name=$course]/chapter', course=dom_course)
responses=StudentModule.objects.filter(student=student)
response_by_id = {}
......@@ -95,15 +95,15 @@ def grade_sheet(student,coursename=None):
for s in dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section',
course=course, chname=chname):
course=dom_course, chname=chname):
problems=dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section[@name=$section]//problem',
course=course, chname=chname, section=s.get('name'))
course=dom_course, chname=chname, section=s.get('name'))
graded = True if s.get('graded') == "true" else False
scores=[]
if len(problems)>0:
for p in problems:
(correct,total) = get_score(student, p, response_by_id, coursename=coursename)
(correct,total) = get_score(student, p, response_by_id, course=course)
if settings.GENERATE_PROFILE_SCORES:
if total > 1:
......@@ -146,7 +146,7 @@ def grade_sheet(student,coursename=None):
return {'courseware_summary' : chapters,
'grade_summary' : grade_summary}
def get_score(user, problem, cache, coursename=None):
def get_score(user, problem, cache, course=None):
## HACK: assumes max score is fixed per problem
id = problem.get('id')
correct = 0.0
......@@ -177,7 +177,7 @@ def get_score(user, problem, cache, coursename=None):
# TODO: These are no longer correct params for I4xSystem -- figure out what this code
# does, clean it up.
from module_render import I4xSystem
system = I4xSystem(None, None, None, coursename=coursename)
system = I4xSystem(None, None, None, course=course)
total=float(xmodule.capa_module.Module(system, etree.tostring(problem), "id").max_score())
response.max_grade = total
response.save()
......
......@@ -35,7 +35,7 @@ class I4xSystem(object):
'''
def __init__(self, ajax_url, track_function, render_function,
module_from_xml, render_template, request=None,
filestore=None):
filestore=None, course=None):
'''
Create a closure around the system environment.
......@@ -56,6 +56,7 @@ class I4xSystem(object):
filestore - A filestore ojbect. Defaults to an instance of OSFS based at
settings.DATA_DIR.
'''
self.course = course
self.ajax_url = ajax_url
self.track_function = track_function
if not filestore:
......@@ -169,14 +170,14 @@ def get_module(user, request, module_xml, student_module_cache, position=None):
state = smod.state if smod else None
# get coursename if present in request
coursename = multicourse_settings.get_coursename_from_request(request)
if coursename and settings.ENABLE_MULTICOURSE:
# path to XML for the course
xp = multicourse_settings.get_course_xmlpath(coursename)
data_root = settings.DATA_DIR + xp
else:
data_root = settings.DATA_DIR
# coursename = multicourse_settings.get_coursename_from_request(request)
# if coursename and settings.ENABLE_MULTICOURSE:
# # path to XML for the course
# xp = multicourse_settings.get_course_xmlpath(coursename)
# data_root = settings.DATA_DIR + xp
# else:
data_root = settings.DATA_DIR+"/"+os.path.basename(course.path)
# Setup system context for module instance
ajax_url = settings.MITX_ROOT_URL + '/modx/' + module_type + '/' + module_id + '/'
......
......@@ -46,24 +46,24 @@ def gradebook(request):
if 'course_admin' not in content_parser.user_groups(request.user):
raise Http404
coursename = multicourse_settings.get_coursename_from_request(request)
course = settings.COURSES_BY_ID[course_id]
student_objects = User.objects.all()[:100]
student_info = [{'username': s.username,
'id': s.id,
'email': s.email,
'grade_info': grades.grade_sheet(s, coursename),
'grade_info': grades.grade_sheet(s, course),
'realname': UserProfile.objects.get(user = s).name
} for s in student_objects]
return render_to_response('gradebook.html', {'students': student_info})
return render_to_response('gradebook.html', {'students': student_info, 'course': course})
@login_required
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
def profile(request, student_id=None):
def profile(request, course_id=None, student_id=None):
''' User profile. Show username, location, etc, as well as grades .
We need to allow the user to change some of these settings .'''
course = settings.COURSES_BY_ID[course_id]
if student_id is None:
student = request.user
else:
......@@ -73,17 +73,18 @@ def profile(request, student_id=None):
user_info = UserProfile.objects.get(user=student) # request.user.profile_cache #
coursename = multicourse_settings.get_coursename_from_request(request)
# coursename = multicourse_settings.get_coursename_from_request(request)
context = {'name': user_info.name,
'username': student.username,
'location': user_info.location,
'language': user_info.language,
'email': student.email,
'course': course,
'format_url_params': content_parser.format_url_params,
'csrf': csrf(request)['csrf_token']
}
context.update(grades.grade_sheet(student, coursename))
context.update(grades.grade_sheet(student, course))
return render_to_response('profile.html', context)
......@@ -95,8 +96,8 @@ def render_accordion(request, course, chapter, section):
If chapter and section are '' or None, renders a default accordion.
Returns (initialization_javascript, content)'''
if not course:
course = "6.002 Spring 2012"
# if not course:
# course = "6.002 Spring 2012"
toc = content_parser.toc_from_xml(
content_parser.course_file(request.user, course), chapter, section)
......@@ -106,9 +107,11 @@ def render_accordion(request, course, chapter, section):
if toc[i]['active']:
active_chapter = i
log.info(course.title)
context=dict([('active_chapter', active_chapter),
('toc', toc),
('course_name', course),
('course_name', course.title),
('course_id', course.id),
('format_url_params', content_parser.format_url_params),
('csrf', csrf(request)['csrf_token'])] +
template_imports.items())
......@@ -133,7 +136,7 @@ def render_section(request, section):
context = {
'csrf': csrf(request)['csrf_token'],
'accordion': render_accordion(request, '', '', '')
'accordion': render_accordion(request, course, '', '')
}
module_ids = dom.xpath("//@id")
......@@ -288,12 +291,16 @@ def index(request, course=None, chapter=None, section=None,
if not settings.COURSEWARE_ENABLED:
return redirect('/')
course = clean(get_course(request, course))
if not multicourse_settings.is_valid_course(course):
return redirect('/')
# course = clean(get_course(request, course))
# if not multicourse_settings.is_valid_course(course):
# return redirect('/')
try:
course = settings.COURSES_BY_ID[course_id]
except KeyError:
raise Http404("Course not found")
# keep track of current course being viewed in django's request.session
request.session['coursename'] = course
request.session['coursename'] = course.title
chapter = clean(chapter)
section = clean(section)
......@@ -301,7 +308,8 @@ def index(request, course=None, chapter=None, section=None,
context = {
'csrf': csrf(request)['csrf_token'],
'accordion': render_accordion(request, course, chapter, section),
'COURSE_TITLE': multicourse_settings.get_course_title(course),
'COURSE_TITLE': course.title,
'course': course,
'init': '',
'content': ''
}
......
from django.contrib.auth.decorators import login_required
from mitxmako.shortcuts import render_to_response
from django.conf import settings
@login_required
def index(request, page=0):
return render_to_response('staticbook.html',{'page':int(page)})
def index(request, course_id=None, page=0):
course = settings.COURSES_BY_ID[course_id]
return render_to_response('staticbook.html',{'page':int(page), 'course': course})
def index_shifted(request, page):
return index(request, int(page)+24)
......@@ -6,19 +6,22 @@ def url_class(url):
return "active"
return ""
%>
<%!
from django.core.urlresolvers import reverse
%>
<nav class="${active_page} course-material">
<div class="inner-wrapper">
<ol class="course-tabs">
<li class="courseware"><a href="${ MITX_ROOT_URL }/courseware/" class="${url_class('courseware')}">Courseware</a></li>
<li class="info"><a href="${ MITX_ROOT_URL }/info" class="${url_class('info')}">Course Info</a></li>
<li class="courseware"><a href="${reverse('courseware', args=[course.id])}" class="${url_class('courseware')}">Courseware</a></li>
<li class="info"><a href="${reverse('info', args=[course.id])}" class="${url_class('info')}">Course Info</a></li>
% if user.is_authenticated():
<li class="book"><a href="${ MITX_ROOT_URL }/book" class="${url_class('book')}">Textbook</a></li>
<li class="book"><a href="${reverse('book', args=[course.id])}" class="${url_class('book')}">Textbook</a></li>
<li class="discussion"><a href="${ MITX_ROOT_URL }/discussion/questions/">Discussion</a></li>
% endif
<li class="wiki"><a href="${ MITX_ROOT_URL }/wiki/view/" class="${url_class('wiki')}">Wiki</a></li>
<li class="wiki"><a href="${reverse('wiki_root')}" class="${url_class('wiki')}">Wiki</a></li>
% if user.is_authenticated():
<li class="profile"><a href="${ MITX_ROOT_URL }/profile" class="${url_class('profile')}">Profile</a></li>
<li class="profile"><a href="${reverse('profile', args=[course.id])}" class="${url_class('profile')}">Profile</a></li>
% endif
</ol>
</div>
......
......@@ -49,18 +49,15 @@ if settings.PERFSTATS:
if settings.COURSEWARE_ENABLED:
urlpatterns += (
url(r'^courseware/$', 'courseware.views.index', name="courseware"),
url(r'^wiki/', include('simplewiki.urls')),
url(r'^masquerade/', include('masquerade.urls')),
url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/(?P<section>[^/]*)/(?P<position>[^/]*)$', 'courseware.views.index'),
url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/(?P<section>[^/]*)/$', 'courseware.views.index', name="courseware_section"),
# url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/(?P<section>[^/]*)/$', 'courseware.views.index', name="courseware_section"),
url(r'^courseware/(?P<course>[^/]*)/(?P<chapter>[^/]*)/$', 'courseware.views.index', name="courseware_chapter"),
url(r'^courseware/(?P<course>[^/]*)/$', 'courseware.views.index', name="courseware_course"),
url(r'^jumpto/(?P<probname>[^/]+)/$', 'courseware.views.jump_to'),
url(r'^section/(?P<section>[^/]*)/$', 'courseware.views.render_section'),
url(r'^modx/(?P<module>[^/]*)/(?P<id>[^/]*)/(?P<dispatch>[^/]*)$', 'courseware.module_render.modx_dispatch'), #reset_problem'),
url(r'^profile$', 'courseware.views.profile'),
url(r'^profile/(?P<student_id>[^/]*)/$', 'courseware.views.profile'),
url(r'^change_setting$', 'student.views.change_setting'),
url(r'^s/(?P<template>[^/]*)$', 'static_template_view.views.auth_index'),
url(r'^book/(?P<page>[^/]*)$', 'staticbook.views.index'),
......@@ -75,8 +72,12 @@ if settings.COURSEWARE_ENABLED:
# Multicourse related:
url(r'^courses$', 'courseware.views.courses'),
url(r'^courses/(?P<course_id>[^/]*)/info$', 'util.views.info'),
url(r'^courses/(?P<course_id>[^/]*)/courseware$', 'courseware.views.index'),
url(r'^courses/(?P<course_id>[^/]*)/info$', 'util.views.info', name="info"),
url(r'^courses/(?P<course_id>[^/]*)/book$', 'staticbook.views.index', name="book"),
url(r'^courses/(?P<course_id>[^/]*)/courseware/?$', 'courseware.views.index', name="courseware"),
url(r'^courses/(?P<course_id>[^/]*)/courseware/(?P<chapter>[^/]*)/(?P<section>[^/]*)/$', 'courseware.views.index', name="courseware_section"),
url(r'^courses/(?P<course_id>[^/]*)/profile$', 'courseware.views.profile', name="profile"),
url(r'^courses/(?P<course_id>[^/]*)/profile/(?P<student_id>[^/]*)/$', 'courseware.views.profile'),
)
......
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