diff --git a/common/djangoapps/external_auth/views.py b/common/djangoapps/external_auth/views.py index 35e59db0ca..9e41d31c77 100644 --- a/common/djangoapps/external_auth/views.py +++ b/common/djangoapps/external_auth/views.py @@ -157,7 +157,7 @@ def edXauth_signup(request, eamap=None): log.debug('ExtAuth: doing signup for %s' % eamap.external_email) - return student_views.main_index(request, extra_context=context) + return student_views.index(request, extra_context=context) #----------------------------------------------------------------------------- # MIT SSL @@ -193,7 +193,7 @@ def edXauth_ssl_login(request): The certificate provides user email and fullname; this populates the ExternalAuthMap. The user is nevertheless still asked to complete the edX signup. - Else continues on with student.views.main_index, and no authentication. + Else continues on with student.views.index, and no authentication. """ certkey = "SSL_CLIENT_S_DN" # specify the request.META field to use @@ -207,7 +207,7 @@ def edXauth_ssl_login(request): pass if not cert: # no certificate information - go onward to main index - return student_views.main_index(request) + return student_views.index(request) (user, email, fullname) = ssl_dn_extract_info(cert) @@ -217,4 +217,4 @@ def edXauth_ssl_login(request): credentials=cert, email=email, fullname=fullname, - retfun = functools.partial(student_views.main_index, request)) + retfun = functools.partial(student_views.index, request)) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 0069935b0b..e7864337b3 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -22,7 +22,6 @@ from django.db import IntegrityError from django.http import HttpResponse, Http404 from django.shortcuts import redirect from mitxmako.shortcuts import render_to_response, render_to_string -from django.core.urlresolvers import reverse from bs4 import BeautifulSoup from django.core.cache import cache @@ -30,7 +29,6 @@ from django_future.csrf import ensure_csrf_cookie from student.models import (Registration, UserProfile, PendingNameChange, PendingEmailChange, CourseEnrollment) -from util.cache import cache_if_anonymous from xmodule.course_module import CourseDescriptor from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.django import modulestore @@ -54,23 +52,7 @@ def csrf_token(context): ' name="csrfmiddlewaretoken" value="%s" />' % (csrf_token)) -@ensure_csrf_cookie -@cache_if_anonymous -def index(request): - - ''' Redirects to main page -- info page if user authenticated, or marketing if not - ''' - - if settings.COURSEWARE_ENABLED and request.user.is_authenticated(): - return redirect(reverse('dashboard')) - - if settings.MITX_FEATURES.get('AUTH_USE_MIT_CERTIFICATES'): - from external_auth.views import edXauth_ssl_login - return edXauth_ssl_login(request) - - return main_index(request, user=request.user) - -def main_index(request, extra_context={}, user=None): +def index(request, extra_context={}, user=None): ''' Render the edX main page. diff --git a/lms/djangoapps/branding/__init__.py b/lms/djangoapps/branding/__init__.py new file mode 100644 index 0000000000..3a4acd2964 --- /dev/null +++ b/lms/djangoapps/branding/__init__.py @@ -0,0 +1,52 @@ + +from xmodule.modulestore.django import modulestore +from xmodule.course_module import CourseDescriptor +from django.conf import settings + + +def get_subdomain(domain): + return domain.split(".")[0] + + +def get_visible_courses(domain=None): + """ + Return the set of CourseDescriptors that should be visible in this branded instance + """ + courses = [c for c in modulestore().get_courses() + if isinstance(c, CourseDescriptor)] + courses = sorted(courses, key=lambda course: course.number) + + if domain and settings.MITX_FEATURES.get('SUBDOMAIN_COURSE_LISTINGS'): + subdomain = get_subdomain(domain) + if subdomain not in settings.COURSE_LISTINGS: + subdomain = 'default' + visible_ids = frozenset(settings.COURSE_LISTINGS[subdomain]) + return [course for course in courses if course.id in visible_ids] + else: + return courses + + +def get_university(domain=None): + """ + Return the university name specified for the domain, or None + if no university was specified + """ + if not settings.MITX_FEATURES['SUBDOMAIN_BRANDING'] or domain is None: + return None + + subdomain = get_subdomain(domain) + return settings.SUBDOMAIN_BRANDING.get(subdomain) + + +def get_logo_url(domain=None): + """ + Return the url for the branded logo image to be used + """ + university = get_university(domain) + + if university is None: + return '/static/images/header-logo.png' + + return '/static/images/{uni}-on-edx-logo.png'.format( + uni=university + ) diff --git a/lms/djangoapps/branding/views.py b/lms/djangoapps/branding/views.py new file mode 100644 index 0000000000..e32eb92138 --- /dev/null +++ b/lms/djangoapps/branding/views.py @@ -0,0 +1,45 @@ +from django.conf import settings +from django.core.urlresolvers import reverse +from django.shortcuts import redirect +from django_future.csrf import ensure_csrf_cookie + +import student.views +import branding +import courseware.views +from util.cache import cache_if_anonymous + + +@ensure_csrf_cookie +@cache_if_anonymous +def index(request): + ''' + Redirects to main page -- info page if user authenticated, or marketing if not + ''' + + if settings.COURSEWARE_ENABLED and request.user.is_authenticated(): + return redirect(reverse('dashboard')) + + if settings.MITX_FEATURES.get('AUTH_USE_MIT_CERTIFICATES'): + from external_auth.views import edXauth_ssl_login + return edXauth_ssl_login(request) + + university = branding.get_university(request.META.get('HTTP_HOST')) + if university is None: + return student.views.index(request, user=request.user) + + return courseware.views.university_profile(request, university) + + +@ensure_csrf_cookie +@cache_if_anonymous +def courses(request): + """ + Render the "find courses" page. If subdomain branding is on, this is the + university profile page, otherwise it's the edX courseware.views.courses page + """ + + university = branding.get_university(request.META.get('HTTP_HOST')) + if university is None: + return courseware.views.courses(request) + + return courseware.views.university_profile(request, university) diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index c92cbb1425..e5ef915e25 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -13,6 +13,7 @@ from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError from static_replace import replace_urls, try_staticfiles_lookup from courseware.access import has_access +import branding log = logging.getLogger(__name__) @@ -141,9 +142,10 @@ 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. +# then. def get_course_syllabus_section(course, section_key): """ This returns the snippet of html to be rendered on the syllabus page, @@ -178,24 +180,11 @@ def get_courses_by_university(user, domain=None): ''' # TODO: Clean up how 'error' is done. # filter out any courses that errored. - courses = [c for c in modulestore().get_courses() - if isinstance(c, CourseDescriptor)] - courses = sorted(courses, key=lambda course: course.number) - - if domain and settings.MITX_FEATURES.get('SUBDOMAIN_COURSE_LISTINGS'): - subdomain = domain.split(".")[0] - if subdomain not in settings.COURSE_LISTINGS: - subdomain = 'default' - visible_courses = frozenset(settings.COURSE_LISTINGS[subdomain]) - else: - visible_courses = frozenset(c.id for c in courses) + visible_courses = branding.get_visible_courses(domain) universities = defaultdict(list) - for course in courses: + for course in visible_courses: if not has_access(user, course, 'see_exists'): continue - if course.id not in visible_courses: - continue universities[course.org].append(course) return universities - diff --git a/lms/envs/common.py b/lms/envs/common.py index c99423c7a1..1cc6ae8d89 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -55,9 +55,14 @@ MITX_FEATURES = { # course_ids (see dev_int.py for an example) 'SUBDOMAIN_COURSE_LISTINGS' : False, + # When True, will override certain branding with university specific values + # Expects a SUBDOMAIN_BRANDING dictionary that maps the subdomain to the + # university to use for branding purposes + 'SUBDOMAIN_BRANDING': False, + # TODO: This will be removed once course-specific tabs are in place. see # courseware/courses.py - 'ENABLE_SYLLABUS' : True, + 'ENABLE_SYLLABUS' : True, 'ENABLE_TEXTBOOK' : True, 'ENABLE_DISCUSSION' : False, @@ -66,7 +71,7 @@ MITX_FEATURES = { 'ENABLE_SQL_TRACKING_LOGS': False, 'ENABLE_LMS_MIGRATION': False, - 'DISABLE_LOGIN_BUTTON': False, # used in systems where login is automatic, eg MIT SSL + 'DISABLE_LOGIN_BUTTON': False, # used in systems where login is automatic, eg MIT SSL # extrernal access methods 'ACCESS_REQUIRE_STAFF_FOR_COURSE': False, @@ -199,6 +204,11 @@ COURSE_SETTINGS = {'6.002x_Fall_2012': {'number' : '6.002x', # TODO (vshnayder): Will probably need to change as we get real access control in. LMS_MIGRATION_ALLOWED_IPS = [] +######################## subdomain specific settings ########################### +COURSE_LISTINGS = {} +SUBDOMAIN_BRANDING = {} + + ############################### XModule Store ################################## MODULESTORE = { 'default': { diff --git a/lms/envs/dev.py b/lms/envs/dev.py index b269d293dd..d798815543 100644 --- a/lms/envs/dev.py +++ b/lms/envs/dev.py @@ -15,6 +15,8 @@ TEMPLATE_DEBUG = True MITX_FEATURES['DISABLE_START_DATES'] = True MITX_FEATURES['ENABLE_SQL_TRACKING_LOGS'] = True +MITX_FEATURES['SUBDOMAIN_COURSE_LISTINGS'] = True +MITX_FEATURES['SUBDOMAIN_BRANDING'] = True WIKI_ENABLED = True @@ -68,6 +70,28 @@ CACHE_TIMEOUT = 0 # Dummy secret key for dev SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' +COURSE_LISTINGS = { + 'default': ['BerkeleyX/CS169.1x/2012_Fall', + 'BerkeleyX/CS188.1x/2012_Fall', + 'HarvardX/CS50x/2012', + 'HarvardX/PH207x/2012_Fall', + 'MITx/3.091x/2012_Fall', + 'MITx/6.002x/2012_Fall', + 'MITx/6.00x/2012_Fall'], + 'berkeley': ['BerkeleyX/CS169.1x/Cal_2012_Fall', + 'BerkeleyX/CS188.1x/Cal_2012_Fall'], + 'harvard': ['HarvardX/CS50x/2012H'], + 'mit': [], + 'sjsu': ['MITx/6.002x-EE98/2012_Fall_SJSU'], +} + +SUBDOMAIN_BRANDING = { + 'sjsu': 'MITx', + 'mit': 'MITx', + 'berkeley': 'BerkeleyX', + 'harvard': 'HarvardX', +} + ################################ LMS Migration ################################# MITX_FEATURES['ENABLE_LMS_MIGRATION'] = True MITX_FEATURES['ACCESS_REQUIRE_STAFF_FOR_COURSE'] = False # require that user be in the staff_* group to be able to enroll diff --git a/lms/static/images/BerkeleyX-on-edx-logo.png b/lms/static/images/BerkeleyX-on-edx-logo.png new file mode 100644 index 0000000000..6c5a828503 Binary files /dev/null and b/lms/static/images/BerkeleyX-on-edx-logo.png differ diff --git a/lms/static/images/HarvardX-on-edx-logo.png b/lms/static/images/HarvardX-on-edx-logo.png new file mode 100644 index 0000000000..a4d40f52b6 Binary files /dev/null and b/lms/static/images/HarvardX-on-edx-logo.png differ diff --git a/lms/static/images/MITx-on-edx-logo.png b/lms/static/images/MITx-on-edx-logo.png new file mode 100644 index 0000000000..156a08bcbc Binary files /dev/null and b/lms/static/images/MITx-on-edx-logo.png differ diff --git a/lms/static/sass/course/layout/_courseware_header.scss b/lms/static/sass/course/layout/_courseware_header.scss index 84ededfabb..c1ff450dff 100644 --- a/lms/static/sass/course/layout/_courseware_header.scss +++ b/lms/static/sass/course/layout/_courseware_header.scss @@ -95,13 +95,6 @@ header.global.slim { top: -12px; width: 1px; } - - a { - width: 48px; - height: 24px; - background: url(../images/small-header-logo.png) no-repeat !important; - } - } .find-courses-button { @@ -138,4 +131,4 @@ header.global.slim { font-weight: bold; letter-spacing: 0; } -} \ No newline at end of file +} diff --git a/lms/static/sass/shared/_header.scss b/lms/static/sass/shared/_header.scss index 116761ddc8..49c9ac250b 100644 --- a/lms/static/sass/shared/_header.scss +++ b/lms/static/sass/shared/_header.scss @@ -19,7 +19,7 @@ header.global { h1.logo { float: left; - margin: 6px 15px 0px 0px; + margin: 0px 15px 0px 0px; padding-right: 20px; position: relative; @@ -46,12 +46,7 @@ header.global { } a { - @include background-image(url('/static/images/header-logo.png')); - background-position: 0 0; - background-repeat: no-repeat; display: block; - height: 31px; - width: 64px; } } diff --git a/lms/templates/footer.html b/lms/templates/footer.html index 85ed6e1769..52c2b45526 100644 --- a/lms/templates/footer.html +++ b/lms/templates/footer.html @@ -6,7 +6,7 @@