Commit ea3506d2 by Nate Hardison

Add general theming capabilities

This commit adds the requisite settings and startup features to
enable integration of themes into the edX platform. It does not
yet provide hooks in any of the templates, but it does cause the
main `lms/static/sass/application.scss` file to `@import` a theme's
base Sass. Template hooks will come down the road.

CHANGELOG
---------
Define a new `MITX_FEATURE`, `USE_CUSTOM_THEME`, that when enabled,
can be used in templates to determine whether or not custom theme
templates should be used instead of the defaults.

Also define a new setting, `THEME_NAME`, which will be used to
locate theme-specific files. Establish the convention that themes
will be stored outside of the `REPO_ROOT`, inside the `ENV_ROOT`,
in a directory named `themes/`. `themes/<THEME_NAME>` will store
the files for a particular theme.

Provide a function, `enable_theme`, that modifies the template and
static asset load paths appropriately to include the theme's files.

Move the main LMS Sass file to a Mako template that conditionally
`@import`s the theme's base Sass file when a theme is enabled.

Add logic to the assets Rakefile to properly preprocess any Sass/
Mako templates before compiling them.
parent d724223a
......@@ -26,6 +26,7 @@ Gemfile.lock
conf/locale/en/LC_MESSAGES/*.po
!messages.po
lms/static/sass/*.css
lms/static/sass/application.scss
cms/static/sass/*.css
lms/lib/comment_client/python
nosetests.xml
......
......@@ -114,6 +114,11 @@ DEFAULT_FEEDBACK_EMAIL = ENV_TOKENS.get('DEFAULT_FEEDBACK_EMAIL', DEFAULT_FEEDBA
ADMINS = ENV_TOKENS.get('ADMINS', ADMINS)
SERVER_EMAIL = ENV_TOKENS.get('SERVER_EMAIL', SERVER_EMAIL)
#Theme overrides
THEME_NAME = ENV_TOKENS.get('THEME_NAME', None)
if not THEME_NAME is None:
enable_theme(THEME_NAME)
#Timezone overrides
TIME_ZONE = ENV_TOKENS.get('TIME_ZONE', TIME_ZONE)
......
......@@ -110,6 +110,9 @@ MITX_FEATURES = {
# Enable URL that shows information about the status of variuous services
'ENABLE_SERVICE_STATUS': False,
# Toggle to indicate use of a custom theme
'USE_CUSTOM_THEME': False
}
# Used for A/B testing
......@@ -167,12 +170,12 @@ MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates',
# This is where Django Template lookup is defined. There are a few of these
# still left lying around.
TEMPLATE_DIRS = (
TEMPLATE_DIRS = [
PROJECT_ROOT / "templates",
COMMON_ROOT / 'templates',
COMMON_ROOT / 'lib' / 'capa' / 'capa' / 'templates',
COMMON_ROOT / 'djangoapps' / 'pipeline_mako' / 'templates',
)
]
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.request',
......@@ -714,3 +717,31 @@ MKTG_URL_LINK_MAP = {
'HONOR': 'honor',
'PRIVACY': 'privacy_edx',
}
############################### THEME ################################
def enable_theme(theme_name):
"""
Enable the settings for a custom theme, whose files should be stored
in ENV_ROOT/themes/THEME_NAME (e.g., edx_all/themes/stanford).
The THEME_NAME setting should be configured separately since it can't
be set here (this function closes too early). An idiom for doing this
is:
THEME_NAME = "stanford"
enable_theme(THEME_NAME)
"""
MITX_FEATURES['USE_CUSTOM_THEME'] = True
# Calculate the location of the theme's files
theme_root = ENV_ROOT / "themes" / theme_name
# Include the theme's templates in the template search paths
TEMPLATE_DIRS.append(theme_root / 'templates')
MAKO_TEMPLATES['main'].append(theme_root / 'templates')
# Namespace the theme's static files to 'themes/<theme_name>' to
# avoid collisions with default edX static files
STATICFILES_DIRS.append((u'themes/%s' % theme_name,
theme_root / 'static'))
......@@ -36,3 +36,16 @@
@import 'news';
@import 'shame';
## THEMING
## -------
## Set up this file to import an edX theme library if the environment
## indicates that a theme should be used. The assumption is that the
## theme resides outside of this main edX repository, in a directory
## called themes/<theme-name>/, with its base Sass file in
## themes/<theme-name>/static/sass/_<theme-name>.scss. That one entry
## point can be used to @import in as many other things as needed.
% if not env['THEME_NAME'] is None:
// import theme's Sass overrides
@import '${env['THEME_NAME']}'
% endif
require 'json'
require 'rake/clean'
require './rakefiles/helpers.rb'
......@@ -7,6 +8,13 @@ end
# Build Constants
REPO_ROOT = File.dirname(__FILE__)
ENV_ROOT = File.dirname(REPO_ROOT)
REPORT_DIR = File.join(REPO_ROOT, "reports")
# Environment constants
SERVICE_VARIANT = ENV['SERVICE_VARIANT']
CONFIG_PREFIX = SERVICE_VARIANT ? SERVICE_VARIANT + "." : ""
ENV_FILE = File.join(ENV_ROOT, CONFIG_PREFIX + "env.json")
ENV_TOKENS = File.exists?(ENV_FILE) ? JSON.parse(File.read(ENV_FILE)) : {}
task :default => [:test, :pep8, :pylint]
# Theming constants
THEME_NAME = ENV_TOKENS['THEME_NAME']
USE_CUSTOM_THEME = !(THEME_NAME.nil? || THEME_NAME.empty?)
if USE_CUSTOM_THEME
THEME_ROOT = File.join(ENV_ROOT, "themes", THEME_NAME)
THEME_SASS = File.join(THEME_ROOT, "static", "sass")
end
# Run the specified file through the Mako templating engine, providing
# the ENV_TOKENS to the templating context.
def preprocess_with_mako(filename)
# simple command-line invocation of Mako engine
mako = "from mako.template import Template;" +
"print Template(filename=\"#{filename}\")" +
# Total hack. It works because a Python dict literal has
# the same format as a JSON object.
".render(env=#{ENV_TOKENS.to_json});"
# strip off the .mako extension
output_filename = filename.chomp(File.extname(filename))
# just pipe from stdout into the new file
File.open(output_filename, 'w') do |file|
file.write(`python -c '#{mako}'`)
end
end
# Preprocess all static assets that have the .mako extension by
# running them through the Mako templating engine. Right now we
# just hardcode the asset filenames.
def preprocess_assets
preprocess_with_mako("lms/static/sass/application.scss.mako")
end
def xmodule_cmd(watch=false, debug=false)
xmodule_cmd = 'xmodule_assets common/static/xmodule'
......@@ -32,10 +65,20 @@ def coffee_cmd(watch=false, debug=false)
end
def sass_cmd(watch=false, debug=false)
# Make sure to preprocess templatized Sass first
preprocess_assets()
sass_load_paths = ["./common/static/sass"]
sass_watch_paths = ["*/static"]
if USE_CUSTOM_THEME
sass_load_paths << THEME_SASS
sass_watch_paths << THEME_SASS
end
"sass #{debug ? '--debug-info' : '--style compressed'} " +
"--load-path ./common/static/sass " +
"--load-path #{sass_load_paths.join(' ')} " +
"--require ./common/static/sass/bourbon/lib/bourbon.rb " +
"#{watch ? '--watch' : '--update'} */static"
"#{watch ? '--watch' : '--update'} #{sass_watch_paths.join(' ')}"
end
desc "Compile all assets"
......
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