diff --git a/common/djangoapps/edxmako/paths.py b/common/djangoapps/edxmako/paths.py index 3e7bb40430e2..1d4c3cacc31d 100644 --- a/common/djangoapps/edxmako/paths.py +++ b/common/djangoapps/edxmako/paths.py @@ -11,6 +11,7 @@ from mako.lookup import TemplateLookup from microsite_configuration import microsite +from openedx.core.djangoapps.theming.core import get_template_path from . import LOOKUP @@ -51,13 +52,14 @@ def get_template(self, uri): """ Overridden method which will hand-off the template lookup to the microsite subsystem """ - microsite_template = microsite.get_template(uri) + if microsite.is_request_in_microsite(): + microsite_template = microsite.get_template(uri) + if microsite_template: + return microsite_template + else: + uri = get_template_path(uri) - return ( - microsite_template - if microsite_template - else super(DynamicTemplateLookup, self).get_template(uri) - ) + return super(DynamicTemplateLookup, self).get_template(uri) def clear_lookups(namespace): diff --git a/common/djangoapps/pipeline_mako/templates/static_content.html b/common/djangoapps/pipeline_mako/templates/static_content.html index 68c0263dca84..e1d16fd41d2b 100644 --- a/common/djangoapps/pipeline_mako/templates/static_content.html +++ b/common/djangoapps/pipeline_mako/templates/static_content.html @@ -4,13 +4,21 @@ from django.utils.translation import get_language_bidi from mako.exceptions import TemplateLookupException -from openedx.core.djangoapps.theming.helpers import get_page_title_breadcrumbs, get_value, get_template_path, get_themed_template_path, is_request_in_themed_site +from openedx.core.djangoapps.theming.helpers import ( + get_page_title_breadcrumbs, + get_value, + get_template_path, + get_themed_template_path, + is_request_in_themed_site, + get_request_domain, +) from certificates.api import get_asset_url_by_slug %> <%def name='url(file, raw=False)'><% try: - url = staticfiles_storage.url(file) + domain = get_request_domain(request) + url = staticfiles_storage.url(file, domain=domain) except: url = file %>${url}${"?raw" if raw else ""}%def> diff --git a/lms/envs/common.py b/lms/envs/common.py index 94e97a4e0ff8..34f6bed45220 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -395,7 +395,7 @@ DATA_DIR = COURSES_ROOT # comprehensive theming system -COMPREHENSIVE_THEME_DIR = "" +COMPREHENSIVE_THEME_DIR = "/".join([REPO_ROOT, "themes"]) # TODO: Remove the rest of the sys.path modification here and in cms/envs/common.py sys.path.append(REPO_ROOT) @@ -776,7 +776,7 @@ CMS_BASE = 'localhost:8001' # Site info -SITE_ID = 1 +# SITE_ID = 1 SITE_NAME = "example.com" HTTPS = 'on' ROOT_URLCONF = 'lms.urls' diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index a0ff8932ce95..3445bf21a526 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -99,6 +99,7 @@ def should_show_debug_toolbar(_): # Revert to the default set of finders as we don't want the production pipeline STATICFILES_FINDERS = [ + 'openedx.core.djangoapps.theming.finders.ComprehensiveThemeFinder', 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ] diff --git a/openedx/core/djangoapps/theming/core.py b/openedx/core/djangoapps/theming/core.py index ee3e85410365..61f5d681ef3d 100644 --- a/openedx/core/djangoapps/theming/core.py +++ b/openedx/core/djangoapps/theming/core.py @@ -1,17 +1,22 @@ """ Core logic for Comprehensive Theming. """ +import os.path from path import Path from django.conf import settings +from django.contrib.sites.shortcuts import get_current_site +from edxmako.middleware import REQUEST_CONTEXT +from util.url import strip_port_from_host -def comprehensive_theme_changes(theme_dir): + +def comprehensive_theme_changes(themes_dir): """ Calculate the set of changes needed to enable a comprehensive theme. Arguments: - theme_dir (path.path): the full path to the theming directory to use. + themes_dir (path.path): the full path to the directory where all themse are listed. Returns: A dict indicating the changes to make: @@ -27,27 +32,20 @@ def comprehensive_theme_changes(theme_dir): 'settings': {}, 'template_paths': [], } - root = Path(settings.PROJECT_ROOT) - if root.name == "": - root = root.parent - - component_dir = theme_dir / root.name - templates_dir = component_dir / "templates" - if templates_dir.isdir(): - changes['template_paths'].append(templates_dir) + root_name = get_project_root_name() - staticfiles_dir = component_dir / "static" - if staticfiles_dir.isdir(): - changes['settings']['STATICFILES_DIRS'] = [staticfiles_dir] + settings.STATICFILES_DIRS + if themes_dir.isdir(): + changes['template_paths'].append(themes_dir) - locale_dir = component_dir / "conf" / "locale" - if locale_dir.isdir(): - changes['settings']['LOCALE_PATHS'] = [locale_dir] + settings.LOCALE_PATHS + for theme_dir in os.listdir(themes_dir): + staticfiles_dir = os.path.join(themes_dir, theme_dir, root_name, "static") + if staticfiles_dir.isdir(): + changes['settings']['STATICFILES_DIRS'] = settings.STATICFILES_DIRS + [staticfiles_dir] - favicon = component_dir / "static" / "images" / "favicon.ico" - if favicon.isfile(): - changes['settings']['FAVICON_PATH'] = str(favicon) + locale_dir = os.path.join(themes_dir, theme_dir, root_name, "conf", "locale") + if locale_dir.isdir(): + changes['settings']['LOCALE_PATHS'] = [locale_dir] + settings.LOCALE_PATHS return changes @@ -64,3 +62,44 @@ def enable_comprehensive_theme(theme_dir): for template_dir in changes['template_paths']: settings.DEFAULT_TEMPLATE_ENGINE['DIRS'].insert(0, template_dir) settings.MAKO_TEMPLATES['main'].insert(0, template_dir) + + +def get_template_path(relative_path): + """ + Returns a path (string) to a Mako template, if one is found in theme directory + otherwise return what is passed. + """ + request = getattr(REQUEST_CONTEXT, 'request', None) + if not request: + return relative_path + + domain = get_current_site(request).domain + domain = strip_port_from_host(domain) + root_name = get_project_root_name() + template_path = "/".join([ + settings.COMPREHENSIVE_THEME_DIR, + domain, + root_name, + "templates" + ]) + + search_path = os.path.join(template_path, relative_path) + if os.path.isfile(search_path): + path = '/{domain}/{root_name}/templates/{relative_path}'.format( + domain=domain, + root_name=root_name, + relative_path=relative_path, + ) + return path + else: + return relative_path + + +def get_project_root_name(): + """ + :return: + """ + root = Path(settings.PROJECT_ROOT) + if root.name == "": + root = root.parent + return root.name diff --git a/openedx/core/djangoapps/theming/finders.py b/openedx/core/djangoapps/theming/finders.py index cbf4366f5a6f..55acdef02e43 100644 --- a/openedx/core/djangoapps/theming/finders.py +++ b/openedx/core/djangoapps/theming/finders.py @@ -17,12 +17,13 @@ .. _Django-Pipeline: http://django-pipeline.readthedocs.org/ .. _Django-Require: https://github.com/etianen/django-require """ -from path import Path from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.contrib.staticfiles import utils from django.contrib.staticfiles.finders import BaseFinder + from openedx.core.djangoapps.theming.storage import CachedComprehensiveThemingStorage +from openedx.core.djangoapps.theming.helpers import is_themed_dir class ComprehensiveThemeFinder(BaseFinder): @@ -34,7 +35,7 @@ class ComprehensiveThemeFinder(BaseFinder): """ def __init__(self, *args, **kwargs): super(ComprehensiveThemeFinder, self).__init__(*args, **kwargs) - + self.storage = None theme_dir = getattr(settings, "COMPREHENSIVE_THEME_DIR", "") if not theme_dir: self.storage = None @@ -43,13 +44,7 @@ def __init__(self, *args, **kwargs): if not isinstance(theme_dir, basestring): raise ImproperlyConfigured("Your COMPREHENSIVE_THEME_DIR setting must be a string") - root = Path(settings.PROJECT_ROOT) - if root.name == "": - root = root.parent - - component_dir = Path(theme_dir) / root.name - static_dir = component_dir / "static" - self.storage = CachedComprehensiveThemingStorage(location=static_dir) + self.storage = CachedComprehensiveThemingStorage(location=theme_dir) def find(self, path, all=False): # pylint: disable=redefined-builtin """ @@ -62,8 +57,13 @@ def find(self, path, all=False): # pylint: disable=redefined-builtin # strip the prefix path = path[len(self.storage.prefix):] - if self.storage.exists(path): - match = self.storage.path(path) + path_parts = path.split("/", 1) + if not is_themed_dir(path_parts[0]): + return [] + + themed_path = path_parts[0] + "/" + self.storage.root_name + self.storage.prefix + "/" + path_parts[1] + if self.storage.exists(themed_path): + match = self.storage.path(themed_path) if all: match = [match] return match diff --git a/openedx/core/djangoapps/theming/helpers.py b/openedx/core/djangoapps/theming/helpers.py index 28ce710ebe8b..1a5fe3dba6ca 100644 --- a/openedx/core/djangoapps/theming/helpers.py +++ b/openedx/core/djangoapps/theming/helpers.py @@ -1,10 +1,33 @@ """ Helpers for accessing comprehensive theming related variables. """ +import os + +from django.contrib.sites.shortcuts import get_current_site + from microsite_configuration import microsite from microsite_configuration import page_title_breadcrumbs from django.conf import settings +from util.url import strip_port_from_host + + +def get_request_domain(request): + domain = get_current_site(request).domain + domain = strip_port_from_host(domain) + return domain + + +def is_themed_dir(str): + themes_dir = getattr(settings, "COMPREHENSIVE_THEME_DIR", "") + if not themes_dir.isdir(): + return False + + for theme_dir in os.listdir(themes_dir): + if theme_dir == str: + return True + return False + def get_page_title_breadcrumbs(*args): """ diff --git a/openedx/core/djangoapps/theming/storage.py b/openedx/core/djangoapps/theming/storage.py index 3fb5311b5a6b..d462891154d8 100644 --- a/openedx/core/djangoapps/theming/storage.py +++ b/openedx/core/djangoapps/theming/storage.py @@ -29,20 +29,20 @@ def __init__(self, *args, **kwargs): root = Path(settings.PROJECT_ROOT) if root.name == "": root = root.parent + self.root_name = root.name - component_dir = Path(theme_dir) / root.name - self.theme_location = component_dir / "static" + if theme_dir: + self.theme_location = theme_dir @property def prefix(self): """ This is used by the ComprehensiveThemeFinder in the collection step. """ - theme_dir = getattr(settings, "COMPREHENSIVE_THEME_DIR", "") - if not theme_dir: - return None - theme_name = os.path.basename(os.path.normpath(theme_dir)) - return "themes/{name}/".format(name=theme_name) + theme_prefix = "" + if self.theme_location: + theme_prefix = "/static" + return theme_prefix def themed(self, name): """ @@ -67,13 +67,21 @@ def path(self, name): path = safe_join(base, name) return os.path.normpath(path) - def url(self, name, *args, **kwargs): + def url(self, name, domain=None): """ Add the theme prefix to the asset URL """ - if self.themed(name): - name = self.prefix + name - return super(ComprehensiveThemingAwareMixin, self).url(name, *args, **kwargs) + if name.startswith(self.prefix): + # strip the prefix + name_without_prefix = name[len(self.prefix):] + else: + name_without_prefix = name + + if domain: + themed_path = domain + "/" + self.root_name + self.prefix + name_without_prefix + if self.themed(themed_path): + name = self.prefix + "/" + domain + name_without_prefix + return super(ComprehensiveThemingAwareMixin, self).url(name) class CachedComprehensiveThemingStorage( diff --git a/openedx/core/storage.py b/openedx/core/storage.py index ff1769470758..6607b27c0c0d 100644 --- a/openedx/core/storage.py +++ b/openedx/core/storage.py @@ -4,9 +4,11 @@ from django.contrib.staticfiles.storage import StaticFilesStorage, CachedFilesMixin from pipeline.storage import PipelineMixin, NonPackagingMixin from require.storage import OptimizedFilesMixin +from openedx.core.djangoapps.theming.storage import ComprehensiveThemingAwareMixin class ProductionStorage( + ComprehensiveThemingAwareMixin, OptimizedFilesMixin, PipelineMixin, CachedFilesMixin, @@ -20,6 +22,7 @@ class ProductionStorage( class DevelopmentStorage( + ComprehensiveThemingAwareMixin, NonPackagingMixin, PipelineMixin, StaticFilesStorage diff --git a/themes/jane.org/lms/static/images/logo.png b/themes/jane.org/lms/static/images/logo.png new file mode 100644 index 000000000000..8d0383dbc938 Binary files /dev/null and b/themes/jane.org/lms/static/images/logo.png differ diff --git a/themes/jane.org/lms/templates/footer.html b/themes/jane.org/lms/templates/footer.html new file mode 100644 index 000000000000..ffc281efc874 --- /dev/null +++ b/themes/jane.org/lms/templates/footer.html @@ -0,0 +1,2 @@ +## mako +