Skip to content
Snippets Groups Projects
Commit fa0146c5 authored by Saleem Latif's avatar Saleem Latif Committed by GitHub
Browse files

Merge pull request #12620 from edx/saleem-latif/WL-416

WL-416: Multi-site comprehensive theming
parents d328328f 68312bdd
No related merge requests found
Showing
with 376 additions and 37 deletions
......@@ -211,7 +211,14 @@ ASSET_IGNORE_REGEX = ENV_TOKENS.get('ASSET_IGNORE_REGEX', ASSET_IGNORE_REGEX)
# Theme overrides
THEME_NAME = ENV_TOKENS.get('THEME_NAME', None)
COMPREHENSIVE_THEME_DIR = path(ENV_TOKENS.get('COMPREHENSIVE_THEME_DIR', COMPREHENSIVE_THEME_DIR))
# following setting is for backward compatibility
if ENV_TOKENS.get('COMPREHENSIVE_THEME_DIR', None):
COMPREHENSIVE_THEME_DIR = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIR')
COMPREHENSIVE_THEME_DIRS = ENV_TOKENS.get('COMPREHENSIVE_THEME_DIRS', COMPREHENSIVE_THEME_DIRS) or []
DEFAULT_SITE_THEME = ENV_TOKENS.get('DEFAULT_SITE_THEME', DEFAULT_SITE_THEME)
ENABLE_COMPREHENSIVE_THEMING = ENV_TOKENS.get('ENABLE_COMPREHENSIVE_THEMING', ENABLE_COMPREHENSIVE_THEMING)
#Timezone overrides
TIME_ZONE = ENV_TOKENS.get('TIME_ZONE', TIME_ZONE)
......
......@@ -59,9 +59,9 @@ STATIC_URL = "/static/"
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
)
STATICFILES_DIRS = (
STATICFILES_DIRS = [
(TEST_ROOT / "staticfiles" / "cms").abspath(),
)
]
# Silence noisy logs
import logging
......
......@@ -47,7 +47,7 @@ import lms.envs.common
from lms.envs.common import (
USE_TZ, TECH_SUPPORT_EMAIL, PLATFORM_NAME, BUGS_EMAIL, DOC_STORE_CONFIG, DATA_DIR, ALL_LANGUAGES, WIKI_ENABLED,
update_module_store_settings, ASSET_IGNORE_REGEX, COPYRIGHT_YEAR,
PARENTAL_CONSENT_AGE_LIMIT, COMPREHENSIVE_THEME_DIR, REGISTRATION_EMAIL_PATTERNS_ALLOWED,
PARENTAL_CONSENT_AGE_LIMIT, COMPREHENSIVE_THEME_DIRS, REGISTRATION_EMAIL_PATTERNS_ALLOWED,
# The following PROFILE_IMAGE_* settings are included as they are
# indirectly accessed through the email opt-in API, which is
# technically accessible through the CMS via legacy URLs.
......@@ -61,7 +61,20 @@ from lms.envs.common import (
# Django REST framework configuration
REST_FRAMEWORK,
STATICI18N_OUTPUT_DIR
STATICI18N_OUTPUT_DIR,
# Theme to use when no site or site theme is defined,
DEFAULT_SITE_THEME,
# Default site to use if no site exists matching request headers
SITE_ID,
# Enable or disable theming
ENABLE_COMPREHENSIVE_THEMING,
# constants for redirects app
REDIRECT_CACHE_TIMEOUT,
REDIRECT_CACHE_KEY_PREFIX,
)
from path import Path as path
from warnings import simplefilter
......@@ -318,6 +331,7 @@ MIDDLEWARE_CLASSES = (
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware',
# Instead of SessionMiddleware, we use a more secure version
# 'django.contrib.sessions.middleware.SessionMiddleware',
......@@ -356,6 +370,8 @@ MIDDLEWARE_CLASSES = (
# for expiring inactive sessions
'session_inactivity_timeout.middleware.SessionInactivityTimeout',
'openedx.core.djangoapps.theming.middleware.CurrentSiteThemeMiddleware',
# use Django built in clickjacking protection
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
......@@ -451,7 +467,6 @@ SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
# Site info
SITE_ID = 1
SITE_NAME = "localhost:8001"
HTTPS = 'on'
ROOT_URLCONF = 'cms.urls'
......@@ -522,7 +537,7 @@ STATICFILES_STORAGE = 'openedx.core.storage.ProductionStorage'
# List of finder classes that know how to find static files in various locations.
# Note: the pipeline finder is included to be able to discover optimized files
STATICFILES_FINDERS = [
'openedx.core.djangoapps.theming.finders.ComprehensiveThemeFinder',
'openedx.core.djangoapps.theming.finders.ThemeFilesFinder',
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openedx.core.lib.xblock_pipeline.finder.XBlockPipelineFinder',
......
......@@ -41,7 +41,7 @@ STATICFILES_STORAGE = 'openedx.core.storage.DevelopmentStorage'
# Revert to the default set of finders as we don't want the production pipeline
STATICFILES_FINDERS = [
'openedx.core.djangoapps.theming.finders.ComprehensiveThemeFinder',
'openedx.core.djangoapps.theming.finders.ThemeFilesFinder',
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]
......
......@@ -41,6 +41,6 @@ STATIC_URL = "/static/"
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
)
STATICFILES_DIRS = (
STATICFILES_DIRS = [
(TEST_ROOT / "staticfiles" / "cms").abspath(),
)
]
......@@ -34,6 +34,7 @@ from lms.envs.test import (
DEFAULT_FILE_STORAGE,
MEDIA_ROOT,
MEDIA_URL,
COMPREHENSIVE_THEME_DIRS,
)
# mongo connection settings
......@@ -285,6 +286,8 @@ MICROSITE_CONFIGURATION = {
MICROSITE_TEST_HOSTNAME = 'testmicrosite.testserver'
MICROSITE_LOGISTRATION_HOSTNAME = 'logistration.testserver'
TEST_THEME = COMMON_ROOT / "test" / "test-theme"
# For consistency in user-experience, keep the value of this setting in sync with
# the one in lms/envs/test.py
FEATURES['ENABLE_DISCUSSION_SERVICE'] = False
......
......@@ -18,7 +18,8 @@ from openedx.core.lib.xblock_utils import xblock_local_resource_url
import xmodule.x_module
import cms.lib.xblock.runtime
from openedx.core.djangoapps.theming.core import enable_comprehensive_theme
from openedx.core.djangoapps.theming.core import enable_theming
from openedx.core.djangoapps.theming.helpers import is_comprehensive_theming_enabled
def run():
......@@ -30,8 +31,8 @@ def run():
# Comprehensive theming needs to be set up before django startup,
# because modifying django template paths after startup has no effect.
if settings.COMPREHENSIVE_THEME_DIR:
enable_comprehensive_theme(settings.COMPREHENSIVE_THEME_DIR)
if is_comprehensive_theming_enabled():
enable_theming()
django.setup()
......
......@@ -25,6 +25,7 @@ from embargo.test_utils import restrict_course
from student.models import CourseEnrollment
from student.tests.factories import CourseEnrollmentFactory, UserFactory
from util.testing import UrlResetMixin
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
@attr('shard_3')
......@@ -374,7 +375,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
self.assertEquals(course_modes, expected_modes)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@theming_test_utils.with_is_edx_domain(True)
@with_comprehensive_theme("edx.org")
def test_hide_nav(self):
# Create the course modes
for mode in ["honor", "verified"]:
......
......@@ -42,10 +42,14 @@ class MakoLoader(object):
def load_template(self, template_name, template_dirs=None):
source, file_path = self.load_template_source(template_name, template_dirs)
# In order to allow dynamic template overrides, we need to cache templates based on their absolute paths
# rather than relative paths, overriding templates would have same relative paths.
module_directory = self.module_directory.rstrip("/") + "/{dir_hash}/".format(dir_hash=hash(file_path))
if source.startswith("## mako\n"):
# This is a mako template
template = Template(filename=file_path,
module_directory=self.module_directory,
module_directory=module_directory,
input_encoding='utf-8',
output_encoding='utf-8',
default_filters=['decode.utf8'],
......
......@@ -9,9 +9,14 @@ import pkg_resources
from django.conf import settings
from mako.lookup import TemplateLookup
from mako.exceptions import TopLevelLookupException
from microsite_configuration import microsite
from . import LOOKUP
from openedx.core.djangoapps.theming.helpers import (
get_template as themed_template,
get_template_path_with_theme,
strip_site_theme_templates_path,
)
class DynamicTemplateLookup(TemplateLookup):
......@@ -49,15 +54,29 @@ class DynamicTemplateLookup(TemplateLookup):
def get_template(self, uri):
"""
Overridden method which will hand-off the template lookup to the microsite subsystem
"""
microsite_template = microsite.get_template(uri)
Overridden method for locating a template in either the database or the site theme.
return (
microsite_template
if microsite_template
else super(DynamicTemplateLookup, self).get_template(uri)
)
If not found, template lookup will be done in comprehensive theme for current site
by prefixing path to theme.
e.g if uri is `main.html` then new uri would be something like this `/red-theme/lms/static/main.html`
If still unable to find a template, it will fallback to the default template directories after stripping off
the prefix path to theme.
"""
# try to get template for the given file from microsite
template = themed_template(uri)
# if microsite template is not present or request is not in microsite then
# let mako find and serve a template
if not template:
try:
# Try to find themed template, i.e. see if current theme overrides the template
template = super(DynamicTemplateLookup, self).get_template(get_template_path_with_theme(uri))
except TopLevelLookupException:
# strip off the prefix path to theme and look in default template dirs
template = super(DynamicTemplateLookup, self).get_template(strip_site_theme_templates_path(uri))
return template
def clear_lookups(namespace):
......
......@@ -12,16 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from django.template import Context
from django.http import HttpResponse
import logging
from django.http import HttpResponse
from django.template import Context
from microsite_configuration import microsite
from edxmako import lookup_template
from edxmako.request_context import get_template_request_context
from django.conf import settings
from django.core.urlresolvers import reverse
from openedx.core.djangoapps.theming.helpers import get_template_path
log = logging.getLogger(__name__)
......@@ -134,8 +136,7 @@ def render_to_string(template_name, dictionary, context=None, namespace='main',
this template. If not supplied, the current request will be used.
"""
# see if there is an override template defined in the microsite
template_name = microsite.get_template_path(template_name)
template_name = get_template_path(template_name)
context_instance = Context(dictionary)
# add dictionary to context_instance
......
......@@ -11,7 +11,6 @@ BaseMicrositeTemplateBackend is Base Class for the microsite template backend.
from __future__ import absolute_import
import abc
import edxmako
import os.path
import threading
......@@ -272,9 +271,7 @@ class BaseMicrositeBackend(AbstractBaseMicrositeBackend):
Configure the paths for the microsites feature
"""
microsites_root = settings.MICROSITE_ROOT_DIR
if os.path.isdir(microsites_root):
edxmako.paths.add_lookup('main', microsites_root)
settings.STATICFILES_DIRS.insert(0, microsites_root)
log.info('Loading microsite path at %s', microsites_root)
......@@ -292,6 +289,7 @@ class BaseMicrositeBackend(AbstractBaseMicrositeBackend):
microsites_root = settings.MICROSITE_ROOT_DIR
if self.has_configuration_set():
settings.MAKO_TEMPLATES['main'].insert(0, microsites_root)
settings.DEFAULT_TEMPLATE_ENGINE['DIRS'].append(microsites_root)
......
......@@ -105,6 +105,23 @@ class DatabaseMicrositeBackendTests(DatabaseMicrositeTestCase):
microsite.clear()
self.assertIsNone(microsite.get_value('platform_name'))
def test_enable_microsites_pre_startup(self):
"""
Tests microsite.test_enable_microsites_pre_startup works as expected.
"""
# remove microsite root directory paths first
settings.DEFAULT_TEMPLATE_ENGINE['DIRS'] = [
path for path in settings.DEFAULT_TEMPLATE_ENGINE['DIRS']
if path != settings.MICROSITE_ROOT_DIR
]
with patch.dict('django.conf.settings.FEATURES', {'USE_MICROSITES': False}):
microsite.enable_microsites_pre_startup(log)
self.assertNotIn(settings.MICROSITE_ROOT_DIR, settings.DEFAULT_TEMPLATE_ENGINE['DIRS'])
with patch.dict('django.conf.settings.FEATURES', {'USE_MICROSITES': True}):
microsite.enable_microsites_pre_startup(log)
self.assertIn(settings.MICROSITE_ROOT_DIR, settings.DEFAULT_TEMPLATE_ENGINE['DIRS'])
self.assertIn(settings.MICROSITE_ROOT_DIR, settings.MAKO_TEMPLATES['main'])
@patch('edxmako.paths.add_lookup')
def test_enable_microsites(self, add_lookup):
"""
......@@ -122,7 +139,6 @@ class DatabaseMicrositeBackendTests(DatabaseMicrositeTestCase):
with patch.dict('django.conf.settings.FEATURES', {'USE_MICROSITES': True}):
microsite.enable_microsites(log)
self.assertIn(settings.MICROSITE_ROOT_DIR, settings.STATICFILES_DIRS)
add_lookup.assert_called_once_with('main', settings.MICROSITE_ROOT_DIR)
def test_get_all_configs(self):
"""
......
......@@ -49,7 +49,7 @@ class PipelineRenderTest(TestCase):
Create static assets once for all pipeline render tests.
"""
super(PipelineRenderTest, cls).setUpClass()
call_task('pavelib.assets.update_assets', args=('lms', '--settings=test'))
call_task('pavelib.assets.update_assets', args=('lms', '--settings=test', '--themes=no'))
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in LMS')
@ddt.data(
......
......@@ -20,8 +20,8 @@ from django.conf import settings
from edxmako.shortcuts import render_to_string
from util.request import safe_get_host
from util.testing import EventTestMixin
from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
from openedx.core.djangoapps.theming import helpers as theming_helpers
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
class TestException(Exception):
......@@ -99,7 +99,7 @@ class ActivationEmailTests(TestCase):
self._create_account()
self._assert_activation_email(self.ACTIVATION_SUBJECT, self.OPENEDX_FRAGMENTS)
@with_is_edx_domain(True)
@with_comprehensive_theme("edx.org")
def test_activation_email_edx_domain(self):
self._create_account()
self._assert_activation_email(self.ACTIVATION_SUBJECT, self.EDX_DOMAIN_FRAGMENTS)
......
......@@ -46,7 +46,6 @@ from certificates.tests.factories import GeneratedCertificateFactory # pylint:
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
import shoppingcart # pylint: disable=import-error
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
# Explicitly import the cache from ConfigurationModel so we can reset it after each test
from config_models.models import cache
......@@ -484,7 +483,6 @@ class DashboardTest(ModuleStoreTestCase):
self.assertEquals(response_2.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@with_is_edx_domain(True)
def test_dashboard_header_nav_has_find_courses(self):
self.client.login(username="jack", password="test")
response = self.client.get(reverse("dashboard"))
......
[
{
"pk": 2,
"model": "sites.Site",
"fields": {
"domain": "localhost:8003",
"name": "lms"
}
},
{
"pk": 3,
"model": "sites.Site",
"fields": {
"domain": "localhost:8031",
"name": "cms"
}
}
]
*.css
// studio - utilities - variables
// ====================
// Table of Contents
// * +Paths
// * +Grid
// * +Fonts
// * +Colors - Utility
// * +Colors - Primary
// * +Colors - Shadow
// * +Color - Application
// * +Timing
// * +Archetype UI
// * +Specific UI
// * +Deprecated
$baseline: 20px;
// +Paths
// ====================
$static-path: '..' !default;
// +Grid
// ====================
$gw-column: ($baseline*3);
$gw-gutter: $baseline;
$fg-column: $gw-column;
$fg-gutter: $gw-gutter;
$fg-max-columns: 12;
$fg-max-width: 1280px;
$fg-min-width: 900px;
// +Fonts
// ====================
$f-sans-serif: 'Open Sans','Helvetica Neue', Helvetica, Arial, sans-serif;
$f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
// +Colors - Utility
// ====================
$transparent: rgba(0,0,0,0); // used when color value is needed for UI width/transitions but element is transparent
// +Colors - Primary
// ====================
$black: rgb(0,0,0);
$black-t0: rgba($black, 0.125);
$black-t1: rgba($black, 0.25);
$black-t2: rgba($black, 0.5);
$black-t3: rgba($black, 0.75);
$white: rgb(255,255,255);
$white-t0: rgba($white, 0.125);
$white-t1: rgba($white, 0.25);
$white-t2: rgba($white, 0.5);
$white-t3: rgba($white, 0.75);
$gray: rgb(127,127,127);
$gray-l1: tint($gray,20%);
$gray-l2: tint($gray,40%);
$gray-l3: tint($gray,60%);
$gray-l4: tint($gray,80%);
$gray-l5: tint($gray,90%);
$gray-l6: tint($gray,95%);
$gray-l7: tint($gray,99%);
$gray-d1: shade($gray,20%);
$gray-d2: shade($gray,40%);
$gray-d3: shade($gray,60%);
$gray-d4: shade($gray,80%);
$blue: rgb(0, 159, 230);
$blue-l1: tint($blue,20%);
$blue-l2: tint($blue,40%);
$blue-l3: tint($blue,60%);
$blue-l4: tint($blue,80%);
$blue-l5: tint($blue,90%);
$blue-d1: shade($blue,20%);
$blue-d2: shade($blue,40%);
$blue-d3: shade($blue,60%);
$blue-d4: shade($blue,80%);
$blue-s1: saturate($blue,15%);
$blue-s2: saturate($blue,30%);
$blue-s3: saturate($blue,45%);
$blue-u1: desaturate($blue,15%);
$blue-u2: desaturate($blue,30%);
$blue-u3: desaturate($blue,45%);
$blue-t0: rgba($blue, 0.125);
$blue-t1: rgba($blue, 0.25);
$blue-t2: rgba($blue, 0.50);
$blue-t3: rgba($blue, 0.75);
$pink: rgb(183, 37, 103); // #b72567;
$pink-l1: tint($pink,20%);
$pink-l2: tint($pink,40%);
$pink-l3: tint($pink,60%);
$pink-l4: tint($pink,80%);
$pink-l5: tint($pink,90%);
$pink-d1: shade($pink,20%);
$pink-d2: shade($pink,40%);
$pink-d3: shade($pink,60%);
$pink-d4: shade($pink,80%);
$pink-s1: saturate($pink,15%);
$pink-s2: saturate($pink,30%);
$pink-s3: saturate($pink,45%);
$pink-u1: desaturate($pink,15%);
$pink-u2: desaturate($pink,30%);
$pink-u3: desaturate($pink,45%);
$red: rgb(178, 6, 16); // #b20610;
$red-l1: tint($red,20%);
$red-l2: tint($red,40%);
$red-l3: tint($red,60%);
$red-l4: tint($red,80%);
$red-l5: tint($red,90%);
$red-d1: shade($red,20%);
$red-d2: shade($red,40%);
$red-d3: shade($red,60%);
$red-d4: shade($red,80%);
$red-s1: saturate($red,15%);
$red-s2: saturate($red,30%);
$red-s3: saturate($red,45%);
$red-u1: desaturate($red,15%);
$red-u2: desaturate($red,30%);
$red-u3: desaturate($red,45%);
$green: rgb(37, 184, 90); // #25b85a
$green-l1: tint($green,20%);
$green-l2: tint($green,40%);
$green-l3: tint($green,60%);
$green-l4: tint($green,80%);
$green-l5: tint($green,90%);
$green-d1: shade($green,20%);
$green-d2: shade($green,40%);
$green-d3: shade($green,60%);
$green-d4: shade($green,80%);
$green-s1: saturate($green,15%);
$green-s2: saturate($green,30%);
$green-s3: saturate($green,45%);
$green-u1: desaturate($green,15%);
$green-u2: desaturate($green,30%);
$green-u3: desaturate($green,45%);
$yellow: rgb(237, 189, 60);
$yellow-l1: tint($yellow,20%);
$yellow-l2: tint($yellow,40%);
$yellow-l3: tint($yellow,60%);
$yellow-l4: tint($yellow,80%);
$yellow-l5: tint($yellow,90%);
$yellow-d1: shade($yellow,20%);
$yellow-d2: shade($yellow,40%);
$yellow-d3: shade($yellow,60%);
$yellow-d4: shade($yellow,80%);
$yellow-s1: saturate($yellow,15%);
$yellow-s2: saturate($yellow,30%);
$yellow-s3: saturate($yellow,45%);
$yellow-u1: desaturate($yellow,15%);
$yellow-u2: desaturate($yellow,30%);
$yellow-u3: desaturate($yellow,45%);
$orange: rgb(237, 189, 60);
$orange-l1: tint($orange,20%);
$orange-l2: tint($orange,40%);
$orange-l3: tint($orange,60%);
$orange-l4: tint($orange,80%);
$orange-l5: tint($orange,90%);
$orange-d1: shade($orange,20%);
$orange-d2: shade($orange,40%);
$orange-d3: shade($orange,60%);
$orange-d4: shade($orange,80%);
$orange-s1: saturate($orange,15%);
$orange-s2: saturate($orange,30%);
$orange-s3: saturate($orange,45%);
$orange-u1: desaturate($orange,15%);
$orange-u2: desaturate($orange,30%);
$orange-u3: desaturate($orange,45%);
// +Colors - Shadows
// ====================
$shadow: rgba($black, 0.2);
$shadow-l1: rgba($black, 0.1);
$shadow-l2: rgba($black, 0.05);
$shadow-d1: rgba($black, 0.4);
$shadow-d2: rgba($black, 0.6);
// +Colors - Application
// ====================
$color-draft: $gray-l3;
$color-live: $blue;
$color-ready: $green;
$color-warning: $orange-l2;
$color-error: $red-l2;
$color-staff-only: $black;
$color-gated: $black;
$color-visibility-set: $black;
$color-heading-base: $gray-d2;
$color-copy-base: $gray-l1;
$color-copy-emphasized: $gray-d2;
// +Timing
// ====================
// used for animation/transition mixin syncing
$tmg-s3: 3.0s;
$tmg-s2: 2.0s;
$tmg-s1: 1.0s;
$tmg-avg: 0.75s;
$tmg-f1: 0.50s;
$tmg-f2: 0.25s;
$tmg-f3: 0.125s;
// +Archetype UI
// ====================
$ui-action-primary-color: $blue-u2;
$ui-action-primary-color-focus: $blue-s1;
$ui-link-color: $blue-u2;
$ui-link-color-focus: $blue-s1;
// +Specific UI
// ====================
$ui-notification-height: ($baseline*10);
$ui-update-color: $blue-l4;
// +Deprecated
// ====================
// do not use, future clean up will use updated styles
$baseFontColor: $gray-d2;
$lighter-base-font-color: rgb(100,100,100);
$offBlack: #3c3c3c;
$green: #108614;
$lightGrey: #edf1f5;
$mediumGrey: #b0b6c2;
$darkGrey: #8891a1;
$extraDarkGrey: #3d4043;
$paleYellow: #fffcf1;
$yellow: rgb(255, 254, 223);
$green: rgb(37, 184, 90);
$brightGreen: rgb(22, 202, 87);
$disabledGreen: rgb(124, 206, 153);
$darkGreen: rgb(52, 133, 76);
// These colors are updated for testing purposes
$lightBluishGrey: rgb(0, 250, 0);
$lightBluishGrey2: rgb(0, 250, 0);
$error-red: rgb(253, 87, 87);
//carryover from LMS for xmodules
$sidebar-color: rgb(246, 246, 246);
// type
$sans-serif: $f-sans-serif;
$body-line-height: golden-ratio(.875em, 1);
// carried over from LMS for xmodules
$action-primary-active-bg: #1AA1DE; // $m-blue
$very-light-text: $white;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment