Commit 0fbfaf61 by Bridger Maxwell

Merge remote-tracking branch 'origin/master' into feature/bridger/new_wiki

parents 68f3aabc 445ce72b
......@@ -24,6 +24,7 @@ MODULESTORE = {
'db': 'xmodule',
'collection': 'modulestore',
'fs_root': GITHUB_REPO_ROOT,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
}
}
......
......@@ -47,6 +47,7 @@ MODULESTORE = {
'db': 'test_xmodule',
'collection': 'modulestore',
'fs_root': GITHUB_REPO_ROOT,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
}
}
......
......@@ -15,7 +15,7 @@ def try_staticfiles_lookup(path):
try:
url = staticfiles_storage.url(path)
except Exception as err:
log.warning("staticfiles_storage couldn't find path {}: {}".format(
log.warning("staticfiles_storage couldn't find path {0}: {1}".format(
path, str(err)))
# Just return the original path; don't kill everything.
url = path
......
......@@ -279,7 +279,8 @@ def replicate_enrollment_save(sender, **kwargs):
enrollment_obj = kwargs['instance']
log.debug("Replicating user because of new enrollment")
replicate_user(enrollment_obj.user, enrollment_obj.course_id)
for course_db_name in db_names_to_replicate_to(enrollment_obj.user.id):
replicate_user(enrollment_obj.user, course_db_name)
log.debug("Replicating enrollment because of new enrollment")
replicate_model(CourseEnrollment.save, enrollment_obj, enrollment_obj.user_id)
......
......@@ -873,6 +873,7 @@ def sympy_check2():
msg = '<font color="red">No answer entered!</font>' if self.xml.get('empty_answer_err') else ''
return CorrectMap(idset[0], 'incorrect', msg=msg)
# NOTE: correct = 'unknown' could be dangerous. Inputtypes such as textline are not expecting 'unknown's
correct = ['unknown'] * len(idset)
messages = [''] * len(idset)
......@@ -898,6 +899,7 @@ def sympy_check2():
if type(self.code) == str:
try:
exec self.code in self.context['global_context'], self.context
correct = self.context['correct']
except Exception as err:
print "oops in customresponse (code) error %s" % err
print "context = ", self.context
......@@ -1271,7 +1273,7 @@ main()
def setup_response(self):
xml = self.xml
self.url = xml.get('url') or "http://eecs1.mit.edu:8889/pyloncapa" # FIXME - hardcoded URL
self.url = xml.get('url') or "http://qisx.mit.edu:8889/pyloncapa" # FIXME - hardcoded URL
# answer = xml.xpath('//*[@id=$id]//answer',id=xml.get('id'))[0] # FIXME - catch errors
answer = xml.find('answer')
......
......@@ -38,5 +38,7 @@
% if msg:
<span class="message">${msg|n}</span>
% endif
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete'] or hidden:
</div>
% endif
</section>
from setuptools import setup, find_packages
setup(
name="mitxmako",
version="0.1",
packages=find_packages(exclude=["tests"]),
install_requires=['distribute'],
)
......@@ -10,7 +10,6 @@ setup(
},
requires=[
'capa',
'mitxmako'
],
# See http://guide.python-distribute.org/creation.html#entry-points
......
......@@ -68,7 +68,7 @@ class SemanticSectionDescriptor(XModuleDescriptor):
the child element
"""
xml_object = etree.fromstring(xml_data)
system.error_tracker("WARNING: the <{}> tag is deprecated. Please do not use in new content."
system.error_tracker("WARNING: the &lt;{0}> tag is deprecated. Please do not use in new content."
.format(xml_object.tag))
if len(xml_object) == 1:
......
......@@ -108,11 +108,9 @@ class CapaModule(XModule):
self.grace_period = None
self.close_date = self.display_due_date
self.max_attempts = only_one(dom2.xpath('/problem/@attempts'))
if len(self.max_attempts) > 0:
self.max_attempts = self.metadata.get('attempts', None)
if self.max_attempts is not None:
self.max_attempts = int(self.max_attempts)
else:
self.max_attempts = None
self.show_answer = self.metadata.get('showanswer', 'closed')
......@@ -244,7 +242,14 @@ class CapaModule(XModule):
# We using strings as truthy values, because the terminology of the
# check button is context-specific.
check_button = "Grade" if self.max_attempts else "Check"
# Put a "Check" button if unlimited attempts or still some left
if self.max_attempts is None or self.attempts < self.max_attempts-1:
check_button = "Check"
else:
# Will be final check so let user know that
check_button = "Final Check"
reset_button = True
save_button = True
......
......@@ -14,7 +14,7 @@ div.video {
section.video-player {
height: 0;
// overflow: hidden;
overflow: hidden;
padding-bottom: 56.25%;
position: relative;
......@@ -171,7 +171,7 @@ div.video {
position: relative;
@include transition();
-webkit-font-smoothing: antialiased;
width: 110px;
width: 116px;
h3 {
color: #999;
......@@ -209,7 +209,7 @@ div.video {
display: none;
opacity: 0;
position: absolute;
width: 125px;
width: 133px;
z-index: 10;
li {
......@@ -444,13 +444,13 @@ div.video {
height: 100%;
left: 0;
margin: 0;
max-height: 100%;
overflow: hidden;
padding: 0;
position: fixed;
top: 0;
width: 100%;
z-index: 999;
vertical-align: middle;
&.closed {
ol.subtitles {
......@@ -459,30 +459,17 @@ div.video {
}
}
a.exit {
color: #aaa;
display: none;
font-style: 12px;
left: 20px;
letter-spacing: 1px;
position: absolute;
text-transform: uppercase;
top: 20px;
&::after {
content: "✖";
@include inline-block();
padding-left: 6px;
}
&:hover {
color: $mit-red;
}
}
div.tc-wrapper {
@include clearfix;
display: table;
width: 100%;
height: 100%;
article.video-wrapper {
width: 100%;
display: table-cell;
vertical-align: middle;
float: none;
}
object, iframe {
......
......@@ -39,6 +39,8 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
def backcompat_paths(cls, path):
if path.endswith('.html.xml'):
path = path[:-9] + '.html' # backcompat--look for html instead of xml
if path.endswith('.html.html'):
path = path[:-5] # some people like to include .html in filenames..
candidates = []
while os.sep in path:
candidates.append(path)
......@@ -73,7 +75,9 @@ class HtmlDescriptor(XmlDescriptor, EditingDescriptor):
cls.clean_metadata_from_xml(definition_xml)
return {'data': stringify_children(definition_xml)}
else:
filepath = cls._format_filepath(xml_object.tag, filename)
# html is special. cls.filename_extension is 'xml', but if 'filename' is in the definition,
# that means to load from .html
filepath = "{category}/{name}.html".format(category='html', name=filename)
# VS[compat]
# TODO (cpennington): If the file doesn't exist at the right path,
......
......@@ -130,13 +130,11 @@ class @VideoPlayer extends Subview
toggleFullScreen: (event) =>
event.preventDefault()
if @el.hasClass('fullscreen')
@$('.exit').remove()
@$('.add-fullscreen').attr('title', 'Fill browser')
@el.removeClass('fullscreen')
else
@el.append('<a href="#" class="exit">Exit</a>').addClass('fullscreen')
@el.addClass('fullscreen')
@$('.add-fullscreen').attr('title', 'Exit fill browser')
@$('.exit').click @toggleFullScreen
@caption.resize()
# Delegates
......
......@@ -12,15 +12,34 @@ from django.conf import settings
_MODULESTORES = {}
FUNCTION_KEYS = ['render_template']
def load_function(path):
"""
Load a function by name.
path is a string of the form "path.to.module.function"
returns the imported python object `function` from `path.to.module`
"""
module_path, _, name = path.rpartition('.')
return getattr(import_module(module_path), name)
def modulestore(name='default'):
global _MODULESTORES
if name not in _MODULESTORES:
class_path = settings.MODULESTORE[name]['ENGINE']
module_path, _, class_name = class_path.rpartition('.')
class_ = getattr(import_module(module_path), class_name)
class_ = load_function(settings.MODULESTORE[name]['ENGINE'])
options = {}
options.update(settings.MODULESTORE[name]['OPTIONS'])
for key in FUNCTION_KEYS:
if key in options:
options[key] = load_function(options[key])
_MODULESTORES[name] = class_(
**settings.MODULESTORE[name]['OPTIONS'])
**options
)
return _MODULESTORES[name]
......@@ -9,7 +9,6 @@ from importlib import import_module
from xmodule.errortracker import null_error_tracker
from xmodule.x_module import XModuleDescriptor
from xmodule.mako_module import MakoDescriptorSystem
from mitxmako.shortcuts import render_to_string
from . import ModuleStoreBase, Location
from .exceptions import (ItemNotFoundError,
......@@ -82,7 +81,8 @@ class MongoModuleStore(ModuleStoreBase):
"""
# TODO (cpennington): Enable non-filesystem filestores
def __init__(self, host, db, collection, fs_root, port=27017, default_class=None,
def __init__(self, host, db, collection, fs_root, render_template,
port=27017, default_class=None,
error_tracker=null_error_tracker):
ModuleStoreBase.__init__(self)
......@@ -108,6 +108,7 @@ class MongoModuleStore(ModuleStoreBase):
self.default_class = None
self.fs_root = path(fs_root)
self.error_tracker = error_tracker
self.render_template = render_template
def _clean_item_data(self, item):
"""
......@@ -160,7 +161,7 @@ class MongoModuleStore(ModuleStoreBase):
self.default_class,
resource_fs,
self.error_tracker,
render_to_string,
self.render_template,
)
return system.load_item(item['location'])
......
......@@ -26,6 +26,7 @@ DB = 'test'
COLLECTION = 'modulestore'
FS_ROOT = DATA_DIR # TODO (vshnayder): will need a real fs_root for testing load_item
DEFAULT_CLASS = 'xmodule.raw_module.RawDescriptor'
RENDER_TEMPLATE = lambda t_n, d, ctx=None, nsp='main': ''
class TestMongoModuleStore(object):
......@@ -48,7 +49,7 @@ class TestMongoModuleStore(object):
@staticmethod
def initdb():
# connect to the db
store = MongoModuleStore(HOST, DB, COLLECTION, FS_ROOT, default_class=DEFAULT_CLASS)
store = MongoModuleStore(HOST, DB, COLLECTION, FS_ROOT, RENDER_TEMPLATE, default_class=DEFAULT_CLASS)
# Explicitly list the courses to load (don't want the big one)
courses = ['toy', 'simple']
import_from_xml(store, DATA_DIR, courses)
......
......@@ -187,11 +187,11 @@ class XMLModuleStore(ModuleStoreBase):
if not os.path.exists(policy_path):
return {}
try:
log.debug("Loading policy from {}".format(policy_path))
log.debug("Loading policy from {0}".format(policy_path))
with open(policy_path) as f:
return json.load(f)
except (IOError, ValueError) as err:
msg = "Error loading course policy from {}".format(policy_path)
msg = "Error loading course policy from {0}".format(policy_path)
tracker(msg)
log.warning(msg + " " + str(err))
return {}
......@@ -238,7 +238,7 @@ class XMLModuleStore(ModuleStoreBase):
url_name = course_data.get('url_name')
if url_name:
policy_path = self.data_dir / course_dir / 'policies' / '{}.json'.format(url_name)
policy_path = self.data_dir / course_dir / 'policies' / '{0}.json'.format(url_name)
policy = self.load_policy(policy_path, tracker)
else:
policy = {}
......
......@@ -201,7 +201,7 @@ class ImportTestCase(unittest.TestCase):
def check_for_key(key, node):
"recursive check for presence of key"
print "Checking {}".format(node.location.url())
print "Checking {0}".format(node.location.url())
self.assertTrue(key in node.metadata)
for c in node.get_children():
check_for_key(key, c)
......
......@@ -629,7 +629,7 @@ class XModuleDescriptor(Plugin, HTMLSnippet):
try:
return parse_time(self.metadata[key])
except ValueError as e:
msg = "Descriptor {} loaded with a bad metadata key '{}': '{}'".format(
msg = "Descriptor {0} loaded with a bad metadata key '{1}': '{2}'".format(
self.location.url(), self.metadata[key], e)
log.warning(msg)
return None
......
......@@ -47,12 +47,12 @@ def cleanup(filepath, remove_meta):
'ispublic', 'xqa_key')
try:
print "Cleaning {}".format(filepath)
print "Cleaning {0}".format(filepath)
with open(filepath) as f:
parser = etree.XMLParser(remove_comments=False)
xml = etree.parse(filepath, parser=parser)
except:
print "Error parsing file {}".format(filepath)
print "Error parsing file {0}".format(filepath)
return
for node in xml.iter(tag=etree.Element):
......@@ -67,12 +67,12 @@ def cleanup(filepath, remove_meta):
del attrs['name']
if 'url_name' in attrs and 'slug' in attrs:
print "WARNING: {} has both slug and url_name"
print "WARNING: {0} has both slug and url_name".format(node)
if ('url_name' in attrs and 'filename' in attrs and
len(attrs)==2 and attrs['url_name'] == attrs['filename']):
# This is a pointer tag in disguise. Get rid of the filename.
print 'turning {}.{} into a pointer tag'.format(node.tag, attrs['url_name'])
print 'turning {0}.{1} into a pointer tag'.format(node.tag, attrs['url_name'])
del attrs['filename']
if remove_meta:
......
This doc is a rough spec of our xml format
Every content element (within a course) should have a unique id. This id is formed as {category}/{url_name}. Categories are the different tag types ('chapter', 'problem', 'html', 'sequential', etc). Url_name is a string containing a-z, A-Z, dot (.) and _. This is what appears in urls that point to this object.
File layout:
- Xml files have content
- "policy", which is also called metadata in various places, should live in a policy file.
- each module (except customtag and course, which are special, see below) should live in a file, located at {category}/{url_name].xml
To include this module in another one (e.g. to put a problem in a vertical), put in a "pointer tag": <{category} url_name="{url_name}"/>. When we read that, we'll load the actual contents.
Customtag is already a pointer, you can just use it in place: <customtag url_name="my_custom_tag" impl="blah" attr1="..."/>
Course tags:
- the top level course pointer tag lives in course.xml
- have 2 extra required attributes: "org" and "course" -- organization name, and course name. Note that the course name is referring to the platonic ideal of this course, not to any particular run of this course. The url_name should be particular run of this course. E.g.
If course.xml contains:
<course org="HarvardX" course="cs50" url_name="2012"/>
we would load the actual course definition from course/2012.xml
To support multiple different runs of the course, you could have a different course.xml, containing
<course org="HarvardX" course="cs50" url_name="2012H"/>
which would load the Harvard-internal version from course/2012H.xml
If there is only one run of the course for now, just have a single course.xml with the right url_name.
If there is more than one run of the course, the different course root pointer files should live in
roots/url_name.xml, and course.xml should be a symbolic link to the one you want to run in your dev instance.
If you want to run both versions, you need to checkout the repo twice, and have course.xml point to different root/{url_name}.xml files.
Policies:
- the policy for a course url_name lives in policies/{url_name}.json
The format is called "json", and is best shown by example (though also feel free to google :)
the file is a dictionary (mapping from keys to values, syntax "{ key : value, key2 : value2, etc}"
Keys are in the form "{category}/{url_name}", which should uniquely id a content element.
Values are dictionaries of the form {"metadata-key" : "metadata-value"}.
metadata can also live in the xml files, but anything defined in the policy file overrides anything in the xml. This is primarily for backwards compatibility, and you should probably not use both. If you do leave some metadata tags in the xml, please be consistent (e.g. if display_names stay in xml, they should all stay in xml).
- note, some xml attributes are not metadata. e.g. in <video youtube="xyz987293487293847"/>, the youtube attribute specifies what video this is, and is logically part of the content, not the policy, so it should stay in video/{url_name}.xml.
Example policy file:
{
"course/2012": {
"graceperiod": "1 day",
"start": "2012-10-15T12:00",
"display_name": "Introduction to Computer Science I",
"xqa_key": "z1y4vdYcy0izkoPeihtPClDxmbY1ogDK"
},
"chapter/Week_0": {
"display_name": "Week 0"
},
"sequential/Pre-Course_Survey": {
"display_name": "Pre-Course Survey",
"format": "Survey"
}
}
NOTE: json is picky about commas. If you have trailing commas before closing braces, it will complain and refuse to parse the file. This is irritating.
Valid tag categories:
abtest
chapter
course
customtag
html
error -- don't put these in by hand :)
problem
problemset
sequential
vertical
video
videosequence
Obsolete tags:
Use customtag instead:
videodev
book
slides
image
discuss
Ex: instead of <book page="12"/>, use <customtag impl="book" page="12"/>
Use something semantic instead, as makes sense: sequential, vertical, videosequence if it's actually a sequence. If the section would only contain a single element, just include that element directly.
section
In general, prefer the most "semantic" name for containers: e.g. use problemset rather than vertical for a problem set. That way, if we decide to display problem sets differently, we don't have to change the xml.
How customtags work:
When we see <customtag impl="special" animal="unicorn" hat="blue"/>, we will:
- look for a file called custom_tags/special in your course dir.
- render it as a mako template, passing parameters {'animal':'unicorn', 'hat':'blue'}, generating html.
METADATA
Metadata that we generally understand:
Only on course tag in courses/url_name.xml
ispublic
xqa_key -- set only on course, inherited to everything else
Everything:
display_name
format (maybe only content containers, e.g. "Lecture sequence", "problem set", "lab", etc. )
start -- modules will not show up to non-course-staff users before the start date (in production)
hide_from_toc -- if this is true, don't show in table of contents for the course. Useful on chapters, and chapter subsections that are linked to from somewhere else.
Used for problems
graceperiod
showanswer
rerandomize
graded
due
These are _inherited_ : if specified on the course, will apply to everything in the course, except for things that explicitly specify them, and their children.
'graded', 'start', 'due', 'graceperiod', 'showanswer', 'rerandomize',
# TODO (ichuang): used for Fall 2012 xqa server access
'xqa_key',
Example sketch:
<course start="tue">
<chap1> -- start tue
<problem> --- start tue
</chap1>
<chap2 start="wed"> -- start wed
<problem2 start="thu"> -- start thu
<problem3> -- start wed
</chap2>
</course>
STATIC LINKS:
if your content links (e.g. in an html file) to "static/blah/ponies.jpg", we will look for this in YOUR_COURSE_DIR/blah/ponies.jpg. Note that this is not looking in a static/ subfolder in your course dir. This may (should?) change at some point.
......@@ -65,7 +65,7 @@ def has_access(user, obj, action):
# Passing an unknown object here is a coding error, so rather than
# returning a default, complain.
raise TypeError("Unknown object type in has_access(): '{}'"
raise TypeError("Unknown object type in has_access(): '{0}'"
.format(type(obj)))
......@@ -255,7 +255,7 @@ def _dispatch(table, action, user, obj):
action)
return result
raise ValueError("Unknown action for object type '{}': '{}'".format(
raise ValueError("Unknown action for object type '{0}': '{1}'".format(
type(obj), action))
def _course_staff_group_name(location):
......
......@@ -41,7 +41,7 @@ def import_course(course_dir, verbose=True):
course = courses[0]
errors = modulestore.get_item_errors(course.location)
if len(errors) != 0:
sys.stderr.write('ERRORs during import: {}\n'.format('\n'.join(map(str_of_err, errors))))
sys.stderr.write('ERRORs during import: {0}\n'.format('\n'.join(map(str_of_err, errors))))
return course
......
......@@ -75,6 +75,10 @@ def toc_for_course(user, request, course, active_chapter, active_section, course
chapters = list()
for chapter in course.get_display_items():
hide_from_toc = chapter.metadata.get('hide_from_toc','false').lower() == 'true'
if hide_from_toc:
continue
sections = list()
for section in chapter.get_display_items():
......@@ -323,7 +327,7 @@ def xqueue_callback(request, course_id, userid, id, dispatch):
user, modulestore().get_item(id), depth=0, select_for_update=True)
instance = get_module(user, request, id, student_module_cache)
if instance is None:
log.debug("No module {} for user {}--access denied?".format(id, user))
log.debug("No module {0} for user {1}--access denied?".format(id, user))
raise Http404
instance_module = get_instance_module(user, instance, student_module_cache)
......@@ -386,7 +390,7 @@ def modx_dispatch(request, dispatch=None, id=None, course_id=None):
if instance is None:
# Either permissions just changed, or someone is trying to be clever
# and load something they shouldn't have access to.
log.debug("No module {} for user {}--access denied?".format(id, user))
log.debug("No module {0} for user {1}--access denied?".format(id, user))
raise Http404
instance_module = get_instance_module(request.user, instance, student_module_cache)
......
......@@ -56,6 +56,7 @@ def mongo_store_config(data_dir):
'db': 'xmodule',
'collection': 'modulestore',
'fs_root': data_dir,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
}
}
......@@ -176,7 +177,7 @@ class PageLoader(ActivateLoginTestCase):
def try_enroll(self, course):
"""Try to enroll. Return bool success instead of asserting it."""
data = self._enroll(course)
print 'Enrollment in {} result: {}'.format(course.location.url(), data)
print 'Enrollment in {0} result: {1}'.format(course.location.url(), data)
return data['success']
def enroll(self, course):
......@@ -308,7 +309,7 @@ class TestViewAuth(PageLoader):
# shouldn't be able to get to the instructor pages
for url in instructor_urls(self.toy) + instructor_urls(self.full):
print 'checking for 404 on {}'.format(url)
print 'checking for 404 on {0}'.format(url)
self.check_for_get_code(404, url)
# Make the instructor staff in the toy course
......@@ -321,11 +322,11 @@ class TestViewAuth(PageLoader):
# Now should be able to get to the toy course, but not the full course
for url in instructor_urls(self.toy):
print 'checking for 200 on {}'.format(url)
print 'checking for 200 on {0}'.format(url)
self.check_for_get_code(200, url)
for url in instructor_urls(self.full):
print 'checking for 404 on {}'.format(url)
print 'checking for 404 on {0}'.format(url)
self.check_for_get_code(404, url)
......@@ -336,7 +337,7 @@ class TestViewAuth(PageLoader):
# and now should be able to load both
for url in instructor_urls(self.toy) + instructor_urls(self.full):
print 'checking for 200 on {}'.format(url)
print 'checking for 200 on {0}'.format(url)
self.check_for_get_code(200, url)
......@@ -387,7 +388,11 @@ class TestViewAuth(PageLoader):
list of urls that students should be able to see only
after launch, but staff should see before
"""
urls = reverse_urls(['info', 'book', 'courseware', 'profile'], course)
urls = reverse_urls(['info', 'courseware', 'profile'], course)
urls.extend([
reverse('book', kwargs={'course_id': course.id, 'book_index': book.title})
for book in course.textbooks
])
return urls
def light_student_urls(course):
......@@ -412,22 +417,22 @@ class TestViewAuth(PageLoader):
def check_non_staff(course):
"""Check that access is right for non-staff in course"""
print '=== Checking non-staff access for {}'.format(course.id)
print '=== Checking non-staff access for {0}'.format(course.id)
for url in instructor_urls(course) + dark_student_urls(course):
print 'checking for 404 on {}'.format(url)
print 'checking for 404 on {0}'.format(url)
self.check_for_get_code(404, url)
for url in light_student_urls(course):
print 'checking for 200 on {}'.format(url)
print 'checking for 200 on {0}'.format(url)
self.check_for_get_code(200, url)
def check_staff(course):
"""Check that access is right for staff in course"""
print '=== Checking staff access for {}'.format(course.id)
print '=== Checking staff access for {0}'.format(course.id)
for url in (instructor_urls(course) +
dark_student_urls(course) +
light_student_urls(course)):
print 'checking for 200 on {}'.format(url)
print 'checking for 200 on {0}'.format(url)
self.check_for_get_code(200, url)
# First, try with an enrolled student
......
......@@ -56,3 +56,7 @@ AWS_SECRET_ACCESS_KEY = AUTH_TOKENS["AWS_SECRET_ACCESS_KEY"]
DATABASES = AUTH_TOKENS['DATABASES']
XQUEUE_INTERFACE = AUTH_TOKENS['XQUEUE_INTERFACE']
if 'COURSE_ID' in ENV_TOKENS:
ASKBOT_URL = "courses/{0}/discussions/".format(ENV_TOKENS['COURSE_ID'])
......@@ -14,6 +14,7 @@ MODULESTORE = {
'db': 'xmodule',
'collection': 'modulestore',
'fs_root': GITHUB_REPO_ROOT,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
}
}
......@@ -8,6 +8,7 @@
</%block>
<%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>
## codemirror
......
......@@ -61,6 +61,11 @@ http {
location /courses/MITx/6.002x/2012_Fall/ {
proxy_pass http://course_mitx_6002_2012_fall;
}
location ~ /courses/([^/]*)/([^/]*)/([^/]*)/(course_wiki|wiki) {
proxy_pass http://portal;
}
}
}
......
......@@ -25,7 +25,6 @@ PACKAGE_REPO = "packages@gp.mitx.mit.edu:/opt/pkgrepo.incoming"
NORMALIZED_DEPLOY_NAME = DEPLOY_NAME.downcase().gsub(/[_\/]/, '-')
INSTALL_DIR_PATH = File.join(DEPLOY_DIR, NORMALIZED_DEPLOY_NAME)
PIP_REPO_REQUIREMENTS = "#{INSTALL_DIR_PATH}/repo-requirements.txt"
# Set up the clean and clobber tasks
CLOBBER.include(BUILD_DIR, REPORT_DIR, 'cover*', '.coverage', 'test_root/*_repo', 'test_root/staticfiles')
CLEAN.include("#{BUILD_DIR}/*.deb", "#{BUILD_DIR}/util")
......@@ -193,36 +192,7 @@ task :package do
afterremove.close()
FileUtils.chmod(0755, afterremove.path)
postinstall = Tempfile.new('postinstall')
postinstall.write <<-POSTINSTALL.gsub(/^\s*/, '')
#! /bin/sh
set -e
set -x
service gunicorn stop || echo "Unable to stop gunicorn. Continuing"
rm -f #{LINK_PATH}
ln -s #{INSTALL_DIR_PATH} #{LINK_PATH}
chown makeitso:makeitso #{LINK_PATH}
# install python modules that are in the package
if [ -r #{PIP_REPO_REQUIREMENTS} ]; then
cd #{INSTALL_DIR_PATH}
pip install -r #{PIP_REPO_REQUIREMENTS}
fi
chown -R makeitso:makeitso #{INSTALL_DIR_PATH}
# Delete mako temp files
rm -rf /tmp/tmp*mako
service gunicorn start || echo "Unable to start gunicorn. Continuing"
POSTINSTALL
postinstall.close()
FileUtils.chmod(0755, postinstall.path)
args = ["fakeroot", "fpm", "-s", "dir", "-t", "deb",
"--after-install=#{postinstall.path}",
"--after-remove=#{afterremove.path}",
"--prefix=#{INSTALL_DIR_PATH}",
"--exclude=**/build/**",
......
-e common/lib/capa
-e common/lib/mitxmako
-e common/lib/xmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment