From 3b36fbf91441fa57c0d35a55937478ec328f037a Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Thu, 16 Aug 2012 12:49:42 -0400 Subject: [PATCH 01/22] Move mitxmako out of common lib, and pass template rendering function into MongoModuleStore --- cms/envs/dev.py | 1 + cms/envs/test.py | 1 + common/{lib => djangoapps}/mitxmako/README | 0 .../mitxmako/__init__.py | 0 .../mitxmako/makoloader.py | 0 .../mitxmako/middleware.py | 0 .../mitxmako/shortcuts.py | 0 .../mitxmako/template.py | 0 .../mitxmako/templatetag_helpers.py | 0 common/lib/mitxmako/setup.py | 8 ------- common/lib/xmodule/setup.py | 1 - .../lib/xmodule/xmodule/modulestore/django.py | 21 +++++++++++++++---- .../lib/xmodule/xmodule/modulestore/mongo.py | 7 ++++--- .../xmodule/modulestore/tests/test_mongo.py | 3 ++- lms/djangoapps/courseware/tests/tests.py | 1 + lms/envs/dev_mongo.py | 1 + repo-requirements.txt | 1 - 17 files changed, 27 insertions(+), 18 deletions(-) rename common/{lib => djangoapps}/mitxmako/README (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/__init__.py (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/makoloader.py (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/middleware.py (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/shortcuts.py (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/template.py (100%) rename common/{lib/mitxmako => djangoapps}/mitxmako/templatetag_helpers.py (100%) delete mode 100644 common/lib/mitxmako/setup.py diff --git a/cms/envs/dev.py b/cms/envs/dev.py index c5e1cf5689..13436ac5a5 100644 --- a/cms/envs/dev.py +++ b/cms/envs/dev.py @@ -24,6 +24,7 @@ MODULESTORE = { 'db': 'xmodule', 'collection': 'modulestore', 'fs_root': GITHUB_REPO_ROOT, + 'render_template': 'mitxmako.shortcuts.render_to_string', } } } diff --git a/cms/envs/test.py b/cms/envs/test.py index 3823cd9dd9..7dcd32caab 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -47,6 +47,7 @@ MODULESTORE = { 'db': 'test_xmodule', 'collection': 'modulestore', 'fs_root': GITHUB_REPO_ROOT, + 'render_template': 'mitxmako.shortcuts.render_to_string', } } } diff --git a/common/lib/mitxmako/README b/common/djangoapps/mitxmako/README similarity index 100% rename from common/lib/mitxmako/README rename to common/djangoapps/mitxmako/README diff --git a/common/lib/mitxmako/mitxmako/__init__.py b/common/djangoapps/mitxmako/__init__.py similarity index 100% rename from common/lib/mitxmako/mitxmako/__init__.py rename to common/djangoapps/mitxmako/__init__.py diff --git a/common/lib/mitxmako/mitxmako/makoloader.py b/common/djangoapps/mitxmako/makoloader.py similarity index 100% rename from common/lib/mitxmako/mitxmako/makoloader.py rename to common/djangoapps/mitxmako/makoloader.py diff --git a/common/lib/mitxmako/mitxmako/middleware.py b/common/djangoapps/mitxmako/middleware.py similarity index 100% rename from common/lib/mitxmako/mitxmako/middleware.py rename to common/djangoapps/mitxmako/middleware.py diff --git a/common/lib/mitxmako/mitxmako/shortcuts.py b/common/djangoapps/mitxmako/shortcuts.py similarity index 100% rename from common/lib/mitxmako/mitxmako/shortcuts.py rename to common/djangoapps/mitxmako/shortcuts.py diff --git a/common/lib/mitxmako/mitxmako/template.py b/common/djangoapps/mitxmako/template.py similarity index 100% rename from common/lib/mitxmako/mitxmako/template.py rename to common/djangoapps/mitxmako/template.py diff --git a/common/lib/mitxmako/mitxmako/templatetag_helpers.py b/common/djangoapps/mitxmako/templatetag_helpers.py similarity index 100% rename from common/lib/mitxmako/mitxmako/templatetag_helpers.py rename to common/djangoapps/mitxmako/templatetag_helpers.py diff --git a/common/lib/mitxmako/setup.py b/common/lib/mitxmako/setup.py deleted file mode 100644 index 535d86f90e..0000000000 --- a/common/lib/mitxmako/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -from setuptools import setup, find_packages - -setup( - name="mitxmako", - version="0.1", - packages=find_packages(exclude=["tests"]), - install_requires=['distribute'], -) diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 8a0a6bb139..cc5dfd183a 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -10,7 +10,6 @@ setup( }, requires=[ 'capa', - 'mitxmako' ], # See http://guide.python-distribute.org/creation.html#entry-points diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index 546aaf30c8..d61d3e6c24 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -12,15 +12,28 @@ from django.conf import settings _MODULESTORES = {} +FUNCTION_KEYS = ['render_template'] + + +def load_function(path): + 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] diff --git a/common/lib/xmodule/xmodule/modulestore/mongo.py b/common/lib/xmodule/xmodule/modulestore/mongo.py index b6101a6929..caada39f3e 100644 --- a/common/lib/xmodule/xmodule/modulestore/mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/mongo.py @@ -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']) diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py index cb94444b7a..746240e763 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mongo.py @@ -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) diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index f3b978adac..9682040b36 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -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', } } } diff --git a/lms/envs/dev_mongo.py b/lms/envs/dev_mongo.py index 1c4980a538..6af0a429bb 100644 --- a/lms/envs/dev_mongo.py +++ b/lms/envs/dev_mongo.py @@ -14,6 +14,7 @@ MODULESTORE = { 'db': 'xmodule', 'collection': 'modulestore', 'fs_root': GITHUB_REPO_ROOT, + 'render_template': 'mitxmako.shortcuts.render_to_string', } } } diff --git a/repo-requirements.txt b/repo-requirements.txt index 74bf02b5bd..dced5b960b 100644 --- a/repo-requirements.txt +++ b/repo-requirements.txt @@ -1,3 +1,2 @@ -e common/lib/capa --e common/lib/mitxmako -e common/lib/xmodule From 4798a46948a2d7b7c15191a392a15981b7840f4d Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Thu, 16 Aug 2012 13:08:10 -0400 Subject: [PATCH 02/22] Add docstring for load_function --- common/lib/xmodule/xmodule/modulestore/django.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py index d61d3e6c24..6a7315a074 100644 --- a/common/lib/xmodule/xmodule/modulestore/django.py +++ b/common/lib/xmodule/xmodule/modulestore/django.py @@ -16,6 +16,12 @@ 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) From c2ee84470488212e2f7efc4a669972d629d1fd67 Mon Sep 17 00:00:00 2001 From: Kyle Fiedler Date: Thu, 16 Aug 2012 13:47:15 -0400 Subject: [PATCH 03/22] Made video go to the center of the screen in full screen --- .../xmodule/xmodule/css/video/display.scss | 33 ++++++------------- .../js/src/video/display/video_player.coffee | 4 +-- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index 9e32de941a..aca575ac98 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -14,7 +14,7 @@ div.video { section.video-player { height: 0; - // overflow: hidden; + overflow: hidden; padding-bottom: 56.25%; position: relative; @@ -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 { diff --git a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee index 0ef091d6b3..4b265d20c8 100644 --- a/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee +++ b/common/lib/xmodule/xmodule/js/src/video/display/video_player.coffee @@ -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('Exit').addClass('fullscreen') + @el.addClass('fullscreen') @$('.add-fullscreen').attr('title', 'Exit fill browser') - @$('.exit').click @toggleFullScreen @caption.resize() # Delegates From 147bd5eb3d7ff88abb1bc57964a25e3f3104b4e5 Mon Sep 17 00:00:00 2001 From: Victor Shnayder Date: Thu, 16 Aug 2012 14:04:41 -0400 Subject: [PATCH 04/22] add initial docs on xml format and policy files --- doc/xml-format.md | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 doc/xml-format.md diff --git a/doc/xml-format.md b/doc/xml-format.md new file mode 100644 index 0000000000..2a9e379ccc --- /dev/null +++ b/doc/xml-format.md @@ -0,0 +1,147 @@ +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: + +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: + + +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 + + + +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