Merge branch 'master' of github.com:MITx/mitx into merge
Conflicts: lms/envs/dev.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))
|
||||
|
||||
@@ -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" /></div>' % (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.
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from functools import wraps
|
||||
|
||||
from django.core import cache
|
||||
|
||||
|
||||
# If we can't find a 'general' CACHE defined in settings.py, we simply fall back
|
||||
# to returning the default cache. This will happen with dev machines.
|
||||
try:
|
||||
@@ -41,7 +42,10 @@ def cache_if_anonymous(view_func):
|
||||
def _decorated(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated():
|
||||
#Use the cache
|
||||
cache_key = "cache_if_anonymous." + request.path
|
||||
# same view accessed through different domain names may
|
||||
# return different things, so include the domain name in the key.
|
||||
domain = str(request.META.get('HTTP_HOST')) + '.'
|
||||
cache_key = domain + "cache_if_anonymous." + request.path
|
||||
response = cache.get(cache_key)
|
||||
if not response:
|
||||
response = view_func(request, *args, **kwargs)
|
||||
|
||||
@@ -557,7 +557,7 @@ class ChoiceResponse(LoncapaResponse):
|
||||
return CorrectMap(self.answer_id, 'incorrect')
|
||||
|
||||
def get_answers(self):
|
||||
return {self.answer_id: self.correct_choices}
|
||||
return {self.answer_id: list(self.correct_choices)}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -390,9 +390,19 @@ class CapaModule(XModule):
|
||||
raise NotFoundError('Answer is not available')
|
||||
else:
|
||||
answers = self.lcp.get_question_answers()
|
||||
|
||||
# answers (eg <solution>) may have embedded images
|
||||
answers = dict( (k,self.system.replace_urls(answers[k], self.metadata['data_dir'])) for k in answers )
|
||||
return {'answers': answers}
|
||||
# but be careful, some problems are using non-string answer dicts
|
||||
new_answers = dict()
|
||||
for answer_id in answers:
|
||||
try:
|
||||
new_answer = {answer_id: self.system.replace_urls(answers[answer_id], self.metadata['data_dir'])}
|
||||
except TypeError:
|
||||
log.debug('Unable to perform URL substitution on answers[%s]: %s' % (answer_id, answers[answer_id]))
|
||||
new_answer = {answer_id: answers[answer_id]}
|
||||
new_answers.update(new_answer)
|
||||
|
||||
return {'answers': new_answers}
|
||||
|
||||
# Figure out if we should move these to capa_problem?
|
||||
def get_problem(self, get):
|
||||
|
||||
@@ -60,6 +60,8 @@ class CourseDescriptor(SequenceDescriptor):
|
||||
def __init__(self, system, definition=None, **kwargs):
|
||||
super(CourseDescriptor, self).__init__(system, definition, **kwargs)
|
||||
self.textbooks = self.definition['data']['textbooks']
|
||||
|
||||
self.wiki_slug = self.definition['data']['wiki_slug'] or self.location.course
|
||||
|
||||
msg = None
|
||||
if self.start is None:
|
||||
@@ -94,8 +96,19 @@ class CourseDescriptor(SequenceDescriptor):
|
||||
for textbook in xml_object.findall("textbook"):
|
||||
textbooks.append(cls.Textbook.from_xml_object(textbook))
|
||||
xml_object.remove(textbook)
|
||||
|
||||
#Load the wiki tag if it exists
|
||||
wiki_slug = None
|
||||
wiki_tag = xml_object.find("wiki")
|
||||
if wiki_tag is not None:
|
||||
wiki_slug = wiki_tag.attrib.get("slug", default=None)
|
||||
xml_object.remove(wiki_tag)
|
||||
|
||||
definition = super(CourseDescriptor, cls).definition_from_xml(xml_object, system)
|
||||
|
||||
definition.setdefault('data', {})['textbooks'] = textbooks
|
||||
definition['data']['wiki_slug'] = wiki_slug
|
||||
|
||||
return definition
|
||||
|
||||
def has_started(self):
|
||||
@@ -197,6 +210,19 @@ class CourseDescriptor(SequenceDescriptor):
|
||||
def start_date_text(self):
|
||||
return time.strftime("%b %d, %Y", self.start)
|
||||
|
||||
# An extra property is used rather than the wiki_slug/number because
|
||||
# there are courses that change the number for different runs. This allows
|
||||
# courses to share the same css_class across runs even if they have
|
||||
# different numbers.
|
||||
#
|
||||
# TODO get rid of this as soon as possible or potentially build in a robust
|
||||
# way to add in course-specific styling. There needs to be a discussion
|
||||
# about the right way to do this, but arjun will address this ASAP. Also
|
||||
# note that the courseware template needs to change when this is removed.
|
||||
@property
|
||||
def css_class(self):
|
||||
return self.metadata.get('css_class', '')
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
return self.display_name
|
||||
@@ -205,10 +231,6 @@ class CourseDescriptor(SequenceDescriptor):
|
||||
def number(self):
|
||||
return self.location.course
|
||||
|
||||
@property
|
||||
def wiki_slug(self):
|
||||
return self.location.course
|
||||
|
||||
@property
|
||||
def org(self):
|
||||
return self.location.org
|
||||
|
||||
@@ -2,18 +2,54 @@ nav.sequence-nav {
|
||||
// TODO (cpennington): This doesn't work anymore. XModules aren't able to
|
||||
// import from external sources.
|
||||
@extend .topbar;
|
||||
border-bottom: 1px solid $border-color;
|
||||
@include border-top-right-radius(4px);
|
||||
margin: 0 0 lh() (-(lh()));
|
||||
margin: -4px 0 30px;
|
||||
position: relative;
|
||||
border-bottom: none;
|
||||
|
||||
.left-shadow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
width: 20px;
|
||||
height: 46px;
|
||||
@include linear-gradient(left, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0));
|
||||
background-color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.right-shadow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 9999;
|
||||
width: 20px;
|
||||
height: 46px;
|
||||
@include linear-gradient(right, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0));
|
||||
background-color: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.sequence-list-wrapper {
|
||||
position: relative;
|
||||
z-index: 9999;
|
||||
border: 1px solid #ccc;
|
||||
height: 44px;
|
||||
margin: 0 30px;
|
||||
@include linear-gradient(top, #ddd, #eee);
|
||||
overflow: hidden;
|
||||
@include box-shadow(0 1px 3px rgba(0, 0, 0, .1) inset);
|
||||
}
|
||||
|
||||
ol {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
@include box-sizing(border-box);
|
||||
display: table;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding-left: 3px;
|
||||
padding-right: flex-grid(1, 9);
|
||||
padding: 0 10px;
|
||||
width: 100%;
|
||||
|
||||
a {
|
||||
@@ -25,42 +61,44 @@ nav.sequence-nav {
|
||||
min-width: 20px;
|
||||
|
||||
a {
|
||||
background-position: center;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
margin: 4px auto;
|
||||
background-position: center 10px;
|
||||
background-repeat: no-repeat;
|
||||
border: 1px solid transparent;
|
||||
border-bottom: none;
|
||||
@include border-radius(3px 3px 0 0);
|
||||
@include border-radius(35px);
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 10px;
|
||||
padding: 15px 0 14px;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
@include transition();
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
background-color: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-color: #F3F3F3;
|
||||
}
|
||||
|
||||
&.visited {
|
||||
background-color: #F3F3F3;
|
||||
|
||||
&:hover {
|
||||
background-position: center center;
|
||||
}
|
||||
background-position: center 10px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $border-color;
|
||||
@include box-shadow(0 2px 0 #fff);
|
||||
background-color: #fff;
|
||||
z-index: 9;
|
||||
|
||||
// &:after {
|
||||
// content: '▲';
|
||||
// position: absolute;
|
||||
// top: 28px;
|
||||
// left: 50%;
|
||||
// z-index: 9999;
|
||||
// margin-left: -5px;
|
||||
// font-size: 12px;
|
||||
// color: #aaa;
|
||||
// }
|
||||
|
||||
&:hover {
|
||||
background-position: center;
|
||||
background-color: #fff;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,20 +209,24 @@ nav.sequence-nav {
|
||||
}
|
||||
|
||||
ul {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
list-style: none;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: flex-grid(1, 9);
|
||||
border: 1px solid $border-color;
|
||||
border-bottom: 0;
|
||||
@include border-radius(3px 3px 0 0);
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border: none;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
position: absolute;
|
||||
margin-bottom: 0;
|
||||
width: 50%;
|
||||
height: 44px;
|
||||
width: 70px;
|
||||
border: 1px solid #ccc;
|
||||
@include linear-gradient(top, #eee, #ddd);
|
||||
@include box-shadow(0 1px 0 rgba(255, 255, 255, .7) inset);
|
||||
|
||||
&.prev, &.next {
|
||||
|
||||
@@ -192,14 +234,13 @@ nav.sequence-nav {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
height: 10px;
|
||||
padding: 15px 0 14px;
|
||||
height: 34px;
|
||||
width: 40px;
|
||||
text-indent: -9999px;
|
||||
@include transition(all, .2s, $ease-in-out-quad);
|
||||
|
||||
&:hover {
|
||||
opacity: .5;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
@@ -210,15 +251,23 @@ nav.sequence-nav {
|
||||
}
|
||||
|
||||
&.prev {
|
||||
left: -10px;
|
||||
border-radius: 35px 0 0 35px;
|
||||
|
||||
a {
|
||||
background-image: url('../images/sequence-nav/previous-icon.png');
|
||||
background-position: center 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&.next {
|
||||
right: -10px;
|
||||
border-radius: 0 35px 35px 0;
|
||||
|
||||
a {
|
||||
border-left: 1px solid lighten($border-color, 10%);
|
||||
margin-left: 30px;
|
||||
background-image: url('../images/sequence-nav/next-icon.png');
|
||||
background-position: center 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
div.video {
|
||||
@include clearfix();
|
||||
background: #f3f3f3;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
display: block;
|
||||
margin: 0 0 0 (-(lh()));
|
||||
padding: 6px lh();
|
||||
margin: 0 -12px;
|
||||
padding: 12px;
|
||||
border-radius: 5px;
|
||||
|
||||
article.video-wrapper {
|
||||
float: left;
|
||||
@@ -401,6 +400,7 @@ div.video {
|
||||
overflow: auto;
|
||||
width: flex-grid(3, 9);
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
|
||||
li {
|
||||
border: 0;
|
||||
|
||||
@@ -15,18 +15,39 @@ from xmodule.errortracker import exc_info_to_str
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# NOTE: This is not the most beautiful design in the world, but there's no good
|
||||
# way to tell if the module is being used in a staff context or not. Errors that get discovered
|
||||
# at course load time are turned into ErrorDescriptor objects, and automatically hidden from students.
|
||||
# Unfortunately, we can also have errors when loading modules mid-request, and then we need to decide
|
||||
# what to show, and the logic for that belongs in the LMS (e.g. in get_module), so the error handler
|
||||
# decides whether to create a staff or not-staff module.
|
||||
|
||||
class ErrorModule(XModule):
|
||||
def get_html(self):
|
||||
'''Show an error.
|
||||
'''Show an error to staff.
|
||||
TODO (vshnayder): proper style, divs, etc.
|
||||
'''
|
||||
# staff get to see all the details
|
||||
return self.system.render_template('module-error.html', {
|
||||
'staff_access' : True,
|
||||
'data' : self.definition['data']['contents'],
|
||||
'error' : self.definition['data']['error_msg'],
|
||||
})
|
||||
|
||||
|
||||
class NonStaffErrorModule(XModule):
|
||||
def get_html(self):
|
||||
'''Show an error to a student.
|
||||
TODO (vshnayder): proper style, divs, etc.
|
||||
'''
|
||||
# staff get to see all the details
|
||||
return self.system.render_template('module-error.html', {
|
||||
'staff_access' : False,
|
||||
'data' : "",
|
||||
'error' : "",
|
||||
})
|
||||
|
||||
|
||||
class ErrorDescriptor(EditingDescriptor):
|
||||
"""
|
||||
Module that provides a raw editing view of broken xml.
|
||||
@@ -99,3 +120,9 @@ class ErrorDescriptor(EditingDescriptor):
|
||||
err_node = etree.SubElement(root, 'error_msg')
|
||||
err_node.text = self.definition['data']['error_msg']
|
||||
return etree.tostring(root)
|
||||
|
||||
class NonStaffErrorDescriptor(ErrorDescriptor):
|
||||
"""
|
||||
Module that provides non-staff error messages.
|
||||
"""
|
||||
module_class = NonStaffErrorModule
|
||||
|
||||
|
Before Width: | Height: | Size: 250 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 243 B After Width: | Height: | Size: 1.0 KiB |
52
lms/djangoapps/branding/__init__.py
Normal file
@@ -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
|
||||
)
|
||||
45
lms/djangoapps/branding/views.py
Normal file
@@ -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)
|
||||
@@ -5,6 +5,7 @@ from django.http import Http404
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from wiki.models import reverse as wiki_reverse
|
||||
from courseware.access import has_access
|
||||
from courseware.courses import get_course_with_access
|
||||
|
||||
|
||||
@@ -135,7 +136,9 @@ def context_processor(request):
|
||||
|
||||
try:
|
||||
course = get_course_with_access(request.user, course_id, 'load')
|
||||
return {'course' : course}
|
||||
staff_access = has_access(request.user, course, 'staff')
|
||||
return {'course' : course,
|
||||
'staff_access': staff_access}
|
||||
except Http404:
|
||||
# We couldn't access the course for whatever reason. It is too late to change
|
||||
# the URL here, so we just leave the course context. The middleware shouldn't
|
||||
|
||||
@@ -80,8 +80,8 @@ def course_wiki_redirect(request, course_id):
|
||||
urlpath = URLPath.create_article(
|
||||
root,
|
||||
course_slug,
|
||||
title=course.number,
|
||||
content="{0}\n===\nThis is the wiki for **{1}**'s _{2}_.".format(course.number, course.org, course.title),
|
||||
title=course_slug,
|
||||
content="This is the wiki for **{0}**'s _{1}_.".format(course.org, course.title),
|
||||
user_message="Course page automatically created.",
|
||||
user=None,
|
||||
ip_address=None,
|
||||
@@ -114,7 +114,7 @@ def get_or_create_root():
|
||||
"===",
|
||||
"Visit a course wiki to add an article."))
|
||||
|
||||
root = URLPath.create_root(title="edX Wiki",
|
||||
root = URLPath.create_root(title="Wiki",
|
||||
content=starting_content)
|
||||
article = root.article
|
||||
article.group = None
|
||||
|
||||
@@ -13,7 +13,6 @@ from xmodule.modulestore import Location
|
||||
from xmodule.timeparse import parse_time
|
||||
from xmodule.x_module import XModule, XModuleDescriptor
|
||||
|
||||
|
||||
DEBUG_ACCESS = False
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
@@ -15,10 +16,12 @@ from courseware.access import has_access
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
from models import StudentModule, StudentModuleCache
|
||||
from static_replace import replace_urls
|
||||
from xmodule.errortracker import exc_info_to_str
|
||||
from xmodule.exceptions import NotFoundError
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor
|
||||
from xmodule_modifiers import replace_course_urls, replace_static_urls, add_histogram, wrap_xmodule
|
||||
|
||||
log = logging.getLogger("mitx.courseware")
|
||||
@@ -73,6 +76,8 @@ def toc_for_course(user, request, course, active_chapter, active_section, course
|
||||
student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(
|
||||
course_id, user, course, depth=2)
|
||||
course = get_module(user, request, course.location, student_module_cache, course_id)
|
||||
if course is None:
|
||||
return None
|
||||
|
||||
chapters = list()
|
||||
for chapter in course.get_display_items():
|
||||
@@ -131,9 +136,9 @@ def get_section(course_module, chapter, section):
|
||||
|
||||
return section_module
|
||||
|
||||
|
||||
def get_module(user, request, location, student_module_cache, course_id, position=None):
|
||||
''' Get an instance of the xmodule class identified by location,
|
||||
"""
|
||||
Get an instance of the xmodule class identified by location,
|
||||
setting the state based on an existing StudentModule, or creating one if none
|
||||
exists.
|
||||
|
||||
@@ -146,9 +151,22 @@ def get_module(user, request, location, student_module_cache, course_id, positio
|
||||
- position : extra information from URL for user-specified
|
||||
position within module
|
||||
|
||||
Returns: xmodule instance
|
||||
Returns: xmodule instance, or None if the user does not have access to the
|
||||
module. If there's an error, will try to return an instance of ErrorModule
|
||||
if possible. If not possible, return None.
|
||||
"""
|
||||
try:
|
||||
return _get_module(user, request, location, student_module_cache, course_id, position)
|
||||
except:
|
||||
# Something has gone terribly wrong, but still not letting it turn into a 500.
|
||||
log.exception("Error in get_module")
|
||||
return None
|
||||
|
||||
'''
|
||||
def _get_module(user, request, location, student_module_cache, course_id, position=None):
|
||||
"""
|
||||
Actually implement get_module. See docstring there for details.
|
||||
"""
|
||||
location = Location(location)
|
||||
descriptor = modulestore().get_instance(course_id, location)
|
||||
|
||||
# Short circuit--if the user shouldn't have access, bail without doing any work
|
||||
@@ -198,7 +216,7 @@ def get_module(user, request, location, student_module_cache, course_id, positio
|
||||
'callback_url': xqueue_callback_url,
|
||||
'default_queuename': xqueue_default_queuename.replace(' ', '_')}
|
||||
|
||||
def _get_module(location):
|
||||
def inner_get_module(location):
|
||||
"""
|
||||
Delegate to get_module. It does an access check, so may return None
|
||||
"""
|
||||
@@ -214,7 +232,7 @@ def get_module(user, request, location, student_module_cache, course_id, positio
|
||||
xqueue=xqueue,
|
||||
# TODO (cpennington): Figure out how to share info between systems
|
||||
filestore=descriptor.system.resources_fs,
|
||||
get_module=_get_module,
|
||||
get_module=inner_get_module,
|
||||
user=user,
|
||||
# TODO (cpennington): This should be removed when all html from
|
||||
# a module is coming through get_html and is therefore covered
|
||||
@@ -226,7 +244,22 @@ def get_module(user, request, location, student_module_cache, course_id, positio
|
||||
system.set('position', position)
|
||||
system.set('DEBUG', settings.DEBUG)
|
||||
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
try:
|
||||
module = descriptor.xmodule_constructor(system)(instance_state, shared_state)
|
||||
except:
|
||||
log.exception("Error creating module from descriptor {0}".format(descriptor))
|
||||
|
||||
# make an ErrorDescriptor -- assuming that the descriptor's system is ok
|
||||
import_system = descriptor.system
|
||||
if has_access(user, location, 'staff'):
|
||||
err_descriptor = ErrorDescriptor.from_xml(str(descriptor), import_system,
|
||||
error_msg=exc_info_to_str(sys.exc_info()))
|
||||
else:
|
||||
err_descriptor = NonStaffErrorDescriptor.from_xml(str(descriptor), import_system,
|
||||
error_msg=exc_info_to_str(sys.exc_info()))
|
||||
|
||||
# Make an error module
|
||||
return err_descriptor.xmodule_constructor(system)(None, None)
|
||||
|
||||
module.get_html = replace_static_urls(
|
||||
wrap_xmodule(module.get_html, module, 'xmodule_display.html'),
|
||||
@@ -374,7 +407,7 @@ def modx_dispatch(request, dispatch, location, course_id):
|
||||
# ''' (fix emacs broken parsing)
|
||||
|
||||
# Check for submitted files and basic file size checks
|
||||
p = request.POST.dict()
|
||||
p = request.POST.copy()
|
||||
if request.FILES:
|
||||
for fileinput_id in request.FILES.keys():
|
||||
inputfiles = request.FILES.getlist(fileinput_id)
|
||||
|
||||
@@ -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': {
|
||||
@@ -318,6 +328,7 @@ WIKI_ACCOUNT_HANDLING = False
|
||||
WIKI_EDITOR = 'course_wiki.editors.CodeMirror'
|
||||
WIKI_SHOW_MAX_CHILDREN = 0 # We don't use the little menu that shows children of an article in the breadcrumb
|
||||
WIKI_ANONYMOUS = False # Don't allow anonymous access until the styling is figured out
|
||||
WIKI_CAN_CHANGE_PERMISSIONS = lambda article, user: user.has_perm('wiki.assign')
|
||||
|
||||
################################# Jasmine ###################################
|
||||
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
|
||||
|
||||
@@ -15,7 +15,8 @@ TEMPLATE_DEBUG = True
|
||||
|
||||
MITX_FEATURES['DISABLE_START_DATES'] = True
|
||||
MITX_FEATURES['ENABLE_SQL_TRACKING_LOGS'] = True
|
||||
MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
|
||||
MITX_FEATURES['SUBDOMAIN_COURSE_LISTINGS'] = True
|
||||
MITX_FEATURES['SUBDOMAIN_BRANDING'] = True
|
||||
|
||||
WIKI_ENABLED = True
|
||||
|
||||
@@ -69,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
|
||||
|
||||
BIN
lms/static/images/BerkeleyX-on-edx-logo.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
lms/static/images/HarvardX-on-edx-logo.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
lms/static/images/MITx-on-edx-logo.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
lms/static/images/bg-texture.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
lms/static/images/small-header-home-icon.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
lms/static/images/small-header-logo.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
104
lms/static/js/jquery.sequence.js
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
|
||||
|
||||
var SequenceNav = function($element) {
|
||||
var _this = this;
|
||||
var $element = $element;
|
||||
var $wrapper = $element.find('.sequence-list-wrapper');
|
||||
var $list = $element.find('#sequence-list');
|
||||
var $arrows = $element.find('.sequence-nav-buttons');
|
||||
var maxScroll = $list.width() - $wrapper.width() + 20;
|
||||
var $leftShadow = $('<div class="left-shadow"></div>');
|
||||
var $rightShadow = $('<div class="right-shadow"></div>');
|
||||
var $body = $('body');
|
||||
var listOrigin;
|
||||
var mouseOrigin;
|
||||
|
||||
var startDrag = function(e) {
|
||||
updateWidths();
|
||||
mouseOrigin = e.pageX;
|
||||
listOrigin = $list.position().left;
|
||||
$body.css('-webkit-user-select', 'none');
|
||||
$body.bind('mousemove', moveDrag);
|
||||
$body.bind('mouseup', stopDrag);
|
||||
};
|
||||
|
||||
var moveDrag = function(e) {
|
||||
var offset = e.pageX - mouseOrigin;
|
||||
var targetLeft = clamp(listOrigin + offset, -maxScroll, 0);
|
||||
|
||||
console.log('---------------');
|
||||
console.log('offset: ' + offset);
|
||||
console.log('target left: ' + targetLeft);
|
||||
console.log('max: ' + maxScroll);
|
||||
|
||||
updateHorizontalPosition(targetLeft);
|
||||
|
||||
setShadows(targetLeft);
|
||||
};
|
||||
|
||||
var stopDrag = function(e) {
|
||||
$body.css('-webkit-user-select', 'auto');
|
||||
$body.unbind('mousemove', moveDrag);
|
||||
$body.unbind('mouseup', stopDrag);
|
||||
};
|
||||
|
||||
var setShadows = function(left) {
|
||||
var left = left || $list.position().left;
|
||||
var padding = 30;
|
||||
|
||||
var leftPercent = clamp(-left / padding, 0, 1);
|
||||
$leftShadow.css('opacity', leftPercent);
|
||||
|
||||
var rightPercent = clamp((maxScroll + left) / padding, 0, 1);
|
||||
$rightShadow.css('opacity', rightPercent);
|
||||
};
|
||||
|
||||
var clamp = function(val, min, max) {
|
||||
if(val > max) return max;
|
||||
if(val < min) return min;
|
||||
return val;
|
||||
};
|
||||
|
||||
var updateWidths = function(e) {
|
||||
maxScroll = $list.width() - $wrapper.width() + 20;
|
||||
var targetLeft = clamp($list.position().left, -maxScroll, 0);
|
||||
updateHorizontalPosition(targetLeft);
|
||||
setShadows(targetLeft);
|
||||
};
|
||||
|
||||
var updateHorizontalPosition = function(left) {
|
||||
$list.css({
|
||||
'left': left + 'px'
|
||||
});
|
||||
};
|
||||
|
||||
var checkPosition = function(e) {
|
||||
var $active = $element.find('.active');
|
||||
if(!$active[0]) {
|
||||
return;
|
||||
}
|
||||
if($active.position().left + $active.width() > $wrapper.width() - $list.position().left) {
|
||||
$list.animate({
|
||||
'left': (-$active.position().left + $wrapper.width() - $active.width() - 10) + 'px'
|
||||
}, {
|
||||
step: setShadows
|
||||
});
|
||||
} else if($active.position().left < -$list.position().left) {
|
||||
$list.animate({
|
||||
'left': (-$active.position().left + 10) + 'px'
|
||||
}, {
|
||||
step: setShadows
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$wrapper.append($leftShadow).append($rightShadow);
|
||||
setShadows(0);
|
||||
$wrapper.bind('mousedown', startDrag);
|
||||
$arrows.bind('click', checkPosition);
|
||||
$(window).bind('resize', updateWidths);
|
||||
setTimeout(function() {
|
||||
checkPosition();
|
||||
}, 200);
|
||||
}
|
||||
3
lms/static/sass/README.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
Sass Watch:
|
||||
|
||||
sass --watch lms/static/sass:lms/static/sass -r ./lms/static/sass/bourbon/lib/bourbon.rb
|
||||
@@ -55,10 +55,10 @@ $tag-text-color: #5b614f;
|
||||
|
||||
.sidebar-module {
|
||||
@include clearfix;
|
||||
padding: 0 24px 24px 0;
|
||||
padding: 0 26px 24px;
|
||||
margin-bottom: 24px;
|
||||
border-bottom: 1px solid #d3d3d3;
|
||||
font-size: 0.8em;
|
||||
font-size: 13px;
|
||||
|
||||
header {
|
||||
margin-bottom: 14px;
|
||||
@@ -67,16 +67,18 @@ $tag-text-color: #5b614f;
|
||||
|
||||
h4 {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sidebar-new-post-button, .sidebar-promote-moderator-button {
|
||||
@include button;
|
||||
}
|
||||
|
||||
.sidebar-revoke-moderator-button {
|
||||
@include button(simple, gray);
|
||||
}
|
||||
|
||||
.sidebar-new-post-button, .sidebar-promote-moderator-button, .sidebar-revoke-moderator-button {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@@ -91,9 +93,13 @@ $tag-text-color: #5b614f;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-new-post-button {
|
||||
margin: 40px 0 20px 0;
|
||||
}
|
||||
|
||||
.sidebar-view-all {
|
||||
float: right;
|
||||
font-size: 0.9em;
|
||||
font-size: 13px;
|
||||
line-height: 1.6em;
|
||||
@include standard-discussion-link;
|
||||
}
|
||||
@@ -108,6 +114,10 @@ $tag-text-color: #5b614f;
|
||||
a {
|
||||
@include standard-discussion-link;
|
||||
background: none;
|
||||
|
||||
span {
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,16 +15,19 @@ $monospace: Monaco, 'Bitstream Vera Sans Mono', 'Lucida Console', monospace;
|
||||
$body-font-size: em(14);
|
||||
$body-line-height: golden-ratio(.875em, 1);
|
||||
$base-font-color: rgb(60,60,60);
|
||||
$lighter-base-font-color: rgb(160,160,160);
|
||||
$lighter-base-font-color: rgb(100,100,100);
|
||||
|
||||
$blue: rgb(29,157,217);
|
||||
$pink: rgb(182,37,104);
|
||||
$yellow: rgb(255, 252, 221);
|
||||
$error-red: rgb(253, 87, 87);
|
||||
$border-color: #C8C8C8;
|
||||
$sidebar-color: #f6f6f6;
|
||||
$outer-border-color: #aaa;
|
||||
|
||||
// old variables
|
||||
|
||||
$light-gray: #ddd;
|
||||
$dark-gray: #333;
|
||||
$text-color: $dark-gray;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
// Course base / layout styles
|
||||
@import 'course/layout/courseware_header';
|
||||
@import 'course/layout/footer';
|
||||
@import 'course/base/base';
|
||||
@import 'course/base/extends';
|
||||
@import 'module/module-styles.scss';
|
||||
@@ -34,6 +35,9 @@
|
||||
@import "course/profile";
|
||||
@import "course/gradebook";
|
||||
|
||||
// instructor
|
||||
@import "course/instructor/instructor";
|
||||
|
||||
// Askbot / Discussion styles
|
||||
@import "course/discussion/askbot-original";
|
||||
@import "course/discussion/discussion";
|
||||
|
||||
@@ -6,6 +6,9 @@ div.gradebook-wrapper {
|
||||
|
||||
section.gradebook-content {
|
||||
@extend .content;
|
||||
display: block;
|
||||
width: 100%;
|
||||
@include clearfix;
|
||||
|
||||
.student-search {
|
||||
padding: 0 20px 0 15px;
|
||||
@@ -15,7 +18,7 @@ div.gradebook-wrapper {
|
||||
width: 100%;
|
||||
height: 27px;
|
||||
padding: 0 15px 0 35px;
|
||||
box-sizing: border-box;
|
||||
@include box-sizing(border-box);
|
||||
border-radius: 13px;
|
||||
border: 1px solid $table-border-color;
|
||||
background: url(../images/search-icon.png) no-repeat 9px center #f6f6f6;
|
||||
@@ -37,7 +40,6 @@ div.gradebook-wrapper {
|
||||
|
||||
.student-table {
|
||||
float: left;
|
||||
// width: 264px;
|
||||
width: 24%;
|
||||
border-radius: 3px 0 0 3px;
|
||||
color: #3c3c3c;
|
||||
@@ -88,12 +90,20 @@ div.gradebook-wrapper {
|
||||
|
||||
.left-shadow {
|
||||
left: 0;
|
||||
background: -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -webkit-gradient(linear, left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-gradient(linear, left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -moz-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -moz-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -ms-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -ms-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -o-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -o-linear-gradient(left, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
.right-shadow {
|
||||
right: 0;
|
||||
background: -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -webkit-gradient(linear, right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-gradient(linear, right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -webkit-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -moz-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -ms-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -ms-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
background-image: -o-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0) 20%), -o-linear-gradient(right, rgba(0, 0, 0, .1), rgba(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,9 +113,8 @@ div.gradebook-wrapper {
|
||||
left: 0;
|
||||
width: 1000px;
|
||||
cursor: move;
|
||||
-webkit-transition: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
@include transition(none);
|
||||
@include user-select(none);
|
||||
|
||||
td,
|
||||
th {
|
||||
@@ -116,32 +125,30 @@ div.gradebook-wrapper {
|
||||
thead th {
|
||||
position: relative;
|
||||
height: 50px;
|
||||
background: -webkit-linear-gradient(top, $cell-border-color, #ddd);
|
||||
@include linear-gradient(top, $cell-border-color, #ddd);
|
||||
font-size: 10px;
|
||||
line-height: 10px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
box-shadow: 0 1px 0 $table-border-color inset, 0 2px 0 rgba(255, 255, 255, .7) inset;
|
||||
border-left: 1px solid #ccc;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 9999;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, .15));
|
||||
}
|
||||
// &:before {
|
||||
// content: '';
|
||||
// display: block;
|
||||
// position: absolute;
|
||||
// left: 0;
|
||||
// top: 0;
|
||||
// z-index: 9999;
|
||||
// width: 1px;
|
||||
// height: 50px;
|
||||
// @include linear-gradient(top, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, .15));
|
||||
// }
|
||||
|
||||
&:first-child {
|
||||
border-radius: 5px 0 0 0;
|
||||
box-shadow: 1px 1px 0 $table-border-color inset, 1px 2px 0 rgba(255, 255, 255, .7) inset;
|
||||
|
||||
&:before {
|
||||
display: hidden;
|
||||
}
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@@ -161,7 +168,7 @@ div.gradebook-wrapper {
|
||||
|
||||
.max {
|
||||
height: 12px;
|
||||
background: -webkit-linear-gradient(top, #c6c6c6, #bababa);
|
||||
@include linear-gradient(top, #c6c6c6, #bababa);
|
||||
font-size: 9px;
|
||||
line-height: 12px;
|
||||
color: #fff;
|
||||
|
||||
@@ -68,10 +68,10 @@ div.info-wrapper {
|
||||
|
||||
section.handouts {
|
||||
@extend .sidebar;
|
||||
border-left: 1px solid $border-color;
|
||||
border-right: 0;
|
||||
@include border-radius(0 4px 4px 0);
|
||||
border-left: 1px solid #ddd;
|
||||
@include box-shadow(none);
|
||||
font-size: 14px;
|
||||
|
||||
&:after {
|
||||
left: -1px;
|
||||
@@ -79,31 +79,51 @@ div.info-wrapper {
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend .bottom-border;
|
||||
margin-bottom: 0;
|
||||
padding: lh(.5) lh(.5);
|
||||
padding: 32px 26px 20px 26px;
|
||||
font-size: 18px;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ol {
|
||||
li {
|
||||
margin: 0 26px 14px 26px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding-left: lh(.5);
|
||||
padding-right: 0;
|
||||
padding: 0;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.expandable,
|
||||
&.collapsable {
|
||||
margin: 0 16px 14px 16px;
|
||||
@include transition(all .2s);
|
||||
|
||||
h4 {
|
||||
color: $blue;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
padding: lh(.25) 0 lh(.25) lh(1.5);
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsable {
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
padding: 14px 0;
|
||||
@include box-shadow(0 0 1px 1px rgba(0, 0, 0, .1), 0 1px 3px rgba(0, 0, 0, .25));
|
||||
|
||||
h4 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&.multiple {
|
||||
padding: lh(.5) 0 lh(.5) lh(.5);
|
||||
|
||||
a {
|
||||
@include inline-block;
|
||||
@@ -121,10 +141,10 @@ div.info-wrapper {
|
||||
|
||||
li {
|
||||
border-bottom: 0;
|
||||
border-top: 1px solid $border-color;
|
||||
@include box-shadow(inset 0 1px 0 #eee);
|
||||
font-size: 1em;
|
||||
padding: lh(.5) 0 lh(.5) lh(.5);
|
||||
border-top: 1px solid #e6e6e6;
|
||||
font-size: 0.9em;
|
||||
margin: 0;
|
||||
padding: 15px 30px;
|
||||
|
||||
a {
|
||||
@include inline-block;
|
||||
@@ -138,11 +158,11 @@ div.info-wrapper {
|
||||
}
|
||||
|
||||
div.hitarea {
|
||||
background-image: url('../images/treeview-default.gif');
|
||||
background-image: url('../images/treeview-default.gif') no-repeat;
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: 0;
|
||||
max-height: 30px;
|
||||
max-height: 20px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
@@ -157,20 +177,20 @@ div.info-wrapper {
|
||||
}
|
||||
|
||||
&.expandable-hitarea {
|
||||
background-position: -72px 7px;
|
||||
background-position: -72px 0px;
|
||||
}
|
||||
|
||||
&.collapsable-hitarea {
|
||||
background-position: -55px -15px;
|
||||
background-position: -55px -23px;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
border-bottom: 0;
|
||||
@include box-shadow(none);
|
||||
color: #aaa;
|
||||
color: #888;
|
||||
font-size: 1em;
|
||||
margin-bottom: em(6);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
div.syllabus {
|
||||
|
||||
padding: 0px 10px;
|
||||
padding: 2em 2.5em;
|
||||
|
||||
text-align: center;
|
||||
|
||||
@@ -9,15 +9,14 @@ div.syllabus {
|
||||
}
|
||||
|
||||
.notes {
|
||||
width: 740px;
|
||||
margin: 0px auto 10px;
|
||||
margin: 0px auto 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
|
||||
text-align: left;
|
||||
|
||||
margin: 10px auto;
|
||||
margin: 10px 0;
|
||||
|
||||
thead {
|
||||
font-weight: bold;
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
div.book-wrapper {
|
||||
@extend .table-wrapper;
|
||||
|
||||
#open_close_accordion {
|
||||
display: none;
|
||||
}
|
||||
|
||||
section.book-sidebar {
|
||||
@extend .sidebar;
|
||||
@extend .tran;
|
||||
@include box-sizing(border-box);
|
||||
padding: 10px 0;
|
||||
border-radius: 3px 0 0 3px;
|
||||
border-right: 1px solid #ccc;
|
||||
|
||||
ul#booknav {
|
||||
font-size: em(14);
|
||||
@@ -32,7 +39,7 @@ div.book-wrapper {
|
||||
li {
|
||||
background: none;
|
||||
border-bottom: 0;
|
||||
padding-left: lh();
|
||||
padding-left: lh();
|
||||
|
||||
a {
|
||||
padding: 0;
|
||||
@@ -49,7 +56,7 @@ div.book-wrapper {
|
||||
|
||||
div.hitarea {
|
||||
background-image: url('../images/treeview-default.gif');
|
||||
margin-left: -22px;
|
||||
|
||||
position: relative;
|
||||
top: 4px;
|
||||
|
||||
@@ -62,26 +69,23 @@ div.book-wrapper {
|
||||
ul {
|
||||
background: none;
|
||||
margin-top: lh(.25);
|
||||
border-top: 1px solid $border-color;
|
||||
padding-top: lh(.25);
|
||||
|
||||
li {
|
||||
padding-bottom: lh(.25);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> li {
|
||||
border-bottom: 1px solid $border-color;
|
||||
padding: 7px 7px 7px 30px;
|
||||
padding: 5px 6px;
|
||||
margin: 0 16px 5px 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.book {
|
||||
@extend .content;
|
||||
padding-right: 0;
|
||||
padding-left: lh();
|
||||
|
||||
nav {
|
||||
@extend .clearfix;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
body {
|
||||
min-width: 980px;
|
||||
min-height: 100%;
|
||||
background: url(../images/bg-texture.png) #ddd;
|
||||
}
|
||||
|
||||
body, h1, h2, h3, h4, h5, h6, p, p a:link, p a:visited, a, label {
|
||||
@@ -11,16 +13,37 @@ table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
a {
|
||||
&:hover {
|
||||
color: $pink;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: lh(2);
|
||||
padding: 20px 0 0 0;
|
||||
|
||||
> div {
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
border-radius: 3px;
|
||||
border: 1px solid $outer-border-color;
|
||||
background: #fff;
|
||||
@include box-shadow(0 1px 2px rgba(0, 0, 0, 0.05));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
form {
|
||||
label {
|
||||
display: block;
|
||||
@@ -75,11 +98,7 @@ img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: em(40) 0;
|
||||
}
|
||||
|
||||
::selection, ::-moz-selection, ::-webkit-selection {
|
||||
background:#444;
|
||||
color:#fff;
|
||||
background: #444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ h1.top-header {
|
||||
.content {
|
||||
@include box-sizing(border-box);
|
||||
display: table-cell;
|
||||
padding-right: lh();
|
||||
padding: 2em 2.5em;
|
||||
vertical-align: top;
|
||||
width: flex-grid(9) + flex-gutter();
|
||||
|
||||
@@ -47,34 +47,28 @@ h1.top-header {
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
border-right: 1px solid #C8C8C8;
|
||||
@include box-sizing(border-box);
|
||||
display: table-cell;
|
||||
font-family: $sans-serif;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
width: flex-grid(3);
|
||||
|
||||
&:after {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
@include position(absolute, 0px -1px 0px 0);
|
||||
content: "";
|
||||
@include background-image(linear-gradient(top, #fff, rgba(#fff, 0)), linear-gradient(top, rgba(#fff, 0), #fff));
|
||||
background-position: top, bottom;
|
||||
@include background-size(1px 20px);
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
background: $sidebar-color;
|
||||
|
||||
h1, h2 {
|
||||
font-size: em(20);
|
||||
font-weight: 100;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
font-family: $sans-serif;
|
||||
text-align: left;
|
||||
font-style: italic;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
padding: 32px 26px 20px 26px;
|
||||
}
|
||||
|
||||
a {
|
||||
@@ -106,7 +100,7 @@ h1.top-header {
|
||||
}
|
||||
|
||||
&.active {
|
||||
@extend .bottom-border;
|
||||
// @extend .bottom-border;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -122,7 +116,7 @@ h1.top-header {
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
@extend .bottom-border;
|
||||
// @extend .bottom-border;
|
||||
@extend .clearfix;
|
||||
background: none;
|
||||
position: relative;
|
||||
|
||||
@@ -12,8 +12,7 @@ div.course-wrapper {
|
||||
|
||||
section.course-content {
|
||||
@extend .content;
|
||||
padding-right: 0;
|
||||
padding-left: lh();
|
||||
padding: 40px;
|
||||
|
||||
h1 {
|
||||
margin: 0 0 lh();
|
||||
@@ -46,6 +45,7 @@ div.course-wrapper {
|
||||
ol.vert-mod {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
line-height: 1.4;
|
||||
|
||||
> li {
|
||||
@extend .clearfix;
|
||||
@@ -224,3 +224,12 @@ div.course-wrapper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.xmodule_VideoModule {
|
||||
margin-bottom: 30px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
section.course-index {
|
||||
@extend .sidebar;
|
||||
@extend .tran;
|
||||
@include border-radius(3px 0 0 3px);
|
||||
border-right: 1px solid #ddd;
|
||||
|
||||
#open_close_accordion {
|
||||
display: none;
|
||||
}
|
||||
|
||||
header {
|
||||
max-height: 47px;
|
||||
@@ -11,10 +17,11 @@ section.course-index {
|
||||
}
|
||||
|
||||
div#accordion {
|
||||
width: auto;
|
||||
font-size: 14px;
|
||||
|
||||
h3 {
|
||||
@include border-radius(0);
|
||||
border-top: 1px solid lighten($border-color, 10%);
|
||||
font-size: em(16, 18);
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -24,7 +31,6 @@ section.course-index {
|
||||
|
||||
&:hover {
|
||||
color: #666;
|
||||
background: #f6f6f6;
|
||||
}
|
||||
|
||||
&.ui-state-hover {
|
||||
@@ -40,6 +46,7 @@ section.course-index {
|
||||
a {
|
||||
@include border-radius(0);
|
||||
@include box-shadow(none);
|
||||
padding-left: 19px;
|
||||
}
|
||||
|
||||
&.ui-state-active {
|
||||
@@ -52,28 +59,50 @@ section.course-index {
|
||||
}
|
||||
|
||||
span.ui-icon {
|
||||
left: 0;
|
||||
background-image: url("/static/images/ui-icons_222222_256x240.png");
|
||||
opacity: .3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chapter {
|
||||
width: 100%;
|
||||
@include box-sizing(border-box);
|
||||
padding: 11px 14px;
|
||||
@include linear-gradient(top, rgba(255, 255, 255, .6), rgba(255, 255, 255, 0));
|
||||
background-color: #eee;
|
||||
@include box-shadow(0 1px 0 #fff inset, 0 -1px 0 rgba(0, 0, 0, .1) inset);
|
||||
@include transition(background-color .1s);
|
||||
|
||||
&:first-child {
|
||||
border-radius: 3px 0 0 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0 0 0 3px;
|
||||
@include box-shadow(0 1px 0 #fff inset);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #fff
|
||||
}
|
||||
}
|
||||
|
||||
ul.ui-accordion-content {
|
||||
background: transparent;
|
||||
border: none;
|
||||
@include border-radius(0);
|
||||
font-size: em(14, 18);
|
||||
margin: 0;
|
||||
padding: 1em 1.5em;
|
||||
padding: 9px 0 9px 9px;
|
||||
|
||||
li {
|
||||
border-bottom: 0;
|
||||
@include border-radius(0);
|
||||
margin-bottom: lh(.5);
|
||||
margin-bottom: 4px;
|
||||
|
||||
a {
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
@include border-radius(4px);
|
||||
display: block;
|
||||
padding: 5px 36px 5px 10px;
|
||||
@@ -84,39 +113,18 @@ section.course-index {
|
||||
font-weight: bold;
|
||||
font-family: $sans-serif;
|
||||
margin-bottom: 0;
|
||||
line-height: 1.3;
|
||||
|
||||
span.subtitle {
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
background: transparent;
|
||||
border-right: 1px solid rgb(180,180,180);
|
||||
border-top: 1px solid rgb(180,180,180);
|
||||
content: "";
|
||||
display: block;
|
||||
height: 12px;
|
||||
margin-top: -6px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
top: 50%;
|
||||
@include transform(rotate(45deg));
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(-90deg, rgba(245,245,245, 0.4), rgba(230,230,230, 0.4)));
|
||||
border-color: rgb(200,200,200);
|
||||
|
||||
&:after {
|
||||
opacity: 1;
|
||||
right: 15px;
|
||||
@include transition();
|
||||
}
|
||||
background: rgba(0, 0, 0, .1);
|
||||
|
||||
> a p {
|
||||
color: #333;
|
||||
@@ -136,8 +144,23 @@ section.course-index {
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
|
||||
&:after {
|
||||
content: '›';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 20px;
|
||||
margin-top: -13px;
|
||||
font-size: 30px;
|
||||
font-weight: normal;
|
||||
color: #333;
|
||||
opacity: 0;
|
||||
@include transition();
|
||||
}
|
||||
|
||||
> a {
|
||||
border-color: rgb(200,200,200);
|
||||
border: 1px solid #bbb;
|
||||
@include box-shadow(0 1px 0 rgba(255, 255, 255, .35) inset);
|
||||
@include linear-gradient(top, #e6e6e6, #d6d6d6);
|
||||
|
||||
&:after {
|
||||
opacity: 1;
|
||||
|
||||
@@ -3,15 +3,16 @@ body.askbot {
|
||||
section.container {
|
||||
div.discussion-wrapper {
|
||||
@extend .table-wrapper;
|
||||
display: table;
|
||||
|
||||
div.discussion-content {
|
||||
@include box-sizing(border-box);
|
||||
display: table-cell;
|
||||
min-width: 650px;
|
||||
padding-right: lh();
|
||||
vertical-align: top;
|
||||
padding: 40px;
|
||||
width: flex-grid(9) + flex-gutter();
|
||||
|
||||
|
||||
a.tabula-rasa, .tabula-rasa{
|
||||
@extend .light-button;
|
||||
@include border-radius(5px);
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
div.discussion-wrapper aside {
|
||||
@extend .sidebar;
|
||||
border-left: 1px solid $border-color;
|
||||
border-left: 1px solid #ccc;
|
||||
border-right: 0;
|
||||
width: flex-grid(3);
|
||||
border-radius: 0 3px 3px 0;
|
||||
|
||||
&:after {
|
||||
left: -1px;
|
||||
@@ -16,9 +17,7 @@ div.discussion-wrapper aside {
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend .bottom-border;
|
||||
padding: lh(.5) lh();
|
||||
margin-bottom: em(16, 20);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -54,7 +53,7 @@ div.discussion-wrapper aside {
|
||||
|
||||
div.box {
|
||||
display: block;
|
||||
padding: lh(.5) lh();
|
||||
padding: 18px 26px;
|
||||
border-top: 1px solid lighten($border-color, 10%);
|
||||
|
||||
&:first-child {
|
||||
@@ -67,7 +66,7 @@ div.discussion-wrapper aside {
|
||||
|
||||
li {
|
||||
border-bottom: 0;
|
||||
background: #eee;
|
||||
background: #ddd;
|
||||
padding: 6px 10px 6px 5px;
|
||||
|
||||
a {
|
||||
@@ -298,6 +297,7 @@ div.discussion-wrapper aside {
|
||||
|
||||
div.view-profile {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
|
||||
a {
|
||||
@extend .gray-button;
|
||||
|
||||
@@ -10,7 +10,7 @@ ul.tags {
|
||||
}
|
||||
|
||||
li {
|
||||
background: #eee;
|
||||
background: #ddd;
|
||||
color: #555;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
@@ -19,7 +19,7 @@ ul.tags {
|
||||
padding: 6px 10px 6px 5px;
|
||||
|
||||
&:before {
|
||||
border-color:transparent #eee transparent transparent;
|
||||
border-color:transparent #ddd transparent transparent;
|
||||
border-style:solid;
|
||||
border-width:12px 10px 12px 0;
|
||||
content:"";
|
||||
|
||||
15
lms/static/sass/course/instructor/_instructor.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
.instructor-dashboard-wrapper {
|
||||
@extend .table-wrapper;
|
||||
display: table;
|
||||
|
||||
section.instructor-dashboard-content {
|
||||
@extend .content;
|
||||
padding: 40px;
|
||||
width: 100%;
|
||||
|
||||
h1 {
|
||||
@extend .top-header;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
nav.course-material {
|
||||
@include clearfix;
|
||||
@include box-sizing(border-box);
|
||||
background: #f6f6f6;
|
||||
border-bottom: 1px solid rgb(200,200,200);
|
||||
border-bottom: none;
|
||||
margin: 0px auto 0px;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
@@ -16,33 +15,32 @@ nav.course-material {
|
||||
ol.course-tabs {
|
||||
@include border-top-radius(4px);
|
||||
@include clearfix;
|
||||
padding: 10px 0 0 0;
|
||||
padding: 28px 0 10px 0;
|
||||
margin-left: 10px;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
list-style: none;
|
||||
margin-right: 6px;
|
||||
|
||||
a {
|
||||
color: darken($lighter-base-font-color, 20%);
|
||||
border-radius: 3px;
|
||||
color: #555;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 8px 13px 12px;
|
||||
padding: 10px 13px 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px rgb(255,255,255);
|
||||
|
||||
&:hover {
|
||||
color: $base-font-color;
|
||||
color: #333;
|
||||
background: rgba(255, 255, 255, .4);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: rgb(255,255,255);
|
||||
border: 1px solid rgb(200,200,200);
|
||||
border-bottom: 0px;
|
||||
@include border-top-radius(4px);
|
||||
@include box-shadow(0 2px 0 0 rgba(255,255,255, 1));
|
||||
color: $blue;
|
||||
background: rgba(255, 255, 255, .8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +55,48 @@ nav.course-material {
|
||||
}
|
||||
}
|
||||
|
||||
.global {
|
||||
header.global.slim {
|
||||
border-bottom: 1px solid $outer-border-color;
|
||||
@include box-shadow(0 1px 2px rgba(0, 0, 0, .1));
|
||||
height: 50px;
|
||||
@include linear-gradient(top, #fff, #eee);
|
||||
|
||||
.guest .secondary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
h1.logo {
|
||||
margin-left: 13px;
|
||||
margin-right: 20px;
|
||||
padding-right: 20px;
|
||||
|
||||
&::before {
|
||||
@extend .faded-vertical-divider;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: -8px;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
@extend .faded-vertical-divider-light;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: -12px;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.find-courses-button {
|
||||
display: none;
|
||||
}
|
||||
@@ -68,8 +107,9 @@ nav.course-material {
|
||||
float: left;
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
line-height: 40px;
|
||||
color: #777;
|
||||
letter-spacing: 0;
|
||||
margin-top: 9px;
|
||||
text-transform: none;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
white-space: nowrap;
|
||||
@@ -79,7 +119,16 @@ nav.course-material {
|
||||
.provider {
|
||||
font: inherit;
|
||||
font-weight: bold;
|
||||
color: #6d6d6d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a#signup {
|
||||
position: relative;
|
||||
margin-top: 4px;
|
||||
padding: 6px 12px 8px;
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
nav.course-material {
|
||||
@include clearfix;
|
||||
@include box-sizing(border-box);
|
||||
background: #f6f6f6;
|
||||
border-bottom: 1px solid rgb(200,200,200);
|
||||
background: none;
|
||||
margin: 0px auto 0px;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
@@ -37,11 +36,6 @@ nav.course-material {
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: rgb(255,255,255);
|
||||
border: 1px solid rgb(200,200,200);
|
||||
border-bottom: 0px;
|
||||
@include border-top-radius(4px);
|
||||
@include box-shadow(0 2px 0 0 rgba(255,255,255, 1));
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
4
lms/static/sass/course/layout/_footer.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
footer {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
section.wiki {
|
||||
padding-top: 25px;
|
||||
|
||||
> header {
|
||||
height: 33px;
|
||||
margin-bottom: 36px;
|
||||
padding-bottom: 26px;
|
||||
border-bottom: 1px solid $light-gray;
|
||||
}
|
||||
|
||||
.pull-left {
|
||||
float: left;
|
||||
}
|
||||
@@ -16,6 +9,18 @@ section.wiki {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.wiki-wrapper {
|
||||
@include clearfix;
|
||||
|
||||
> header {
|
||||
height: 33px;
|
||||
padding: 24px 0 26px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-radius: 3px 3px 0 0;
|
||||
background-color: $sidebar-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------
|
||||
@@ -27,7 +32,7 @@ section.wiki {
|
||||
.breadcrumb {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0 0 0 flex-gutter();
|
||||
margin: 0 0 0 40px;
|
||||
|
||||
li {
|
||||
float: left;
|
||||
@@ -68,7 +73,7 @@ section.wiki {
|
||||
.global-functions {
|
||||
display: block;
|
||||
width: auto;
|
||||
margin-right: flex-gutter();
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.add-article-btn {
|
||||
@@ -129,8 +134,9 @@ section.wiki {
|
||||
.main-article {
|
||||
float: left;
|
||||
width: flex-grid(9);
|
||||
margin-left: flex-gutter();
|
||||
padding: 40px 0 40px 40px;
|
||||
color: $base-font-color;
|
||||
@include box-sizing(border-box);
|
||||
}
|
||||
|
||||
&.view .main-article {
|
||||
@@ -193,6 +199,17 @@ section.wiki {
|
||||
font-size: 0.9em;
|
||||
font-family: Monaco, monospace;
|
||||
}
|
||||
|
||||
.toc {
|
||||
background-color: $sidebar-color;
|
||||
padding: 9px;
|
||||
margin: 10px 0;
|
||||
@include border-radius(5px);
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,13 +223,14 @@ section.wiki {
|
||||
|
||||
.article-functions {
|
||||
float: left;
|
||||
width: flex-grid(2) + flex-gutter();
|
||||
margin-left: flex-grid(1);
|
||||
width: flex-grid(3);
|
||||
padding: 40px 40px;
|
||||
@include box-sizing(border-box);
|
||||
|
||||
.timestamp {
|
||||
margin: 4px 0 15px;
|
||||
padding: 0 0 15px 5px;
|
||||
border-bottom: 1px solid $light-gray;
|
||||
.timestamp{
|
||||
margin-top: 15px;
|
||||
padding: 15px 0 0 10px;
|
||||
border-top: 1px solid $light-gray;
|
||||
|
||||
.label {
|
||||
font-size: 0.7em;
|
||||
@@ -223,6 +241,26 @@ section.wiki {
|
||||
.date {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.see-children {
|
||||
padding: 15px 0 0;
|
||||
border-top: 1px solid $light-gray;
|
||||
margin-top: 15px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 2px 4px 2px 10px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.9em;
|
||||
line-height: 25px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f6f6f6;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +274,8 @@ section.wiki {
|
||||
a {
|
||||
color: $blue;
|
||||
|
||||
.icon-view {
|
||||
.icon-view,
|
||||
.icon-home {
|
||||
background-position: -25px 0;
|
||||
}
|
||||
|
||||
@@ -244,11 +283,13 @@ section.wiki {
|
||||
background-position: -25px -25px;
|
||||
}
|
||||
|
||||
.icon-changes {
|
||||
.icon-changes,
|
||||
.icon-time {
|
||||
background-position: -25px -49px;
|
||||
}
|
||||
|
||||
.icon-attachments {
|
||||
.icon-attachments,
|
||||
.icon-file {
|
||||
background-position: -25px -73px;
|
||||
}
|
||||
|
||||
@@ -280,7 +321,8 @@ section.wiki {
|
||||
background: url(../images/wiki-icons.png) no-repeat;
|
||||
}
|
||||
|
||||
.icon-view {
|
||||
.icon-view,
|
||||
.icon-home {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
@@ -288,11 +330,13 @@ section.wiki {
|
||||
background-position: 0 -25px;
|
||||
}
|
||||
|
||||
.icon-changes {
|
||||
.icon-changes,
|
||||
.icon-time {
|
||||
background-position: 0 -49px;
|
||||
}
|
||||
|
||||
.icon-attachments {
|
||||
.icon-attachments,
|
||||
.icon-file {
|
||||
background-position: 0 -73px;
|
||||
}
|
||||
|
||||
@@ -646,6 +690,59 @@ section.wiki {
|
||||
margin-top: 9px;
|
||||
}
|
||||
|
||||
/*-----------------
|
||||
|
||||
Directory
|
||||
|
||||
-----------------*/
|
||||
.directory-toolbar {
|
||||
background-color: $sidebar-color;
|
||||
padding: 9px;
|
||||
margin: 0 -9px 20px;
|
||||
@include border-radius(5px);
|
||||
|
||||
.well-small {
|
||||
@include clearfix;
|
||||
|
||||
a {
|
||||
@include inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
+ p {
|
||||
font-size: 0.9em;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-clear {
|
||||
margin-right: 10px;
|
||||
margin-top: 10px;
|
||||
font-size: .9em;
|
||||
|
||||
a {
|
||||
color: #aaa;
|
||||
|
||||
&:hover {
|
||||
color: #777;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table.table-striped {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
|
||||
th, td {
|
||||
border-bottom: 1px solid $light-gray;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background: #F6F6F6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -706,6 +803,10 @@ section.wiki {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.attachment-actions {
|
||||
width: 175px;
|
||||
}
|
||||
|
||||
.attachment-actions .btn {
|
||||
float: right;
|
||||
}
|
||||
@@ -767,6 +868,39 @@ section.wiki {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.missing {
|
||||
max-width: 400px;
|
||||
margin: lh(2) auto;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
background: $pink;
|
||||
padding: lh();
|
||||
@include box-shadow(inset 0 0 0 1px lighten($pink, 10%));
|
||||
border: 1px solid darken($pink, 15%);
|
||||
|
||||
p {
|
||||
color: #fff;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
background: darken($pink, 8%);
|
||||
margin: lh() (-(lh())) (-(lh()));
|
||||
padding: lh();
|
||||
border-top: 1px solid darken($pink, 15%);
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: em(18);
|
||||
@include transition;
|
||||
text-align: center;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
|
||||
&:hover {
|
||||
background: darken($pink, 12%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
|
||||
@@ -48,7 +48,6 @@ footer {
|
||||
|
||||
a:link, a:visited {
|
||||
color: $lighter-base-font-color;
|
||||
letter-spacing: 1px;
|
||||
padding: 6px 0px;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +69,7 @@ footer {
|
||||
position: relative;
|
||||
width: 47px;
|
||||
vertical-align: middle;
|
||||
@include transition(none);
|
||||
|
||||
&:hover {
|
||||
background-position: 0 0;
|
||||
@@ -90,7 +90,6 @@ footer {
|
||||
a {
|
||||
color: $lighter-base-font-color;
|
||||
@include inline-block;
|
||||
letter-spacing: 1px;
|
||||
margin-right: 20px;
|
||||
padding-top: 2px;
|
||||
vertical-align: middle;
|
||||
@@ -165,7 +164,6 @@ footer {
|
||||
color: $lighter-base-font-color;
|
||||
font-family: $serif;
|
||||
font-style: italic;
|
||||
letter-spacing: 1px;
|
||||
line-height: 1.6em;
|
||||
margin-left: 20px;
|
||||
text-transform: lowercase;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +131,7 @@ header.global {
|
||||
|
||||
&.user {
|
||||
float: right;
|
||||
margin-top: 4px;
|
||||
|
||||
> li.primary {
|
||||
display: block;
|
||||
@@ -151,22 +147,22 @@ header.global {
|
||||
> a {
|
||||
@include border-radius(0 4px 4px 0);
|
||||
border-left: none;
|
||||
padding: 5px 8px 7px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.user-link {
|
||||
padding: 10px 12px 10px 42px;
|
||||
padding: 6px 12px 8px 35px;
|
||||
position: relative;
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
|
||||
.avatar {
|
||||
//background: rgb(220,220,220);
|
||||
@include background-image(url('../images/portal-icons/home-icon.png'));
|
||||
background-size: cover;
|
||||
//@include border-radius(3px);
|
||||
//border: 1px solid rgb(80,80,80);
|
||||
//@include box-shadow(0 1px 0 0 rgba(255,255,255, 0.6));
|
||||
@include background-image(url('../images/small-header-home-icon.png'));
|
||||
background-repeat: no-repeat;
|
||||
height: 26px;
|
||||
@include inline-block;
|
||||
left: 8px;
|
||||
@@ -194,7 +190,7 @@ header.global {
|
||||
padding: 5px 10px;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 50px;
|
||||
top: 34px;
|
||||
width: 170px;
|
||||
z-index: 3;
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
|
||||
<%def name="make_chapter(chapter)">
|
||||
<h3 ${' class="active"' if 'active' in chapter and chapter['active'] else ''}><a href="#">${chapter['display_name']}</a>
|
||||
</h3>
|
||||
<div class="chapter">
|
||||
<h3 ${' class="active"' if 'active' in chapter and chapter['active'] else ''}><a href="#">${chapter['display_name']}</a>
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
% for section in chapter['sections']:
|
||||
<li${' class="active"' if 'active' in section and section['active'] else ''}>
|
||||
<a href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}">
|
||||
<p>${section['display_name']}
|
||||
<span class="subtitle">
|
||||
${section['format']} ${"due " + section['due'] if 'due' in section and section['due'] != '' else ''}
|
||||
</span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
<ul>
|
||||
% for section in chapter['sections']:
|
||||
<li${' class="active"' if 'active' in section and section['active'] else ''}>
|
||||
<a href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}">
|
||||
<p>${section['display_name']}
|
||||
<span class="subtitle">
|
||||
${section['format']} ${"due " + section['due'] if 'due' in section and section['due'] != '' else ''}
|
||||
</span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
% for chapter in toc:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%inherit file="/main.html" />
|
||||
<%namespace name='static' file='/static_content.html'/>
|
||||
<%block name="bodyclass">courseware</%block>
|
||||
<%block name="bodyclass">courseware ${course.css_class}</%block>
|
||||
<%block name="title"><title>${course.number} Courseware</title></%block>
|
||||
|
||||
<%block name="headextra">
|
||||
@@ -11,6 +11,7 @@
|
||||
<%block name="js_extra">
|
||||
<script type="text/javascript" src="${static.url('js/vendor/jquery.scrollTo-1.4.2-min.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/flot/jquery.flot.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/jquery.sequence.js')}"></script>
|
||||
|
||||
## codemirror
|
||||
<script type="text/javascript" src="${static.url('js/vendor/codemirror-compressed.js')}"></script>
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
<thead>
|
||||
<tr> <!-- Header Row -->
|
||||
%for section in templateSummary['section_breakdown']:
|
||||
<th>${section['label']}</th>
|
||||
<th><div class="assignment-label">${section['label']}</div></th>
|
||||
%endfor
|
||||
<th>Total</th>
|
||||
<th><div class="assignment-label">Total</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
%>
|
||||
|
||||
<section class="container">
|
||||
<div class="syllabus">
|
||||
<h1> Syllabus </h1>
|
||||
% if user.is_authenticated():
|
||||
${get_course_syllabus_section(course, 'syllabus')}
|
||||
% else:
|
||||
${get_course_syllabus_section(course, 'guest_syllabus')}
|
||||
% endif
|
||||
<div class="syllabus_wrapper">
|
||||
<div class="syllabus">
|
||||
<h1> Syllabus </h1>
|
||||
% if user.is_authenticated():
|
||||
${get_course_syllabus_section(course, 'syllabus')}
|
||||
% else:
|
||||
${get_course_syllabus_section(course, 'guest_syllabus')}
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<nav>
|
||||
<section class="top">
|
||||
<section class="primary">
|
||||
<a href="${reverse('root')}" class="logo"></a>
|
||||
<a href="https://www.edx.org" class="logo"></a>
|
||||
<a href="${reverse('courses')}">Find Courses</a>
|
||||
<a href="${reverse('about_edx')}">About</a>
|
||||
<a href="http://edxonline.tumblr.com/">Blog</a>
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
<h1>There has been an error on the <em>MITx</em> servers</h1>
|
||||
<p>We're sorry, this module is temporarily unavailable. Our staff is working to fix it as soon as possible. Please email us at <a href="mailto:technical@mitx.mit.edu">technical@mitx.mit.edu</a> to report any problems or downtime.</p>
|
||||
|
||||
<h1>Details below:</h1>
|
||||
% if staff_access:
|
||||
<h1>Details</h1>
|
||||
|
||||
<p>Error: ${error | h}</p>
|
||||
<p>Error:
|
||||
<pre>
|
||||
${error | h}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>Raw data: ${data | h}</p>
|
||||
<p>Raw data:
|
||||
|
||||
<pre>${data | h}</pre>
|
||||
</p>
|
||||
|
||||
% endif
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<%inherit file="main.html" />
|
||||
<%include file="navigation.html" args="active_page=''" />
|
||||
<script>
|
||||
function name_confirm(id) {
|
||||
postJSON('/accept_name_change',{"id":id},
|
||||
|
||||
@@ -3,11 +3,20 @@
|
||||
## one for people who aren't. Assume a Course object is passed to the former,
|
||||
## instead of using settings.COURSE_TITLE
|
||||
<%namespace name='static' file='static_content.html'/>
|
||||
<%! from django.core.urlresolvers import reverse %>
|
||||
<%!
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
<header class="global" aria-label="Global Navigation">
|
||||
# App that handles subdomain specific branding
|
||||
import branding
|
||||
%>
|
||||
|
||||
%if course:
|
||||
<header class="global slim" aria-label="Global Navigation">
|
||||
%else:
|
||||
<header class="global" aria-label="Global Navigation">
|
||||
%endif
|
||||
<nav>
|
||||
<h1 class="logo"><a href="${reverse('root')}"></a></h1>
|
||||
<h1 class="logo"><a href="${reverse('root')}"><img src="${static.url(branding.get_logo_url(request.META.get('HTTP_HOST')))}"/></a></h1>
|
||||
|
||||
%if course:
|
||||
<h2><span class="provider">${course.org}:</span> ${course.number} ${course.title}</h2>
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
<div id="sequence_${element_id}" class="sequence" data-id="${item_id}" data-position="${position}" data-course_modx_root="/course/modx" >
|
||||
<nav aria-label="Section Navigation" class="sequence-nav">
|
||||
<ol id="sequence-list">
|
||||
% for idx, item in enumerate(items):
|
||||
## TODO (vshnayder): add item.progress_detail either to the title or somewhere else.
|
||||
## Make sure it gets updated after ajax calls.
|
||||
## implementation note: will need to figure out how to handle combining detail
|
||||
## statuses of multiple modules in js.
|
||||
<li>
|
||||
<a class="seq_${item['type']} inactive progress-${item['progress_status']}" data-element="${idx+1}">
|
||||
<p>${item['title']}</p>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ol>
|
||||
<div class="sequence-list-wrapper">
|
||||
<ol id="sequence-list">
|
||||
% for idx, item in enumerate(items):
|
||||
## TODO (vshnayder): add item.progress_detail either to the title or somewhere else.
|
||||
## Make sure it gets updated after ajax calls.
|
||||
## implementation note: will need to figure out how to handle combining detail
|
||||
## statuses of multiple modules in js.
|
||||
<li>
|
||||
<a class="seq_${item['type']} inactive progress-${item['progress_status']}" data-element="${idx+1}">
|
||||
<p>${item['title']}</p>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<ul class="sequence-nav-buttons">
|
||||
<li class="prev"><a href="#">Previous</a></li>
|
||||
@@ -21,7 +23,7 @@
|
||||
</nav>
|
||||
|
||||
% for item in items:
|
||||
<div class="seq_contents tex2jax_ignore">${item['content'] | h}</div>
|
||||
<div class="seq_contents tex2jax_ignore asciimath2jax_ignore">${item['content'] | h}</div>
|
||||
% endfor
|
||||
<div id="seq_content"></div>
|
||||
|
||||
@@ -32,3 +34,15 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var sequenceNav;
|
||||
$(document).ready(function() {
|
||||
// console.log($('.sequence-nav'));
|
||||
|
||||
sequenceNav = new SequenceNav($('.sequence-nav'));
|
||||
console.log(sequenceNav);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<%inherit file="main.html" />
|
||||
<%block name="title"><title>Textbook – MITx 6.002x</title></%block>
|
||||
|
||||
<div id="bodyContent">
|
||||
<%include file="navigation.html" />
|
||||
|
||||
<div>
|
||||
${ text }
|
||||
</div>
|
||||
</div>
|
||||
@@ -11,25 +11,32 @@
|
||||
{% block wiki_contents %}
|
||||
|
||||
<div class="article-wrapper">
|
||||
|
||||
|
||||
<article class="main-article">
|
||||
{% if selected_tab != "edit" %}
|
||||
<h1>{{ article.current_revision.title }}</h1>
|
||||
<h1>{{ article.current_revision.title }}</h1>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% block wiki_contents_tab %}
|
||||
{% wiki_render article %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
</article>
|
||||
|
||||
<div class="article-functions">
|
||||
<ul class="nav nav-tabs">
|
||||
{% include "wiki/includes/article_menu.html" %}
|
||||
</ul>
|
||||
<div class="timestamp">
|
||||
<span class="label">{% trans "Last modified:" %}</span><br />
|
||||
<span class="date">{{ article.current_revision.modified }}</span>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
{% include "wiki/includes/article_menu.html" %}
|
||||
</ul>
|
||||
|
||||
{% if urlpath %}
|
||||
<div class="see-children">
|
||||
<a href="{% url 'wiki:dir' path=urlpath.path %}">See all children</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -51,24 +51,24 @@
|
||||
{% endif %}
|
||||
|
||||
<section class="container wiki {{ selected_tab }}">
|
||||
<div class="wiki-wrapper">
|
||||
{% block wiki_body %}
|
||||
|
||||
{% block wiki_breadcrumbs %}{% endblock %}
|
||||
|
||||
{% block wiki_body %}
|
||||
|
||||
{% block wiki_breadcrumbs %}{% endblock %}
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }}">
|
||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% block wiki_contents %}{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }}">
|
||||
<a class="close" data-dismiss="alert" href="#">×</a>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% block wiki_contents %}{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
{% extends "wiki/base.html" %}
|
||||
{% load wiki_tags i18n sekizai_tags %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block pagetitle %}{% trans "Delete article" %}{% endblock %}
|
||||
|
||||
{% block wiki_contents %}
|
||||
<h1 class="page-header">{% trans "Delete" %} "{{ article.current_revision.title }}"</h1>
|
||||
|
||||
{% if cannot_delete_root %}
|
||||
<p class="lead">{% trans "You cannot delete a root article." %}</p>
|
||||
<p><a href="{% url 'wiki:get' path=urlpath.path article_id=article.id %}">{% trans "Go back" %}</a></p>
|
||||
{% else %}
|
||||
|
||||
{% if cannot_delete_children %}
|
||||
|
||||
<p class="alert alert-error"><strong>{% trans "You cannot delete this article because you do not have permission to delete articles with children. Try to remove the children manually one-by-one." %}</strong></p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if delete_children %}
|
||||
|
||||
<p class="lead">{% trans "You are deleting an article. This means that its children will be deleted as well. If you choose to purge, children will also be purged!" %}</p>
|
||||
|
||||
<h2>{% trans "Articles that will be deleted" %}</h2>
|
||||
|
||||
<ul>
|
||||
{% for child in delete_children %}
|
||||
<li><a href="{% url 'wiki:get' article_id=child.article.id %}" target="_blank">{{ child.article }}</a></li>
|
||||
{% if delete_children_more %}
|
||||
<li><em>{% trans "...and more!" %}</em></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if not cannot_delete_children %}
|
||||
<p class="lead">{% trans "You are deleting an article. Please confirm." %}</p>
|
||||
|
||||
<form method="POST" class="form-horizontal">
|
||||
{% wiki_form delete_form %}
|
||||
<script type="text/javascript">
|
||||
$('#id_revision').val('{{ article.current_revision.id }}');
|
||||
</script>
|
||||
<div class="form-actions">
|
||||
<a href="{% url 'wiki:get' path=urlpath.path article_id=article.id %}" class="btn btn-large">
|
||||
<span class="icon-circle-arrow-left"></span>
|
||||
{% trans "Go back" %}
|
||||
</a>
|
||||
<button type="submit" name="save_changes" class="btn btn-danger btn-large">
|
||||
<span class="icon-plus"></span>
|
||||
{% trans "Delete article" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<li class="${"active" if selected_tab == "view" else ""}">
|
||||
<a href="${reverse('wiki:get', kwargs={'article_id' : article.id, 'path' : urlpath.path})}">
|
||||
<span class="icon-home"></span>
|
||||
<span class="icon-home icon"></span>
|
||||
View
|
||||
</a>
|
||||
</li>
|
||||
@@ -11,7 +11,7 @@
|
||||
%if article.can_write(user):
|
||||
<li class="${"active" if selected_tab == "edit" else ""}">
|
||||
<a href="${reverse('wiki:edit', kwargs={'article_id' : article.id, 'path' : urlpath.path})}">
|
||||
<span class="icon-edit"></span>
|
||||
<span class="icon-edit icon"></span>
|
||||
Edit
|
||||
</a>
|
||||
</li>
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<li class="${"active" if selected_tab == "history" else ""}">
|
||||
<a href="${reverse('wiki:history', kwargs={'article_id' : article.id, 'path' : urlpath.path})}">
|
||||
<span class="icon-time"></span>
|
||||
<span class="icon-changes icon"></span>
|
||||
Changes
|
||||
</a>
|
||||
</li>
|
||||
@@ -28,19 +28,25 @@
|
||||
%if hasattr(plugin, "article_tab"):
|
||||
<li class="${"active" if selected_tab == plugin.slug else ""}">
|
||||
<a href="${reverse('wiki:plugin', kwargs={'slug' : plugin.slug, 'article_id' : article.id, 'path' : urlpath.path}) }">
|
||||
<span class="${plugin.article_tab[1]}"></span>
|
||||
<span class="${plugin.article_tab[1]} icon"></span>
|
||||
${plugin.article_tab[0]}
|
||||
</a>
|
||||
</li>
|
||||
%endif
|
||||
%endfor
|
||||
|
||||
|
||||
<%doc>
|
||||
The settings link has been disabled because the notifications app hasn't been integrated yet and those are the only useful settings.
|
||||
|
||||
%if not user.is_anonymous():
|
||||
<li class="${"active" if selected_tab == "settings" else ""}">
|
||||
<a href="${reverse('wiki:settings', kwargs={'article_id' : article.id, 'path' : urlpath.path})}">
|
||||
<span class="icon-wrench"></span>
|
||||
<span class="icon-settings icon"></span>
|
||||
Settings
|
||||
</a>
|
||||
</li>
|
||||
%endif
|
||||
</%doc>
|
||||
|
||||
|
||||
|
||||
@@ -115,7 +115,13 @@
|
||||
{% if attachment.current_revision.user %}{{ attachment.current_revision.user }}{% else %}{% if user|is_moderator %}{{ attachment.current_revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
|
||||
</td>
|
||||
<td>{{ attachment.current_revision.get_size|filesizeformat }}</td>
|
||||
<td>{{ attachment.attachmentrevision_set.all.count }} {% trans "revisions" %}</td>
|
||||
|
||||
<td>
|
||||
<a href="{% url 'wiki:attachments_history' path=urlpath.path article_id=article.id attachment_id=attachment.id %}">
|
||||
<span class="icon-time"></span>
|
||||
{% trans "File history" %} ({{ attachment.attachmentrevision_set.all.count }} {% trans "revisions" %})
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -10,22 +10,31 @@
|
||||
<div class="main-article">
|
||||
{% if revision %}
|
||||
<div class="alert alert-info">
|
||||
<strong>{% trans "Previewing revision" %}:</strong> {{ revision.created }} (#{{ revision.revision_number }}) by {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
|
||||
<strong>{% trans "Previewing revision" %}:</strong>
|
||||
{% include "wiki/includes/revision_info.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if merge %}
|
||||
<div class="alert alert-info">
|
||||
<strong>{% trans "Previewing merge between" %}:</strong>
|
||||
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
|
||||
{% include "wiki/includes/revision_info.html" with revision=merge1 %}
|
||||
<strong>{% trans "and" %}</strong>
|
||||
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
|
||||
{% include "wiki/includes/revision_info.html" with revision=merge2 %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h1 class="page-header">{{ title }}</h1>
|
||||
|
||||
{% wiki_render article content %}
|
||||
{% if revision and revision.deleted %}
|
||||
<div class="warning">
|
||||
<strong>This revision has been deleted.</strong>
|
||||
<p>Restoring to this revision will mark the article as deleted.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
{% wiki_render article content %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
{% extends "wiki/base.html" %}
|
||||
{% load wiki_tags i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block pagetitle %}{% trans "Settings" %}: {{ article.current_revision.title }}{% endblock %}
|
||||
|
||||
{% block wiki_breadcrumbs %}
|
||||
{% include "wiki/includes/breadcrumbs.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block wiki_contents %}
|
||||
|
||||
<div class="article-wrapper">
|
||||
<article class="main-article">
|
||||
{% if selected_tab != "edit" %}
|
||||
<h1>{{ article.current_revision.title }}</h1>
|
||||
{% endif %}
|
||||
|
||||
{% for form in forms %}
|
||||
<form method="POST" class="form-horizontal" id="settings_form" action="?f={{form.action}}">
|
||||
<h2>{{ form.settings_form_headline }}</h2>
|
||||
<div class="well">
|
||||
{% wiki_form form %}
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button type="submit" name="save" value="1" class="btn btn-large btn-primary">
|
||||
<span class="icon-ok"></span>
|
||||
{% trans "Save changes" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</article>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="article-functions">
|
||||
<div class="timestamp">
|
||||
<span class="label">{% trans "Last modified:" %}</span><br />
|
||||
<span class="date">{{ article.current_revision.modified }}</span>
|
||||
</div>
|
||||
<ul class="nav nav-tabs">
|
||||
{% with "settings" as selected %}
|
||||
{% include "wiki/includes/article_menu.html" %}
|
||||
{% endwith %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{% extends "wiki/base.html" %}
|
||||
{% load wiki_tags i18n %}
|
||||
{% load url from future %}
|
||||
|
||||
{% block pagetitle %}{{ article.current_revision.title }}{% endblock %}
|
||||
|
||||
{% block wiki_breadcrumbs %}
|
||||
{% include "wiki/includes/breadcrumbs.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block wiki_contents %}
|
||||
|
||||
<div class="missing-wrapper">
|
||||
<p>This article was not found, and neither was the parent. <a href="#">Go back to the main wiki article.</a></p>
|
||||
<button type="submit">Create a new article</button>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -10,7 +10,7 @@ if settings.DEBUG:
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = ('',
|
||||
url(r'^$', 'student.views.index', name="root"), # Main marketing page, or redirect to courseware
|
||||
url(r'^$', 'branding.views.index', name="root"), # Main marketing page, or redirect to courseware
|
||||
url(r'^dashboard$', 'student.views.dashboard', name="dashboard"),
|
||||
|
||||
url(r'^admin_dashboard$', 'dashboard.views.dashboard'),
|
||||
@@ -115,7 +115,7 @@ if settings.COURSEWARE_ENABLED:
|
||||
# url(r'^edit_circuit/(?P<circuit>[^/]*)$', 'circuit.views.edit_circuit'),
|
||||
# url(r'^save_circuit/(?P<circuit>[^/]*)$', 'circuit.views.save_circuit'),
|
||||
|
||||
url(r'^courses/?$', 'courseware.views.courses', name="courses"),
|
||||
url(r'^courses/?$', 'branding.views.courses', name="courses"),
|
||||
url(r'^change_enrollment$',
|
||||
'student.views.change_enrollment_view', name="change_enrollment"),
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-e git://github.com/MITx/django-staticfiles.git@6d2504e5c8#egg=django-staticfiles
|
||||
-e git://github.com/MITx/django-pipeline.git#egg=django-pipeline
|
||||
-e git://github.com/benjaoming/django-wiki.git@02275fb4#egg=django-wiki
|
||||
-e git://github.com/benjaoming/django-wiki.git@63003aa#egg=django-wiki
|
||||
-e git://github.com/dementrock/pystache_custom.git@776973740bdaad83a3b029f96e415a7d1e8bec2f#egg=pystache_custom-dev
|
||||
-e common/lib/capa
|
||||
-e common/lib/xmodule
|
||||
|
||||
@@ -2,7 +2,7 @@ django>=1.4,<1.5
|
||||
pip
|
||||
numpy
|
||||
scipy
|
||||
markdown
|
||||
Markdown<2.3.0
|
||||
pygments
|
||||
lxml
|
||||
boto
|
||||
@@ -43,5 +43,7 @@ django-ses
|
||||
django-storages
|
||||
django-threaded-multihost
|
||||
django-sekizai<0.7
|
||||
django-mptt>=0.5.3
|
||||
sorl-thumbnail
|
||||
networkx
|
||||
-r repo-requirements.txt
|
||||
|
||||