From 1cfed46d06b0aebe9a29062478b64b8b59b04504 Mon Sep 17 00:00:00 2001 From: Arjun Singh Date: Tue, 21 Aug 2012 05:47:26 -0700 Subject: [PATCH 1/3] Adding a syllabus page (accessible via course navigation) --- lms/djangoapps/courseware/courses.py | 26 ++++++++ lms/djangoapps/courseware/views.py | 12 ++++ lms/envs/common.py | 1 + lms/static/sass/course.scss | 1 + lms/static/sass/course/_syllabus.scss | 64 +++++++++++++++++++ .../courseware/course_navigation.html | 3 + lms/templates/courseware/syllabus.html | 24 +++++++ lms/urls.py | 2 + 8 files changed, 133 insertions(+) create mode 100644 lms/static/sass/course/_syllabus.scss create mode 100644 lms/templates/courseware/syllabus.html diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index b4407b7f93..62d05cbc04 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -142,6 +142,32 @@ def get_course_info_section(course, section_key): raise KeyError("Invalid about key " + str(section_key)) +def get_course_syllabus_section(course, section_key): + """ + This returns the snippet of html to be rendered on the syllabus page, + given the key for the section. + + Valid keys: + - syllabus + - guest_syllabus + """ + + # Many of these are stored as html files instead of some semantic + # markup. This can change without effecting this interface when we find a + # good format for defining so many snippets of text/html. + + if section_key in ['syllabus', 'guest_syllabus']: + try: + with course.system.resources_fs.open(path("syllabus") / section_key + ".html") as htmlFile: + return replace_urls(htmlFile.read().decode('utf-8'), + course.metadata['data_dir']) + except ResourceNotFoundError: + log.exception("Missing syllabus section {key} in course {url}".format( + key=section_key, url=course.location.url())) + return "! Syllabus missing !" + + raise KeyError("Invalid about key " + str(section_key)) + def get_courses_by_university(user, domain=None): ''' diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 2ab6fa0223..73529a5f88 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -219,6 +219,18 @@ def course_info(request, course_id): return render_to_response('courseware/info.html', {'course': course, 'staff_access': staff_access,}) +@ensure_csrf_cookie +def syllabus(request, course_id): + """ + Display the course's syllabus.html, or 404 if there is no such course. + + Assumes the course_id is in a valid format. + """ + course = get_course_with_access(request.user, course_id, 'load') + staff_access = has_access(request.user, course, 'staff') + + return render_to_response('courseware/syllabus.html', {'course': course, + 'staff_access': staff_access,}) def registered_for_course(course, user): '''Return CourseEnrollment if user is registered for course, else False''' diff --git a/lms/envs/common.py b/lms/envs/common.py index 52cb8c7d06..2561ad7f61 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -56,6 +56,7 @@ MITX_FEATURES = { 'ENABLE_TEXTBOOK' : True, 'ENABLE_DISCUSSION' : True, + 'ENABLE_SYLLABUS' : True, 'ENABLE_SQL_TRACKING_LOGS': False, 'ENABLE_LMS_MIGRATION': False, diff --git a/lms/static/sass/course.scss b/lms/static/sass/course.scss index d3a74cb91b..054e403289 100644 --- a/lms/static/sass/course.scss +++ b/lms/static/sass/course.scss @@ -29,6 +29,7 @@ // pages @import "course/info"; +@import "course/syllabus"; @import "course/textbook"; @import "course/profile"; @import "course/gradebook"; diff --git a/lms/static/sass/course/_syllabus.scss b/lms/static/sass/course/_syllabus.scss new file mode 100644 index 0000000000..2f2b9eedcd --- /dev/null +++ b/lms/static/sass/course/_syllabus.scss @@ -0,0 +1,64 @@ +div.syllabus { + + padding: 0px 10px; + + text-align: center; + + h1 { + @extend .top-header + } + + .notes { + width: 740px; + margin: 0px auto 10px; + } + + table { + + text-align: left; + + margin: 10px auto; + + thead { + font-weight: bold; + border-bottom: 1px solid black; + } + + tr.first { + td { + padding-top: 15px; + } + } + + td { + + vertical-align: middle; + + padding: 5px 10px; + + &.day, &.due { + white-space: nowrap; + } + + &.no_class { + text-align: center; + } + + &.important { + color: red; + } + + &.week_separator { + padding: 0px; + + hr { + margin: 10px; + } + + } + + } + + } + +} diff --git a/lms/templates/courseware/course_navigation.html b/lms/templates/courseware/course_navigation.html index 3b329c4832..7567e682dd 100644 --- a/lms/templates/courseware/course_navigation.html +++ b/lms/templates/courseware/course_navigation.html @@ -19,6 +19,9 @@ def url_class(url):
  1. Courseware
  2. Course Info
  3. +% if settings.MITX_FEATURES.get('ENABLE_SYLLABUS'): +
  4. Syllabus
  5. +% endif % if user.is_authenticated(): % if settings.MITX_FEATURES.get('ENABLE_TEXTBOOK'): % for index, textbook in enumerate(course.textbooks): diff --git a/lms/templates/courseware/syllabus.html b/lms/templates/courseware/syllabus.html new file mode 100644 index 0000000000..38c1fbd6f8 --- /dev/null +++ b/lms/templates/courseware/syllabus.html @@ -0,0 +1,24 @@ +<%inherit file="/main.html" /> +<%namespace name='static' file='/static_content.html'/> + +<%block name="headextra"> + <%static:css group='course'/> + + +<%block name="title">${course.number} Course Info + +<%include file="/courseware/course_navigation.html" args="active_page='syllabus'" /> +<%! + from courseware.courses import get_course_syllabus_section +%> + +
    +
    +

    Syllabus

    + % if user.is_authenticated(): + ${get_course_syllabus_section(course, 'syllabus')} + % else: + ${get_course_syllabus_section(course, 'guest_syllabus')} + % endif +
    +
    diff --git a/lms/urls.py b/lms/urls.py index a3c6c9cdad..9bf021ea04 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -126,6 +126,8 @@ if settings.COURSEWARE_ENABLED: #Inside the course url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/info$', 'courseware.views.course_info', name="info"), + url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/syllabus$', + 'courseware.views.syllabus', name="syllabus"), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/book/(?P[^/]*)/$', 'staticbook.views.index', name="book"), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/book/(?P[^/]*)/(?P[^/]*)$', From b86fbdbd108b0aae353b481a9628ae58c017fca8 Mon Sep 17 00:00:00 2001 From: Arjun Singh Date: Tue, 21 Aug 2012 13:23:00 -0700 Subject: [PATCH 2/3] Adding comments about removing the syllabus tab ASAP. --- lms/djangoapps/courseware/courses.py | 3 +++ lms/envs/common.py | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 62d05cbc04..d975f48564 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -142,6 +142,9 @@ def get_course_info_section(course, section_key): raise KeyError("Invalid about key " + str(section_key)) +# TODO: Fix this such that these are pulled in as extra course-specific tabs. +# arjun will address this by the end of October if no one does so prior to +# then. def get_course_syllabus_section(course, section_key): """ This returns the snippet of html to be rendered on the syllabus page, diff --git a/lms/envs/common.py b/lms/envs/common.py index 464716940b..d6636282c7 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -55,8 +55,11 @@ MITX_FEATURES = { # course_ids (see dev_int.py for an example) 'SUBDOMAIN_COURSE_LISTINGS' : False, + # TODO: This will be removed once course-specific tabs are in place. see + # courseware/courses.py + 'ENABLE_SYLLABUS' : True, + 'ENABLE_TEXTBOOK' : True, - 'ENABLE_SYLLABUS' : True, 'ENABLE_DISCUSSION' : False, 'ENABLE_DISCUSSION_SERVICE': True, From 02ecfb473001efeb5f985150d99e074eb23f957a Mon Sep 17 00:00:00 2001 From: Arjun Singh Date: Tue, 21 Aug 2012 13:25:29 -0700 Subject: [PATCH 3/3] Adding comments about removing the syllabus tab ASAP. --- lms/djangoapps/courseware/views.py | 1 + lms/static/sass/course.scss | 2 +- lms/urls.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 446dd36064..460e8fd42f 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -233,6 +233,7 @@ def course_info(request, course_id): return render_to_response('courseware/info.html', {'course': course, 'staff_access': staff_access,}) +# TODO arjun: remove when custom tabs in place, see courseware/syllabus.py @ensure_csrf_cookie def syllabus(request, course_id): """ diff --git a/lms/static/sass/course.scss b/lms/static/sass/course.scss index 054e403289..93296aead6 100644 --- a/lms/static/sass/course.scss +++ b/lms/static/sass/course.scss @@ -29,7 +29,7 @@ // pages @import "course/info"; -@import "course/syllabus"; +@import "course/syllabus"; // TODO arjun replace w/ custom tabs, see courseware/courses.py @import "course/textbook"; @import "course/profile"; @import "course/gradebook"; diff --git a/lms/urls.py b/lms/urls.py index f65e45cc7a..9c3baf2f41 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -127,7 +127,7 @@ if settings.COURSEWARE_ENABLED: url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/info$', 'courseware.views.course_info', name="info"), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/syllabus$', - 'courseware.views.syllabus', name="syllabus"), + 'courseware.views.syllabus', name="syllabus"), # TODO arjun remove when custom tabs in place, see courseware/courses.py url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/book/(?P[^/]*)/$', 'staticbook.views.index', name="book"), url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/book/(?P[^/]*)/(?P[^/]*)$',