Commit 1240c5ae by Will Daly

Merge branch 'master' into feature/will/ci-lettuce-tests

parents 40529971 abc67b5e
[submodule "common/test/phantom-jasmine"]
path = common/test/phantom-jasmine
url = https://github.com/jcarver989/phantom-jasmine.git
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#pylint: disable=W0621 #pylint: disable=W0621
from lettuce import world, step from lettuce import world, step
from nose.tools import assert_true, assert_equal from nose.tools import assert_true, assert_equal, assert_in
from terrain.steps import reload_the_page from terrain.steps import reload_the_page
from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import StaleElementReferenceException
...@@ -63,7 +63,7 @@ def i_select_a_link_to_the_course_outline(step): ...@@ -63,7 +63,7 @@ def i_select_a_link_to_the_course_outline(step):
@step('I am brought to the course outline page$') @step('I am brought to the course outline page$')
def i_am_brought_to_course_outline(step): def i_am_brought_to_course_outline(step):
assert_equal('Course Outline', world.css_find('.outline .title-1')[0].text) assert_in('Course Outline', world.css_find('.outline .page-header')[0].text)
assert_equal(1, len(world.browser.windows)) assert_equal(1, len(world.browser.windows))
......
# pylint: disable=W0401, W0511 # pylint: disable=W0401, W0511
# TODO: component.py should explicitly enumerate exports with __all__
from .component import *
# TODO: course.py should explicitly enumerate exports with __all__
from .course import *
# Disable warnings about import from wildcard # Disable warnings about import from wildcard
# All files below declare exports with __all__ # All files below declare exports with __all__
from .assets import * from .assets import *
from .checklist import * from .checklist import *
from .component import *
from .course import *
from .error import * from .error import *
from .item import * from .item import *
from .preview import * from .preview import *
......
...@@ -59,12 +59,12 @@ def asset_index(request, org, course, name): ...@@ -59,12 +59,12 @@ def asset_index(request, org, course, name):
asset_display = [] asset_display = []
for asset in assets: for asset in assets:
id = asset['_id'] asset_id = asset['_id']
display_info = {} display_info = {}
display_info['displayname'] = asset['displayname'] display_info['displayname'] = asset['displayname']
display_info['uploadDate'] = get_default_time_display(asset['uploadDate'].timetuple()) display_info['uploadDate'] = get_default_time_display(asset['uploadDate'].timetuple())
asset_location = StaticContent.compute_location(id['org'], id['course'], id['name']) asset_location = StaticContent.compute_location(asset_id['org'], asset_id['course'], asset_id['name'])
display_info['url'] = StaticContent.get_url_path_from_location(asset_location) display_info['url'] = StaticContent.get_url_path_from_location(asset_location)
# note, due to the schema change we may not have a 'thumbnail_location' in the result set # note, due to the schema change we may not have a 'thumbnail_location' in the result set
...@@ -171,13 +171,13 @@ def import_course(request, org, course, name): ...@@ -171,13 +171,13 @@ def import_course(request, org, course, name):
temp_file.write(chunk) temp_file.write(chunk)
temp_file.close() temp_file.close()
tf = tarfile.open(temp_filepath) tar_file = tarfile.open(temp_filepath)
tf.extractall(course_dir + '/') tar_file.extractall(course_dir + '/')
# find the 'course.xml' file # find the 'course.xml' file
for r, d, f in os.walk(course_dir): for dirpath, _dirnames, filenames in os.walk(course_dir):
for files in f: for files in filenames:
if files == 'course.xml': if files == 'course.xml':
break break
if files == 'course.xml': if files == 'course.xml':
...@@ -186,13 +186,13 @@ def import_course(request, org, course, name): ...@@ -186,13 +186,13 @@ def import_course(request, org, course, name):
if files != 'course.xml': if files != 'course.xml':
return HttpResponse(json.dumps({'ErrMsg': 'Could not find the course.xml file in the package.'})) return HttpResponse(json.dumps({'ErrMsg': 'Could not find the course.xml file in the package.'}))
logging.debug('found course.xml at {0}'.format(r)) logging.debug('found course.xml at {0}'.format(dirpath))
if r != course_dir: if dirpath != course_dir:
for fname in os.listdir(r): for fname in os.listdir(dirpath):
shutil.move(r / fname, course_dir) shutil.move(dirpath / fname, course_dir)
module_store, course_items = import_from_xml(modulestore('direct'), settings.GITHUB_REPO_ROOT, _module_store, course_items = import_from_xml(modulestore('direct'), settings.GITHUB_REPO_ROOT,
[course_subdir], load_error_modules=False, [course_subdir], load_error_modules=False,
static_content_store=contentstore(), static_content_store=contentstore(),
target_location_namespace=Location(location), target_location_namespace=Location(location),
...@@ -234,9 +234,9 @@ def generate_export_course(request, org, course, name): ...@@ -234,9 +234,9 @@ def generate_export_course(request, org, course, name):
#filename = root_dir / name + '.tar.gz' #filename = root_dir / name + '.tar.gz'
logging.debug('tar file being generated at {0}'.format(export_file.name)) logging.debug('tar file being generated at {0}'.format(export_file.name))
tf = tarfile.open(name=export_file.name, mode='w:gz') tar_file = tarfile.open(name=export_file.name, mode='w:gz')
tf.add(root_dir / name, arcname=name) tar_file.add(root_dir / name, arcname=name)
tf.close() tar_file.close()
# remove temp dir # remove temp dir
shutil.rmtree(root_dir / name) shutil.rmtree(root_dir / name)
......
...@@ -26,16 +26,22 @@ from models.settings.course_grading import CourseGradingModel ...@@ -26,16 +26,22 @@ from models.settings.course_grading import CourseGradingModel
from .requests import get_request_method, _xmodule_recurse from .requests import get_request_method, _xmodule_recurse
from .access import has_access from .access import has_access
# TODO: should explicitly enumerate exports with __all__ __all__ = ['OPEN_ENDED_COMPONENT_TYPES',
'ADVANCED_COMPONENT_POLICY_KEY',
# to install PIL on MacOSX: 'easy_install http://dist.repoze.org/PIL-1.1.6.tar.gz' 'edit_subsection',
'edit_unit',
'assignment_type_update',
'create_draft',
'publish_draft',
'unpublish_unit',
'module_info']
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
COMPONENT_TYPES = ['customtag', 'discussion', 'html', 'problem', 'video'] COMPONENT_TYPES = ['customtag', 'discussion', 'html', 'problem', 'video']
OPEN_ENDED_COMPONENT_TYPES = ["combinedopenended", "peergrading"] OPEN_ENDED_COMPONENT_TYPES = ["combinedopenended", "peergrading"]
ADVANCED_COMPONENT_TYPES = ['annotatable' + 'word_cloud'] + OPEN_ENDED_COMPONENT_TYPES ADVANCED_COMPONENT_TYPES = ['annotatable', 'word_cloud'] + OPEN_ENDED_COMPONENT_TYPES
ADVANCED_COMPONENT_CATEGORY = 'advanced' ADVANCED_COMPONENT_CATEGORY = 'advanced'
ADVANCED_COMPONENT_POLICY_KEY = 'advanced_modules' ADVANCED_COMPONENT_POLICY_KEY = 'advanced_modules'
......
"""
Views related to operations on course objects
"""
import json import json
import time import time
...@@ -10,16 +13,17 @@ from django.core.urlresolvers import reverse ...@@ -10,16 +13,17 @@ from django.core.urlresolvers import reverse
from mitxmako.shortcuts import render_to_response from mitxmako.shortcuts import render_to_response
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.exceptions import ItemNotFoundError, \ from xmodule.modulestore.exceptions \
InvalidLocationError import ItemNotFoundError, InvalidLocationError
from xmodule.modulestore import Location from xmodule.modulestore import Location
from contentstore.course_info_model import get_course_updates, \ from contentstore.course_info_model \
update_course_updates, delete_course_update import get_course_updates, update_course_updates, delete_course_update
from contentstore.utils import get_lms_link_for_item, \ from contentstore.utils \
add_open_ended_panel_tab, remove_open_ended_panel_tab import get_lms_link_for_item, add_open_ended_panel_tab, \
from models.settings.course_details import CourseDetails, \ remove_open_ended_panel_tab
CourseSettingsEncoder from models.settings.course_details \
import CourseDetails, CourseSettingsEncoder
from models.settings.course_grading import CourseGradingModel from models.settings.course_grading import CourseGradingModel
from models.settings.course_metadata import CourseMetadata from models.settings.course_metadata import CourseMetadata
from auth.authz import create_all_course_groups from auth.authz import create_all_course_groups
...@@ -30,7 +34,13 @@ from .requests import get_request_method ...@@ -30,7 +34,13 @@ from .requests import get_request_method
from .tabs import initialize_course_tabs from .tabs import initialize_course_tabs
from .component import OPEN_ENDED_COMPONENT_TYPES, ADVANCED_COMPONENT_POLICY_KEY from .component import OPEN_ENDED_COMPONENT_TYPES, ADVANCED_COMPONENT_POLICY_KEY
# TODO: should explicitly enumerate exports with __all__ __all__ = ['course_index', 'create_new_course', 'course_info',
'course_info_updates', 'get_course_settings',
'course_config_graders_page',
'course_config_advanced_page',
'course_settings_updates',
'course_grader_updates',
'course_advanced_updates']
@login_required @login_required
...@@ -87,8 +97,9 @@ def create_new_course(request): ...@@ -87,8 +97,9 @@ def create_new_course(request):
try: try:
dest_location = Location('i4x', org, number, 'course', Location.clean(display_name)) dest_location = Location('i4x', org, number, 'course', Location.clean(display_name))
except InvalidLocationError as e: except InvalidLocationError as error:
return HttpResponse(json.dumps({'ErrMsg': "Unable to create course '" + display_name + "'.\n\n" + e.message})) return HttpResponse(json.dumps({'ErrMsg': "Unable to create course '" +
display_name + "'.\n\n" + error.message}))
# see if the course already exists # see if the course already exists
existing_course = None existing_course = None
......
...@@ -96,7 +96,7 @@ def preview_module_system(request, preview_id, descriptor): ...@@ -96,7 +96,7 @@ def preview_module_system(request, preview_id, descriptor):
return ModuleSystem( return ModuleSystem(
ajax_url=reverse('preview_dispatch', args=[preview_id, descriptor.location.url(), '']).rstrip('/'), ajax_url=reverse('preview_dispatch', args=[preview_id, descriptor.location.url(), '']).rstrip('/'),
# TODO (cpennington): Do we want to track how instructors are using the preview problems? # TODO (cpennington): Do we want to track how instructors are using the preview problems?
track_function=lambda type, event: None, track_function=lambda event_type, event: None,
filestore=descriptor.system.resources_fs, filestore=descriptor.system.resources_fs,
get_module=partial(get_preview_module, request, preview_id), get_module=partial(get_preview_module, request, preview_id),
render_template=render_from_lms, render_template=render_from_lms,
...@@ -171,7 +171,7 @@ def get_module_previews(request, descriptor): ...@@ -171,7 +171,7 @@ def get_module_previews(request, descriptor):
descriptor: An XModuleDescriptor descriptor: An XModuleDescriptor
""" """
preview_html = [] preview_html = []
for idx, (instance_state, shared_state) in enumerate(descriptor.get_sample_state()): for idx, (_instance_state, _shared_state) in enumerate(descriptor.get_sample_state()):
module = load_preview_module(request, str(idx), descriptor) module = load_preview_module(request, str(idx), descriptor)
preview_html.append(module.get_html()) preview_html.append(module.get_html())
return preview_html return preview_html
...@@ -33,7 +33,7 @@ PIPELINE_JS['spec'] = { ...@@ -33,7 +33,7 @@ PIPELINE_JS['spec'] = {
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee' JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
STATICFILES_DIRS.append(COMMON_ROOT / 'test' / 'phantom-jasmine' / 'lib') STATICFILES_DIRS.append(REPO_ROOT/'node_modules/phantom-jasmine/lib')
# Remove the localization middleware class because it requires the test database # Remove the localization middleware class because it requires the test database
# to be sync'd and migrated in order to run the jasmine tests interactively # to be sync'd and migrated in order to run the jasmine tests interactively
......
...@@ -22,6 +22,7 @@ CMS.Views.Checklists = Backbone.View.extend({ ...@@ -22,6 +22,7 @@ CMS.Views.Checklists = Backbone.View.extend({
} }
); );
}, },
reset: true,
error: CMS.ServerError error: CMS.ServerError
} }
); );
......
...@@ -160,9 +160,15 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({ ...@@ -160,9 +160,15 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
var targetModel = this.eventModel(event); var targetModel = this.eventModel(event);
this.modelDom(event).remove(); this.modelDom(event).remove();
var cacheThis = this; var cacheThis = this;
targetModel.destroy({success : function (model, response) { targetModel.destroy({
cacheThis.collection.fetch({success : function() {cacheThis.render();}, success: function (model, response) {
error : CMS.ServerError}); cacheThis.collection.fetch({
success: function() {
cacheThis.render();
},
reset: true,
error: CMS.ServerError
});
}, },
error : CMS.ServerError error : CMS.ServerError
}); });
...@@ -238,8 +244,7 @@ CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({ ...@@ -238,8 +244,7 @@ CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({
initialize: function() { initialize: function() {
var self = this; var self = this;
this.model.fetch( this.model.fetch({
{
complete: function() { complete: function() {
window.templateLoader.loadRemoteTemplate("course_info_handouts", window.templateLoader.loadRemoteTemplate("course_info_handouts",
"/static/client_templates/course_info_handouts.html", "/static/client_templates/course_info_handouts.html",
...@@ -249,9 +254,9 @@ CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({ ...@@ -249,9 +254,9 @@ CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({
} }
); );
}, },
error : CMS.ServerError reset: true,
} error: CMS.ServerError
); });
}, },
render: function () { render: function () {
......
...@@ -155,6 +155,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({ ...@@ -155,6 +155,7 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
self.model.clear({silent : true}); self.model.clear({silent : true});
self.model.fetch({ self.model.fetch({
success : function() { self.render(); }, success : function() { self.render(); },
reset: true,
error : CMS.ServerError error : CMS.ServerError
}); });
}, },
......
...@@ -8,11 +8,10 @@ html { ...@@ -8,11 +8,10 @@ html {
} }
body { body {
@include font-size(16); @extend .t-copy-base;
min-width: $fg-min-width; min-width: $fg-min-width;
background: $gray-l5; background: $gray-l5;
line-height: 1.6; color: $gray-d2;
color: $baseFontColor;
} }
body, input { body, input {
...@@ -30,7 +29,7 @@ a { ...@@ -30,7 +29,7 @@ a {
} }
h1 { h1 {
@include font-size(28); @extend .t-title4;
font-weight: 300; font-weight: 300;
} }
...@@ -51,43 +50,183 @@ h1 { ...@@ -51,43 +50,183 @@ h1 {
// ==================== // ====================
// typography - basic // typography - basic
.page-header {
@extend .t-title3;
display: block;
font-weight: 600;
color: $gray-d3;
.subtitle {
@extend .t-title7;
position: relative;
top: ($baseline/4);
display: block;
color: $gray-l2;
font-weight: 400;
}
}
.section-header {
@extend .t-title4;
font-weight: 600;
.subtitle {
@extend .t-title7;
}
}
.area-header {
@extend .t-title6;
font-weight: 600;
.subtitle {
@extend .t-title8;
}
}
.area-subheader {
@extend .t-title7;
font-weight: 600;
.subtitle {
@extend .t-title9;
}
}
// ====================
// typography - primary content
.content-primary {
.section-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.content-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.area-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.area-subheader {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
}
// typography - primary content
.content-secondary {
.section-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.content-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.content-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
}
// ====================
// typography - loose headings (BT: needs to be removed once html is clean)
.title-1, .title-2, .title-3, .title-4, .title-5, .title-6 { .title-1, .title-2, .title-3, .title-4, .title-5, .title-6 {
font-weight: 600; font-weight: 600;
}
// typography - primary content
.content-secondary {
.section-header {
color: $gray-d3; color: $gray-d3;
margin: 0;
padding: 0; .subtitle {
color: $gray-l2;
}
}
.content-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
.content-header {
color: $gray-d3;
.subtitle {
color: $gray-l2;
}
}
} }
// ====================
// typography - loose headings (BT: needs to be removed once html is clean)
.title-1 { .title-1 {
@include font-size(32); @extend .t-title3;
margin-bottom: ($baseline*1.5); margin-bottom: ($baseline*1.5);
} }
.title-2 { .title-2 {
@include font-size(24); @extend .t-title4;
margin-bottom: $baseline; margin-bottom: $baseline;
} }
.title-3 { .title-3 {
@include font-size(18); @extend .t-title5;
margin-bottom: ($baseline/2); margin-bottom: ($baseline/2);
} }
.title-4 { .title-4 {
@include font-size(14); @extend .t-title7;
margin-bottom: $baseline; margin-bottom: $baseline;
font-weight: 500 font-weight: 500
} }
.title-5 { .title-5 {
@include font-size(14); @extend .t-title7;
color: $gray-l1; color: $gray-l1;
margin-bottom: $baseline; margin-bottom: $baseline;
font-weight: 500 font-weight: 500
} }
.title-6 { .title-6 {
@include font-size(14); @extend .t-title7;
color: $gray-l2; color: $gray-l2;
margin-bottom: $baseline; margin-bottom: $baseline;
font-weight: 500 font-weight: 500
...@@ -118,7 +257,6 @@ p, ul, ol, dl { ...@@ -118,7 +257,6 @@ p, ul, ol, dl {
.mast, .metadata { .mast, .metadata {
@include clearfix(); @include clearfix();
@include font-size(16);
position: relative; position: relative;
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
...@@ -131,53 +269,8 @@ p, ul, ol, dl { ...@@ -131,53 +269,8 @@ p, ul, ol, dl {
border-bottom: 1px solid $gray-l4; border-bottom: 1px solid $gray-l4;
padding-bottom: ($baseline/2); padding-bottom: ($baseline/2);
.title-sub {
@include font-size(14);
position: relative;
top: ($baseline/4);
display: block;
margin: 0;
color: $gray-l2;
font-weight: 400;
}
.title, .title-1 {
@include font-size(32);
margin: 0;
padding: 0;
font-weight: 600;
color: $gray-d3;
}
.nav-hierarchy {
@include font-size(14);
display: block;
margin: 0;
color: $gray-l2;
font-weight: 400;
.nav-item {
display: inline;
vertical-align: middle;
margin-right: ($baseline/4);
&:after {
content: ">>";
margin-left: ($baseline/4);
}
&:last-child {
margin-right: 0;
&:after {
content: none;
}
}
}
}
// layout with actions // layout with actions
.title { .page-header {
width: flex-grid(12); width: flex-grid(12);
} }
...@@ -185,7 +278,7 @@ p, ul, ol, dl { ...@@ -185,7 +278,7 @@ p, ul, ol, dl {
&.has-actions { &.has-actions {
@include clearfix(); @include clearfix();
.title { .page-header {
float: left; float: left;
width: flex-grid(6,12); width: flex-grid(6,12);
margin-right: flex-gutter(); margin-right: flex-gutter();
...@@ -210,22 +303,20 @@ p, ul, ol, dl { ...@@ -210,22 +303,20 @@ p, ul, ol, dl {
// buttons // buttons
.button { .button {
padding: ($baseline/4) ($baseline/2) ($baseline/3) ($baseline/2) !important; padding: ($baseline/4) ($baseline/2) ($baseline/3) ($baseline/2);
font-weight: 400 !important;
} }
.new-button { .new-button {
font-weight: 700 !important;
} }
.view-button { .view-button {
font-weight: 700 !important;
} }
.upload-button .icon-create { .upload-button .icon-create {
@include font-size(18); @extend .t-action2;
margin-top: ($baseline/4); line-height: 0 !important;
} }
} }
} }
...@@ -254,7 +345,7 @@ p, ul, ol, dl { ...@@ -254,7 +345,7 @@ p, ul, ol, dl {
.content { .content {
@include clearfix(); @include clearfix();
@include font-size(16); @extend .t-copy-base;
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
width: flex-grid(12); width: flex-grid(12);
...@@ -268,14 +359,14 @@ p, ul, ol, dl { ...@@ -268,14 +359,14 @@ p, ul, ol, dl {
padding-bottom: ($baseline/2); padding-bottom: ($baseline/2);
.title-sub { .title-sub {
@include font-size(14); @extend .t-copy-sub1;
display: block; display: block;
margin: 0; margin: 0;
color: $gray-l2; color: $gray-l2;
} }
.title-1 { .title-1 {
@include font-size(32); @extend .t-title3;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-weight: 600; font-weight: 600;
...@@ -285,7 +376,7 @@ p, ul, ol, dl { ...@@ -285,7 +376,7 @@ p, ul, ol, dl {
.introduction { .introduction {
@include box-sizing(border-box); @include box-sizing(border-box);
@include font-size(14); @extend .t-copy-sub1;
width: flex-grid(12); width: flex-grid(12);
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
...@@ -303,14 +394,14 @@ p, ul, ol, dl { ...@@ -303,14 +394,14 @@ p, ul, ol, dl {
} }
.nav-introduction-supplementary { .nav-introduction-supplementary {
@include font-size(13); @extend .t-copy-sub2;
float: right; float: right;
width: flex-grid(4,12); width: flex-grid(4,12);
display: block; display: block;
text-align: right; text-align: right;
.icon { .icon {
@include font-size(14); @extend .t-action3;
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
margin-right: ($baseline/4); margin-right: ($baseline/4);
...@@ -327,21 +418,17 @@ p, ul, ol, dl { ...@@ -327,21 +418,17 @@ p, ul, ol, dl {
// layout - primary content // layout - primary content
.content-primary { .content-primary {
.title-1, .title-2, .title-3, .title-4, .title-5, .title-5 {
color: $gray-d3;
}
.title-1 { .title-1 {
@extend .t-title-1; @extend .t-title3;
} }
.title-2 { .title-2 {
@extend .t-title-2; @extend .t-title4;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
} }
.title-3 { .title-3 {
@extend .t-title-3; @extend .t-title6;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
} }
...@@ -355,7 +442,7 @@ p, ul, ol, dl { ...@@ -355,7 +442,7 @@ p, ul, ol, dl {
} }
.tip { .tip {
@include font-size(13); @extend .t-copy-sub2;
width: flex-grid(7, 12); width: flex-grid(7, 12);
float: right; float: right;
margin-top: ($baseline/2); margin-top: ($baseline/2);
...@@ -373,7 +460,7 @@ p, ul, ol, dl { ...@@ -373,7 +460,7 @@ p, ul, ol, dl {
} }
.bit { .bit {
@include font-size(13); @extend .t-copy-sub1;
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
border-bottom: 1px solid $gray-l4; border-bottom: 1px solid $gray-l4;
padding: 0 0 $baseline 0; padding: 0 0 $baseline 0;
...@@ -386,7 +473,7 @@ p, ul, ol, dl { ...@@ -386,7 +473,7 @@ p, ul, ol, dl {
} }
h3 { h3 {
@include font-size(14); @extend .t-title7;
margin: 0 0 ($baseline/4) 0; margin: 0 0 ($baseline/4) 0;
color: $gray-d2; color: $gray-d2;
font-weight: 600; font-weight: 600;
...@@ -494,7 +581,7 @@ p, ul, ol, dl { ...@@ -494,7 +581,7 @@ p, ul, ol, dl {
// misc // misc
hr.divide { hr.divide {
@include text-sr(); @extend .text-sr;
} }
.item-details { .item-details {
...@@ -655,7 +742,7 @@ hr.divide { ...@@ -655,7 +742,7 @@ hr.divide {
.new-button { .new-button {
@include green-button; @include green-button;
@include font-size(13); @extend .t-action4;
padding: 8px 20px 10px; padding: 8px 20px 10px;
text-align: center; text-align: center;
...@@ -674,7 +761,7 @@ hr.divide { ...@@ -674,7 +761,7 @@ hr.divide {
.view-button { .view-button {
@include blue-button; @include blue-button;
@include font-size(13); @extend .t-copy-base;
text-align: center; text-align: center;
&.big { &.big {
...@@ -693,7 +780,7 @@ hr.divide { ...@@ -693,7 +780,7 @@ hr.divide {
.edit-button.standard, .edit-button.standard,
.delete-button.standard { .delete-button.standard {
@include font-size(12); @extend .t-action4;
@include white-button; @include white-button;
float: left; float: left;
padding: 3px 10px 4px; padding: 3px 10px 4px;
...@@ -714,6 +801,7 @@ hr.divide { ...@@ -714,6 +801,7 @@ hr.divide {
} }
.tooltip { .tooltip {
@extend .t-copy-sub2;
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
...@@ -721,7 +809,6 @@ hr.divide { ...@@ -721,7 +809,6 @@ hr.divide {
padding: 0 10px; padding: 0 10px;
border-radius: 3px; border-radius: 3px;
background: rgba(0, 0, 0, 0.85); background: rgba(0, 0, 0, 0.85);
font-size: 11px;
font-weight: normal; font-weight: normal;
line-height: 26px; line-height: 26px;
color: #fff; color: #fff;
...@@ -745,7 +832,7 @@ hr.divide { ...@@ -745,7 +832,7 @@ hr.divide {
// basic utility // basic utility
.sr { .sr {
@include text-sr(); @extend .text-sr;
} }
.fake-link { .fake-link {
...@@ -798,7 +885,7 @@ body.js { ...@@ -798,7 +885,7 @@ body.js {
text-align: center; text-align: center;
.label { .label {
@include text-sr(); @extend .text-sr;
} }
.ss-icon { .ss-icon {
...@@ -821,14 +908,14 @@ body.js { ...@@ -821,14 +908,14 @@ body.js {
} }
.title { .title {
@include font-size(18); @extend .t-title5;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
font-weight: 600; font-weight: 600;
color: $gray-d3; color: $gray-d3;
} }
.description { .description {
@include font-size(13); @extend .t-copy-sub2;
margin-top: ($baseline/2); margin-top: ($baseline/2);
color: $gray-l1; color: $gray-l1;
} }
......
...@@ -6,6 +6,11 @@ ...@@ -6,6 +6,11 @@
// @include box-sizing(border-box); // @include box-sizing(border-box);
// } // }
// better text rendering/kerning through SVG
* {
text-rendering: optimizeLegibility;
}
html, body, div, span, applet, object, iframe, html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre, h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code, a, abbr, acronym, address, big, cite, code,
......
// studio - shame
// // shame file - used for any bad-form/orphaned scss that knowingly violate edX FED architecture/standards (see - http://csswizardry.com/2013/04/shame-css/)
// ====================
...@@ -12,9 +12,15 @@ $fg-max-columns: 12; ...@@ -12,9 +12,15 @@ $fg-max-columns: 12;
$fg-max-width: 1280px; $fg-max-width: 1280px;
$fg-min-width: 900px; $fg-min-width: 900px;
// type // ====================
$sans-serif: 'Open Sans', $verdana;
$body-line-height: golden-ratio(.875em, 1); // fonts
$f-serif: 'Bree Serif', Georgia, Cambria, 'Times New Roman', Times, serif;
$f-sans-serif: 'Open Sans','Helvetica Neue', Helvetica, Arial, sans-serif;
$f-decorative: '';
$f-monospace: 'Bitstream Vera Sans Mono', Consolas, Courier, monospace;
// ====================
// colors - new for re-org // colors - new for re-org
$black: rgb(0,0,0); $black: rgb(0,0,0);
...@@ -152,11 +158,14 @@ $shadow-l1: rgba(0,0,0,0.1); ...@@ -152,11 +158,14 @@ $shadow-l1: rgba(0,0,0,0.1);
$shadow-l2: rgba(0,0,0,0.05); $shadow-l2: rgba(0,0,0,0.05);
$shadow-d1: rgba(0,0,0,0.4); $shadow-d1: rgba(0,0,0,0.4);
// ====================
// specific UI // specific UI
$notification-height: ($baseline*10); $notification-height: ($baseline*10);
// colors - inherited // ====================
// inherited
$baseFontColor: $gray-d2; $baseFontColor: $gray-d2;
$offBlack: #3c3c3c; $offBlack: #3c3c3c;
$green: #108614; $green: #108614;
...@@ -173,3 +182,8 @@ $darkGreen: rgb(52, 133, 76); ...@@ -173,3 +182,8 @@ $darkGreen: rgb(52, 133, 76);
$lightBluishGrey: rgb(197, 207, 223); $lightBluishGrey: rgb(197, 207, 223);
$lightBluishGrey2: rgb(213, 220, 228); $lightBluishGrey2: rgb(213, 220, 228);
$error-red: rgb(253, 87, 87); $error-red: rgb(253, 87, 87);
// type
$sans-serif: $f-serif;
$body-line-height: golden-ratio(.875em, 1);
@font-face { // studio - assets - fonts
font-family: 'Open Sans'; // ====================
font-style: normal;
font-weight: 700; // import from google fonts - Open Sans
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/k3k702ZOKiLJc3WVjuplzKRDOzjiPcYnFooOUGCOsRk.woff) format('woff'); @import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,700,300);
}
@font-face { // import from google fonts - Bree
font-family: 'Open Sans'; @import url(http://fonts.googleapis.com/css?family=Bree+Serif);
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/DXI1ORHCpsQm3Vp6mXoaTaRDOzjiPcYnFooOUGCOsRk.woff) format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 700;
src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxhbnBKKEOwRKgsHDreGcocg.woff) format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 300;
src: local('Open Sans Light Italic'), local('OpenSansLight-Italic'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxvR_54zmj3SbGZQh3vCOwvY.woff) format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 400;
src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/xjAJXh38I15wypJXxuGMBrrIa-7acMAeDBVuclsi6Gc.woff) format('woff');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(http://themes.googleusercontent.com/static/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3bO3LdcAZYWl9Si6vvxL-qU.woff) format('woff');
}
// studio - css architecture // studio - css architecture
// ==================== // ====================
// bourbon libs and resets // libs and resets *do not edit*
@import 'bourbon/bourbon'; @import 'bourbon/bourbon'; // lib - bourbon
@import 'bourbon/addons/button'; @import 'bourbon/addons/button'; // lib bourbon - button add-on
@import "variables";
// VENDOR + REBASE *referenced/used vendor presentation and reset*
// ====================
@import 'vendor/normalize'; @import 'vendor/normalize';
@import 'reset'; @import 'reset';
// utilities
// BASE *default edX offerings*
// ====================
// base - utilities
@import 'variables'; @import 'variables';
@import 'mixins'; @import 'mixins';
@import 'cms_mixins'; @import 'mixins-inherited';
// assets // base - assets
@import 'assets/fonts'; @import 'assets/fonts';
@import 'assets/graphics'; @import 'assets/graphics'; // sprites, basic img/figure/svg styling
@import 'assets/keyframes'; @import 'assets/anims'; // animations
// base // base - starter
@import 'base'; @import 'base';
// elements // base - elements
@import 'elements/typography'; @import 'elements/typography';
@import 'elements/icons'; @import 'elements/icons'; // references to icons used
@import 'elements/controls'; @import 'elements/controls'; // buttons, link styles, sliders, etc.
@import 'elements/navigation'; @import 'elements/navigation'; // all archetypes of navigation
@import 'elements/forms';
@import 'elements/header'; @import 'elements/header';
@import 'elements/footer'; @import 'elements/footer';
@import 'elements/sock'; @import 'elements/sock';
@import 'elements/forms';
@import 'elements/modal';
@import 'elements/alerts';
@import 'elements/vendor';
@import 'elements/tender-widget'; @import 'elements/tender-widget';
@import 'elements/system-feedback'; // alerts, notifications, states
@import 'elements/system-help'; // help UI
@import 'elements/modal'; // interstitial UI, dialogs, modal windows
@import 'elements/vendor'; // overrides to vendor-provided styling
// specific views // base - specific views
@import 'views/account'; @import 'views/account';
@import 'views/assets'; @import 'views/assets';
@import 'views/updates'; @import 'views/updates';
...@@ -51,8 +58,12 @@ ...@@ -51,8 +58,12 @@
@import 'views/users'; @import 'views/users';
@import 'views/checklists'; @import 'views/checklists';
// temp - inherited
@import 'assets/content-types'; @import 'assets/content-types';
// xblock-related // xmodule
@import 'xmodule/modules/css/module-styles.scss'; @import 'xmodule/modules/css/module-styles.scss';
@import 'xmodule/descriptors/css/module-styles.scss'; @import 'xmodule/descriptors/css/module-styles.scss';
@import 'shame'; // shame file - used for any bad-form/orphaned scss that knowingly violate edX FED architecture/standards (see - http://csswizardry.com/2013/04/shame-css/)
...@@ -141,3 +141,9 @@ ...@@ -141,3 +141,9 @@
// calls-to-action // calls-to-action
// ====================
// specific buttons - view live
.view-live-button {
@extend .t-action4;
}
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
padding: $baseline; padding: $baseline;
footer.primary { footer.primary {
@extend .t-copy-sub2;
@include clearfix(); @include clearfix();
@include font-size(13);
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
width: flex-grid(12); width: flex-grid(12);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// ==================== // ====================
.wrapper-header { .wrapper-header {
@extend .depth3;
margin: 0; margin: 0;
padding: $baseline; padding: $baseline;
border-bottom: 1px solid $gray; border-bottom: 1px solid $gray;
...@@ -10,7 +11,6 @@ ...@@ -10,7 +11,6 @@
height: 76px; height: 76px;
position: relative; position: relative;
width: 100%; width: 100%;
z-index: 1000;
a { a {
color: $baseFontColor; color: $baseFontColor;
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
padding-right: ($baseline*0.75); padding-right: ($baseline*0.75);
a { a {
@include text-hide(); @extend .text-hide;
display: block; display: block;
width: 164px; width: 164px;
height: 32px; height: 32px;
...@@ -146,7 +146,7 @@ ...@@ -146,7 +146,7 @@
.title { .title {
display: block; display: block;
padding: 5px; padding: 0 ($baseline/4);
text-transform: uppercase; text-transform: uppercase;
font-weight: 600; font-weight: 600;
color: $gray-d3; color: $gray-d3;
......
...@@ -2,6 +2,19 @@ ...@@ -2,6 +2,19 @@
// ==================== // ====================
// common // common
nav {
ol, ul {
@extend .no-list;
}
.nav-item {
a {
}
}
}
// ==================== // ====================
......
...@@ -28,13 +28,13 @@ ...@@ -28,13 +28,13 @@
.cta-show-sock { .cta-show-sock {
@extend .btn-pill; @extend .btn-pill;
@extend .t-action3; @extend .t-action4;
background: $gray-l5; background: $gray-l5;
padding: ($baseline/2) $baseline; padding: ($baseline/2) $baseline;
color: $gray; color: $gray;
.icon { .icon {
@include font-size(16); @include font-size(14);
} }
&:hover { &:hover {
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
header { header {
.title { .title {
@extend .t-title-2; @extend .t-title4;
} }
.ss-icon { .ss-icon {
...@@ -73,12 +73,13 @@ ...@@ -73,12 +73,13 @@
@include box-sizing(border-box); @include box-sizing(border-box);
.title { .title {
@extend .t-title-3; @extend .t-title6;
color: $white; color: $white;
margin-bottom: ($baseline/2); margin-bottom: ($baseline/2);
} }
.copy { .copy {
@extend .t-copy-sub2;
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
} }
...@@ -94,6 +95,7 @@ ...@@ -94,6 +95,7 @@
} }
.action { .action {
@extend .t-action4;
display: block; display: block;
.icon { .icon {
......
// studio alerts, prompts and notifications // studio - elements - system feedback
// alerts, notifications, prompts, and status communication
// ==================== // ====================
// shared // shared
...@@ -6,7 +7,7 @@ ...@@ -6,7 +7,7 @@
@include box-sizing(border-box); @include box-sizing(border-box);
.copy { .copy {
@extend .t-copy-sub2; @extend .t-copy-sub1;
} }
} }
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
.nav-actions .action-primary { .nav-actions .action-primary {
@include blue-button(); @include blue-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $blue-d2; border-color: $blue-d2;
} }
...@@ -53,6 +55,7 @@ ...@@ -53,6 +55,7 @@
.nav-actions .action-primary { .nav-actions .action-primary {
@include orange-button(); @include orange-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $orange-d2; border-color: $orange-d2;
color: $gray-d4; color: $gray-d4;
} }
...@@ -71,6 +74,7 @@ ...@@ -71,6 +74,7 @@
.nav-actions .action-primary { .nav-actions .action-primary {
@include red-button(); @include red-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $red-d2; border-color: $red-d2;
} }
...@@ -88,6 +92,7 @@ ...@@ -88,6 +92,7 @@
.nav-actions .action-primary { .nav-actions .action-primary {
@include blue-button(); @include blue-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $blue-d2; border-color: $blue-d2;
} }
...@@ -105,6 +110,7 @@ ...@@ -105,6 +110,7 @@
.nav-actions .action-primary { .nav-actions .action-primary {
@include green-button(); @include green-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $green-d2; border-color: $green-d2;
} }
...@@ -121,8 +127,9 @@ ...@@ -121,8 +127,9 @@
&.step-required { &.step-required {
.nav-actions .action-primary { .nav-actions .action-primary {
border-color: $pink-d2;
@include pink-button(); @include pink-button();
@include font-size(12); // needed due to bad button mixins for now
border-color: $pink-d2;
} }
a { a {
...@@ -137,6 +144,7 @@ ...@@ -137,6 +144,7 @@
// prompts // prompts
.wrapper-prompt { .wrapper-prompt {
@extend .depth4;
@include transition(all 0.05s ease-in-out); @include transition(all 0.05s ease-in-out);
position: fixed; position: fixed;
top: 0; top: 0;
...@@ -144,7 +152,6 @@ ...@@ -144,7 +152,6 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
text-align: center; text-align: center;
z-index: 10000;
&:before { &:before {
content: ''; content: '';
...@@ -184,12 +191,12 @@ ...@@ -184,12 +191,12 @@
} }
.action-primary { .action-primary {
@extend .t-action3; @extend .t-action4;
font-weight: 600; font-weight: 600;
} }
.action-secondary { .action-secondary {
@extend .t-action3; @extend .t-action4;
} }
} }
} }
...@@ -235,11 +242,11 @@ ...@@ -235,11 +242,11 @@
// notifications // notifications
.wrapper-notification { .wrapper-notification {
@extend .depth3;
@include clearfix(); @include clearfix();
@include box-shadow(0 -1px 3px $shadow, inset 0 3px 1px $blue); @include box-shadow(0 -1px 3px $shadow, inset 0 3px 1px $blue);
position: fixed; position: fixed;
bottom: 0; bottom: 0;
z-index: 1000;
width: 100%; width: 100%;
padding: $baseline ($baseline*2); padding: $baseline ($baseline*2);
...@@ -361,18 +368,19 @@ ...@@ -361,18 +368,19 @@
@include font-size(22); @include font-size(22);
width: flex-grid(1, 12); width: flex-grid(1, 12);
height: ($baseline*1.25); height: ($baseline*1.25);
margin-top: ($baseline/4);
margin-right: flex-gutter(); margin-right: flex-gutter();
text-align: right; text-align: right;
color: $white; color: $white;
} }
.copy { .copy {
@extend .t-copy-sub2; @extend .t-copy-sub1;
width: flex-grid(10, 12); width: flex-grid(10, 12);
color: $gray-l2; color: $gray-l2;
.title { .title {
@extend .t-title-4; @extend .t-title7;
margin-bottom: 0; margin-bottom: 0;
color: $white; color: $white;
} }
...@@ -409,13 +417,13 @@ ...@@ -409,13 +417,13 @@
.action-primary { .action-primary {
@include blue-button(); @include blue-button();
@extend .t-action3;
border-color: $blue-d2; border-color: $blue-d2;
font-weight: 600; font-weight: 600;
} }
.action-secondary { .action-secondary {
@extend .t-action3;
@extend .t-action4;
} }
} }
...@@ -434,7 +442,7 @@ ...@@ -434,7 +442,7 @@
} }
.copy p { .copy p {
@include text-sr(); @extend .text-sr;
} }
} }
} }
...@@ -443,10 +451,10 @@ ...@@ -443,10 +451,10 @@
// alerts // alerts
.wrapper-alert { .wrapper-alert {
@extend .depth2;
@include box-sizing(border-box); @include box-sizing(border-box);
@include box-shadow(0 1px 1px $white, inset 0 2px 2px $shadow-d1, inset 0 -4px 1px $blue); @include box-shadow(0 1px 1px $white, inset 0 2px 2px $shadow-d1, inset 0 -4px 1px $blue);
position: relative; position: relative;
z-index: 100;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
border-top: 1px solid $black; border-top: 1px solid $black;
...@@ -504,7 +512,6 @@ ...@@ -504,7 +512,6 @@
// adopted alerts // adopted alerts
.alert { .alert {
@extend .t-copy-sub2;
@include box-sizing(border-box); @include box-sizing(border-box);
@include clearfix(); @include clearfix();
margin: 0 auto; margin: 0 auto;
...@@ -530,11 +537,11 @@ ...@@ -530,11 +537,11 @@
} }
.copy { .copy {
@extend .t-copy-sub2;
width: flex-grid(10, 12); width: flex-grid(10, 12);
color: $gray-l2; color: $gray-l2;
.title { .title {
@extend .t-title7;
margin-bottom: 0; margin-bottom: 0;
color: $white; color: $white;
} }
...@@ -568,12 +575,12 @@ ...@@ -568,12 +575,12 @@
} }
.action-primary { .action-primary {
@extend .t-action3; @extend .t-action4;
font-weight: 600; font-weight: 600;
} }
.action-secondary { .action-secondary {
@extend .t-action3; @extend .t-action4;
} }
} }
} }
...@@ -590,7 +597,7 @@ ...@@ -590,7 +597,7 @@
text-align: center; text-align: center;
.label { .label {
@include text-sr(); @extend .text-sr;
} }
.icon { .icon {
...@@ -730,7 +737,7 @@ body.uxdesign.alerts { ...@@ -730,7 +737,7 @@ body.uxdesign.alerts {
border-radius: 3px; border-radius: 3px;
background: #fbf6e1; background: #fbf6e1;
// background: #edbd3c; // background: #edbd3c;
@extend .t-copy-sub1; font-size: 14px;
@include clearfix; @include clearfix;
.alert-message { .alert-message {
......
// studio - elements - system help
// ====================
// studio - elements - typography // studio - elements - typography
// ==================== // ====================
// Scale - (6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 24, 36, 48, 60, 72)
// headings/titles // headings/titles
.t-title-1, .t-title-2, .t-title-3, .t-title-4, .t-title-5 { .t-title {
color: $gray-d3; font-family: $f-sans-serif;
}
.t-title1 {
@extend .t-title;
@include font-size(60);
@include lh(60);
} }
.t-title-1 { .t-title2 {
@extend .t-title;
@include font-size(48);
@include lh(48);
}
.t-title3 {
@include font-size(36); @include font-size(36);
@include lh(36);
} }
.t-title-2 { .t-title4 {
@extend .t-title;
@include font-size(24); @include font-size(24);
font-weight: 600; @include lh(24);
}
.t-title5 {
@extend .t-title;
@include font-size(18);
@include lh(18);
} }
.t-title-3 { .t-title6 {
@extend .t-title;
@include font-size(16); @include font-size(16);
font-weight: 600; @include lh(16);
} }
.t-title-4 { .t-title7 {
@extend .t-title;
@include font-size(14); @include font-size(14);
@include lh(14);
} }
.t-title-5 { .t-title8 {
@extend .t-title;
@include font-size(12);
@include lh(12);
}
.t-title9 {
@extend .t-title;
@include font-size(11);
@include lh(11);
} }
// ==================== // ====================
// copy // copy
.t-copy {
font-family: $f-sans-serif;
}
.t-copy-base { .t-copy-base {
@extend .t-copy;
@include font-size(16); @include font-size(16);
@include lh(16);
} }
.t-copy-lead1 { .t-copy-lead1 {
@extend .t-copy;
@include font-size(18); @include font-size(18);
@include lh(18);
} }
.t-copy-lead2 { .t-copy-lead2 {
@include font-size(20); @extend .t-copy;
@include font-size(24);
@include lh(24);
} }
.t-copy-sub1 { .t-copy-sub1 {
@extend .t-copy;
@include font-size(14); @include font-size(14);
@include lh(14);
} }
.t-copy-sub2 { .t-copy-sub2 {
@include font-size(13); @extend .t-copy;
}
.t-copy-sub3 {
@include font-size(12); @include font-size(12);
@include lh(12);
} }
// ==================== // ====================
// actions/labels // actions/labels
.t-action1 { .t-action1 {
@include font-size(14); @include font-size(18);
font-weight: 600; @include lh(18);
} }
.t-action2 { .t-action2 {
@include font-size(13); @include font-size(16);
font-weight: 600; @include lh(16);
text-transform: uppercase;
} }
.t-action3 { .t-action3 {
@include font-size(13); @include font-size(14);
@include lh(14);
} }
.t-action4 { .t-action4 {
@include font-size(12); @include font-size(12);
@include lh(12);
}
// ====================
// code
.t-code {
font-family: $f-monospace;
} }
// ==================== // ====================
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
border-color: $darkGrey; border-color: $darkGrey;
border-radius: 2px; border-radius: 2px;
background: #fff; background: #fff;
font-family: $sans-serif; font-family: $f-sans-serif;
font-size: 12px; font-size: 12px;
@include box-shadow(0 5px 10px rgba(0, 0, 0, 0.1)); @include box-shadow(0 5px 10px rgba(0, 0, 0, 0.1));
z-index: 100000 !important; z-index: 100000 !important;
......
...@@ -12,7 +12,7 @@ body.signup, body.signin { ...@@ -12,7 +12,7 @@ body.signup, body.signin {
.content { .content {
@include clearfix(); @include clearfix();
@include font-size(16); @extend .t-copy-base;
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
width: flex-grid(12); width: flex-grid(12);
...@@ -26,14 +26,14 @@ body.signup, body.signin { ...@@ -26,14 +26,14 @@ body.signup, body.signin {
padding-bottom: ($baseline/2); padding-bottom: ($baseline/2);
h1 { h1 {
@include font-size(32); @extend .t-title3;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-weight: 600; font-weight: 600;
} }
.action { .action {
@include font-size(13); @extend .t-action3;
position: absolute; position: absolute;
right: 0; right: 0;
top: 40%; top: 40%;
...@@ -41,7 +41,7 @@ body.signup, body.signin { ...@@ -41,7 +41,7 @@ body.signup, body.signin {
} }
.introduction { .introduction {
@include font-size(14); @extend .t-copy-sub1;
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
} }
} }
...@@ -69,8 +69,8 @@ body.signup, body.signin { ...@@ -69,8 +69,8 @@ body.signup, body.signin {
.action-primary { .action-primary {
@include blue-button; @include blue-button;
@extend .t-action2;
@include transition(all .15s); @include transition(all .15s);
@include font-size(15);
display: block; display: block;
width: 100%; width: 100%;
padding: ($baseline*0.75) ($baseline/2); padding: ($baseline*0.75) ($baseline/2);
...@@ -108,7 +108,7 @@ body.signup, body.signin { ...@@ -108,7 +108,7 @@ body.signup, body.signin {
} }
label { label {
@include font-size(14); @extend .t-copy-sub1;
@include transition(color, 0.15s, ease-in-out); @include transition(color, 0.15s, ease-in-out);
margin: 0 0 ($baseline/4) 0; margin: 0 0 ($baseline/4) 0;
...@@ -118,7 +118,7 @@ body.signup, body.signin { ...@@ -118,7 +118,7 @@ body.signup, body.signin {
} }
input, textarea { input, textarea {
@include font-size(16); @extend .t-copy-base;
height: 100%; height: 100%;
width: 100%; width: 100%;
padding: ($baseline/2); padding: ($baseline/2);
...@@ -171,8 +171,8 @@ body.signup, body.signin { ...@@ -171,8 +171,8 @@ body.signup, body.signin {
} }
.tip { .tip {
@extend .t-copy-sub2;
@include transition(color, 0.15s, ease-in-out); @include transition(color, 0.15s, ease-in-out);
@include font-size(13);
display: block; display: block;
margin-top: ($baseline/4); margin-top: ($baseline/4);
color: $gray-l3; color: $gray-l3;
...@@ -212,7 +212,7 @@ body.signup, body.signin { ...@@ -212,7 +212,7 @@ body.signup, body.signin {
width: flex-grid(4, 12); width: flex-grid(4, 12);
.bit { .bit {
@include font-size(13); @extend .t-copy-sub1;
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
border-bottom: 1px solid $gray-l4; border-bottom: 1px solid $gray-l4;
padding: 0 0 $baseline 0; padding: 0 0 $baseline 0;
...@@ -225,7 +225,7 @@ body.signup, body.signin { ...@@ -225,7 +225,7 @@ body.signup, body.signin {
} }
h3 { h3 {
@include font-size(14); @extend .t-title7;
margin: 0 0 ($baseline/4) 0; margin: 0 0 ($baseline/4) 0;
color: $gray-d2; color: $gray-d2;
font-weight: 600; font-weight: 600;
...@@ -245,7 +245,7 @@ body.signup, body.signin { ...@@ -245,7 +245,7 @@ body.signup, body.signin {
position: relative; position: relative;
.action-forgotpassword { .action-forgotpassword {
@include font-size(13); @extend .t-action3;
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
...@@ -257,7 +257,7 @@ body.signup, body.signin { ...@@ -257,7 +257,7 @@ body.signup, body.signin {
// messages // messages
.message { .message {
@include font-size(14); @extend .t-copy-sub1;
display: block; display: block;
} }
......
...@@ -23,7 +23,7 @@ body.course.checklists { ...@@ -23,7 +23,7 @@ body.course.checklists {
// visual status // visual status
.viz-checklist-status { .viz-checklist-status {
@include text-hide(); @extend .text-hide;
@include size(100%,($baseline/4)); @include size(100%,($baseline/4));
position: relative; position: relative;
display: block; display: block;
...@@ -40,7 +40,7 @@ body.course.checklists { ...@@ -40,7 +40,7 @@ body.course.checklists {
background: $green; background: $green;
.int { .int {
@include text-sr(); @extend .text-sr;
} }
} }
} }
...@@ -83,7 +83,7 @@ body.course.checklists { ...@@ -83,7 +83,7 @@ body.course.checklists {
} }
.checklist-status { .checklist-status {
@include font-size(13); @extend .t-copy-sub1;
width: flex-grid(3, 9); width: flex-grid(3, 9);
float: right; float: right;
margin-top: ($baseline/2); margin-top: ($baseline/2);
...@@ -100,7 +100,7 @@ body.course.checklists { ...@@ -100,7 +100,7 @@ body.course.checklists {
} }
.status-count { .status-count {
@include font-size(16); @extend .t-copy-base;
margin-left: ($baseline/4); margin-left: ($baseline/4);
margin-right: ($baseline/4); margin-right: ($baseline/4);
color: $gray-d3; color: $gray-d3;
...@@ -108,7 +108,7 @@ body.course.checklists { ...@@ -108,7 +108,7 @@ body.course.checklists {
} }
.status-amount { .status-amount {
@include font-size(16); @extend .t-copy-base;
margin-left: ($baseline/4); margin-left: ($baseline/4);
color: $gray-d3; color: $gray-d3;
font-weight: 600; font-weight: 600;
...@@ -138,8 +138,8 @@ body.course.checklists { ...@@ -138,8 +138,8 @@ body.course.checklists {
} }
.action-secondary { .action-secondary {
@include font-size(14);
@include grey-button(); @include grey-button();
@extend .t-action3;
font-weight: 400; font-weight: 400;
float: right; float: right;
...@@ -247,14 +247,14 @@ body.course.checklists { ...@@ -247,14 +247,14 @@ body.course.checklists {
} }
.task-description { .task-description {
@extend .t-copy-sub1;
@include transition(color .15s .25s ease-in-out); @include transition(color .15s .25s ease-in-out);
@include font-size(14);
color: $gray-l2; color: $gray-l2;
} }
.task-support { .task-support {
@extend .t-copy-sub2;
@include transition(opacity .15s .25s ease-in-out); @include transition(opacity .15s .25s ease-in-out);
@include font-size(12);
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
} }
...@@ -274,14 +274,14 @@ body.course.checklists { ...@@ -274,14 +274,14 @@ body.course.checklists {
.action-primary { .action-primary {
@include blue-button; @include blue-button;
@extend .t-action4;
@include transition(all .15s); @include transition(all .15s);
@include font-size(12);
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
} }
.action-secondary { .action-secondary {
@include font-size(13); @extend .t-action4;
margin-top: ($baseline/2); margin-top: ($baseline/2);
} }
} }
...@@ -322,7 +322,7 @@ body.course.checklists { ...@@ -322,7 +322,7 @@ body.course.checklists {
.action-primary { .action-primary {
@include grey-button; @include grey-button;
@include font-size(12); @extend .t-action4;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
} }
......
...@@ -18,8 +18,8 @@ body.index { ...@@ -18,8 +18,8 @@ body.index {
} }
.content { .content {
@extend .t-copy-base;
@include clearfix(); @include clearfix();
@include font-size(16);
max-width: $fg-max-width; max-width: $fg-max-width;
min-width: $fg-min-width; min-width: $fg-min-width;
width: flex-grid(12); width: flex-grid(12);
...@@ -62,7 +62,7 @@ body.index { ...@@ -62,7 +62,7 @@ body.index {
color: $white; color: $white;
h1 { h1 {
@include font-size(52); @extend .t-title2;
float: none; float: none;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
border-bottom: 1px solid $blue-l1; border-bottom: 1px solid $blue-l1;
...@@ -72,7 +72,7 @@ body.index { ...@@ -72,7 +72,7 @@ body.index {
} }
.logo { .logo {
@include text-hide(); @extend .text-hide;
position: relative; position: relative;
top: 3px; top: 3px;
display: inline-block; display: inline-block;
...@@ -83,7 +83,7 @@ body.index { ...@@ -83,7 +83,7 @@ body.index {
} }
.tagline { .tagline {
@include font-size(24); @extend .t-title4;
margin: 0; margin: 0;
color: $blue-l3; color: $blue-l3;
} }
...@@ -198,13 +198,13 @@ body.index { ...@@ -198,13 +198,13 @@ body.index {
margin-top: -($baseline/4); margin-top: -($baseline/4);
h3 { h3 {
@extend .t-title4;
margin: 0 0 ($baseline/2) 0; margin: 0 0 ($baseline/2) 0;
@include font-size(24);
font-weight: 600; font-weight: 600;
} }
> p { > p {
@include font-size(18); @extend .t-copy-lead1;
color: $gray-d1; color: $gray-d1;
} }
...@@ -214,8 +214,8 @@ body.index { ...@@ -214,8 +214,8 @@ body.index {
} }
.list-proofpoints { .list-proofpoints {
@extend .t-copy-sub1;
@include clearfix(); @include clearfix();
@include font-size(14);
width: flex-grid(9, 9); width: flex-grid(9, 9);
margin: ($baseline*1.5) 0 0 0; margin: ($baseline*1.5) 0 0 0;
...@@ -233,7 +233,7 @@ body.index { ...@@ -233,7 +233,7 @@ body.index {
color: $gray-l1; color: $gray-l1;
.title { .title {
@include font-size(16); @extend .t-copy-base;
margin: 0 0 ($baseline/4) 0; margin: 0 0 ($baseline/4) 0;
font-weight: 500; font-weight: 500;
color: $gray-d3; color: $gray-d3;
...@@ -322,23 +322,23 @@ body.index { ...@@ -322,23 +322,23 @@ body.index {
display: block; display: block;
width: 100%; width: 100%;
text-align: center; text-align: center;
}
.action-primary { &.action-primary {
@extend .t-action1;
@include blue-button; @include blue-button;
@include transition(all .15s); @include transition(all .15s);
@include font-size(18);
padding: ($baseline*0.75) ($baseline/2); padding: ($baseline*0.75) ($baseline/2);
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
text-transform: uppercase; text-transform: uppercase;
} }
.action-secondary { &.action-secondary {
@include font-size(14); @extend .t-action3;
margin-top: ($baseline/2); margin-top: ($baseline/2);
} }
} }
} }
} }
}
} }
...@@ -29,6 +29,7 @@ body.course.outline { ...@@ -29,6 +29,7 @@ body.course.outline {
width: 100px; width: 100px;
.status-label { .status-label {
@include font-size(12);
position: absolute; position: absolute;
top: 2px; top: 2px;
right: -5px; right: -5px;
...@@ -38,7 +39,6 @@ body.course.outline { ...@@ -38,7 +39,6 @@ body.course.outline {
@include border-radius(3px); @include border-radius(3px);
color: $lightGrey; color: $lightGrey;
text-align: right; text-align: right;
font-size: 12px;
font-weight: bold; font-weight: bold;
line-height: 16px; line-height: 16px;
} }
...@@ -57,6 +57,10 @@ body.course.outline { ...@@ -57,6 +57,10 @@ body.course.outline {
} }
.menu { .menu {
@include font-size(12);
@include border-radius(4px);
@include box-shadow(0 1px 2px rgba(0, 0, 0, .2));
@include transition(opacity .15s);
z-index: 1; z-index: 1;
display: none; display: none;
opacity: 0.0; opacity: 0.0;
...@@ -67,10 +71,6 @@ body.course.outline { ...@@ -67,10 +71,6 @@ body.course.outline {
padding: 8px 12px; padding: 8px 12px;
background: $white; background: $white;
border: 1px solid $mediumGrey; border: 1px solid $mediumGrey;
font-size: 12px;
@include border-radius(4px);
@include box-shadow(0 1px 2px rgba(0, 0, 0, .2));
@include transition(opacity .15s);
li { li {
...@@ -167,7 +167,7 @@ body.course.outline { ...@@ -167,7 +167,7 @@ body.course.outline {
text-align: right; text-align: right;
.published-status { .published-status {
font-size: 12px; @include font-size(12);
margin-right: 15px; margin-right: 15px;
strong { strong {
...@@ -185,19 +185,19 @@ body.course.outline { ...@@ -185,19 +185,19 @@ body.course.outline {
.schedule-button, .schedule-button,
.edit-button { .edit-button {
font-size: 11px; @include font-size(11);
padding: 3px 15px 5px; padding: 3px 15px 5px;
} }
} }
.datepair .date, .datepair .date,
.datepair .time { .datepair .time {
@include font-size(13);
@include box-shadow(none);
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
border: none; border: none;
background: none; background: none;
@include box-shadow(none);
font-size: 13px;
font-weight: bold; font-weight: bold;
color: $blue; color: $blue;
cursor: pointer; cursor: pointer;
...@@ -231,10 +231,10 @@ body.course.outline { ...@@ -231,10 +231,10 @@ body.course.outline {
@include clearfix(); @include clearfix();
.section-name { .section-name {
@include font-size(19);
float: left; float: left;
margin-right: 10px; margin-right: 10px;
width: 350px; width: 350px;
font-size: 19px;
font-weight: bold; font-weight: bold;
color: $blue; color: $blue;
} }
...@@ -254,7 +254,7 @@ body.course.outline { ...@@ -254,7 +254,7 @@ body.course.outline {
background: $white; background: $white;
input { input {
font-size: 16px; @include font-size(16);
} }
.save-button { .save-button {
...@@ -275,7 +275,7 @@ body.course.outline { ...@@ -275,7 +275,7 @@ body.course.outline {
background: $lightGrey; background: $lightGrey;
.published-status { .published-status {
font-size: 12px; @include font-size(12);
margin-right: 15px; margin-right: 15px;
strong { strong {
...@@ -293,9 +293,8 @@ body.course.outline { ...@@ -293,9 +293,8 @@ body.course.outline {
.schedule-button, .schedule-button,
.edit-button { .edit-button {
font-size: 11px; @include font-size(11);
padding: 3px 15px 5px; padding: 0 15px 2px 15px;
} }
} }
...@@ -306,17 +305,17 @@ body.course.outline { ...@@ -306,17 +305,17 @@ body.course.outline {
width: 145px; width: 145px;
.status-label { .status-label {
@include font-size(12);
@include border-radius(3px);
position: absolute; position: absolute;
top: 0; top: 0;
right: 2px; right: 2px;
display: none; display: none;
width: 100px; width: 100px;
padding: 10px 35px 10px 10px; padding: 10px 35px 10px 10px;
@include border-radius(3px);
background: $lightGrey; background: $lightGrey;
color: $lightGrey; color: $lightGrey;
text-align: right; text-align: right;
font-size: 12px;
font-weight: bold; font-weight: bold;
line-height: 16px; line-height: 16px;
} }
...@@ -335,6 +334,11 @@ body.course.outline { ...@@ -335,6 +334,11 @@ body.course.outline {
} }
.menu { .menu {
@include font-size(12);
@include border-radius(4px);
@include box-shadow(0 1px 2px rgba(0, 0, 0, .2));
@include transition(opacity .15s);
@include transition(display .15s);
z-index: 1; z-index: 1;
display: none; display: none;
opacity: 0.0; opacity: 0.0;
...@@ -345,11 +349,7 @@ body.course.outline { ...@@ -345,11 +349,7 @@ body.course.outline {
padding: 8px 12px; padding: 8px 12px;
background: $white; background: $white;
border: 1px solid $mediumGrey; border: 1px solid $mediumGrey;
font-size: 12px;
@include border-radius(4px);
@include box-shadow(0 1px 2px rgba(0, 0, 0, .2));
@include transition(opacity .15s);
@include transition(display .15s);
li { li {
...@@ -422,7 +422,7 @@ body.course.outline { ...@@ -422,7 +422,7 @@ body.course.outline {
.expand-collapse-icon { .expand-collapse-icon {
float: left; float: left;
margin: 29px 6px 16px 16px; margin: 25px 6px 16px 16px;
@include transition(none); @include transition(none);
&.expand { &.expand {
...@@ -440,7 +440,7 @@ body.course.outline { ...@@ -440,7 +440,7 @@ body.course.outline {
} }
h3 { h3 {
font-size: 19px; @include font-size(19);
font-weight: 700; font-weight: 700;
color: $blue; color: $blue;
} }
...@@ -460,7 +460,7 @@ body.course.outline { ...@@ -460,7 +460,7 @@ body.course.outline {
.section-name-edit { .section-name-edit {
input { input {
font-size: 16px; @include font-size(16);
} }
.save-button { .save-button {
...@@ -476,7 +476,7 @@ body.course.outline { ...@@ -476,7 +476,7 @@ body.course.outline {
} }
h4 { h4 {
font-size: 12px; @include font-size(12);
color: #878e9d; color: #878e9d;
strong { strong {
...@@ -502,8 +502,8 @@ body.course.outline { ...@@ -502,8 +502,8 @@ body.course.outline {
&.new-section { &.new-section {
header { header {
height: auto;
@include clearfix(); @include clearfix();
height: auto;
} }
.expand-collapse-icon { .expand-collapse-icon {
...@@ -522,12 +522,11 @@ body.course.outline { ...@@ -522,12 +522,11 @@ body.course.outline {
} }
.toggle-button-sections { .toggle-button-sections {
@include font-size(12);
display: none; display: none;
position: relative; position: relative;
float: right; float: right;
margin-top: 10px; margin-top: ($baseline/4);
font-size: 13px;
color: $darkGrey; color: $darkGrey;
&.is-shown { &.is-shown {
...@@ -535,13 +534,13 @@ body.course.outline { ...@@ -535,13 +534,13 @@ body.course.outline {
} }
.ss-icon { .ss-icon {
@include font-size(11);
@include border-radius(20px); @include border-radius(20px);
position: relative; position: relative;
top: -1px; top: -1px;
display: inline-block; display: inline-block;
margin-right: 2px; margin-right: 2px;
line-height: 5px; line-height: 5px;
font-size: 11px;
} }
.label { .label {
...@@ -599,7 +598,7 @@ body.course.outline { ...@@ -599,7 +598,7 @@ body.course.outline {
} }
h3 { h3 {
font-size: 34px; @include font-size(34);
font-weight: 300; font-weight: 300;
} }
...@@ -625,16 +624,16 @@ body.course.outline { ...@@ -625,16 +624,16 @@ body.course.outline {
} }
label { label {
@include font-size(14); @extend .t-copy-sub1;
margin-bottom: ($baseline/4); margin-bottom: ($baseline/4);
} }
} }
} }
.description { .description {
@include font-size(14);
float: left; float: left;
margin-top: 30px; margin-top: 30px;
font-size: 14px;
line-height: 20px; line-height: 20px;
width: 100%; width: 100%;
} }
...@@ -645,7 +644,7 @@ body.course.outline { ...@@ -645,7 +644,7 @@ body.course.outline {
.start-date, .start-date,
.start-time { .start-time {
font-size: 19px; @include font-size(19);
} }
.save-button { .save-button {
...@@ -659,14 +658,14 @@ body.course.outline { ...@@ -659,14 +658,14 @@ body.course.outline {
.save-button, .save-button,
.cancel-button { .cancel-button {
font-size: 16px; @include font-size(16);
} }
} }
.collapse-all-button { .collapse-all-button {
@include font-size(13);
float: right; float: right;
margin-top: 10px; margin-top: 10px;
font-size: 13px;
color: $darkGrey; color: $darkGrey;
} }
......
...@@ -66,7 +66,7 @@ body.course.settings { ...@@ -66,7 +66,7 @@ body.course.settings {
} }
.tip { .tip {
@include font-size(13); @extend .t-copy-sub2;
width: flex-grid(5, 9); width: flex-grid(5, 9);
float: right; float: right;
margin-top: ($baseline/2); margin-top: ($baseline/2);
...@@ -86,20 +86,20 @@ body.course.settings { ...@@ -86,20 +86,20 @@ body.course.settings {
// in form -UI hints/tips/messages // in form -UI hints/tips/messages
.instructions { .instructions {
@include font-size(14); @extend .t-copy-sub1;
margin: 0 0 $baseline 0; margin: 0 0 $baseline 0;
} }
.tip { .tip {
@extend .t-copy-sub2;
@include transition(color, 0.15s, ease-in-out); @include transition(color, 0.15s, ease-in-out);
@include font-size(13);
display: block; display: block;
margin-top: ($baseline/4); margin-top: ($baseline/4);
color: $gray-l3; color: $gray-l3;
} }
.message-error { .message-error {
@include font-size(13); @extend .t-copy-sub1;
display: block; display: block;
margin-top: ($baseline/4); margin-top: ($baseline/4);
margin-bottom: ($baseline/2); margin-bottom: ($baseline/2);
...@@ -109,12 +109,13 @@ body.course.settings { ...@@ -109,12 +109,13 @@ body.course.settings {
// buttons // buttons
.remove-item { .remove-item {
@include white-button; @include white-button;
@include font-size(13); @extend .t-action-3;
font-weight: 400; font-weight: 400;
} }
.new-button { .new-button {
@include font-size(13); // @extend .t-action-3; - bad buttons won't render this properly
@include font-size(14);
} }
// form basics // form basics
...@@ -158,8 +159,8 @@ body.course.settings { ...@@ -158,8 +159,8 @@ body.course.settings {
} }
input, textarea { input, textarea {
@extend .t-copy-base;
@include placeholder($gray-l4); @include placeholder($gray-l4);
@include font-size(16);
@include size(100%,100%); @include size(100%,100%);
padding: ($baseline/2); padding: ($baseline/2);
...@@ -324,7 +325,7 @@ body.course.settings { ...@@ -324,7 +325,7 @@ body.course.settings {
.action-primary { .action-primary {
@include blue-button(); @include blue-button();
@include font-size(13); @extend .t-action-3;
font-weight: 600; font-weight: 600;
.icon { .icon {
...@@ -747,7 +748,7 @@ body.course.settings { ...@@ -747,7 +748,7 @@ body.course.settings {
// specific to code mirror instance in JSON policy editing, need to sync up with other similar code mirror UIs // specific to code mirror instance in JSON policy editing, need to sync up with other similar code mirror UIs
.CodeMirror { .CodeMirror {
@include font-size(16); @extend .t-copy-base;
@include box-sizing(border-box); @include box-sizing(border-box);
@include box-shadow(0 1px 2px rgba(0, 0, 0, .1) inset); @include box-shadow(0 1px 2px rgba(0, 0, 0, .1) inset);
@include linear-gradient($lightGrey, tint($lightGrey, 90%)); @include linear-gradient($lightGrey, tint($lightGrey, 90%));
......
...@@ -123,7 +123,7 @@ body.course.static-pages { ...@@ -123,7 +123,7 @@ body.course.static-pages {
.component-actions { .component-actions {
position: absolute; position: absolute;
top: 26px; top: 20px;
right: 44px; right: 44px;
} }
} }
......
...@@ -35,10 +35,10 @@ ...@@ -35,10 +35,10 @@
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Course Content</span> <small class="subtitle">Course Content</small>
<h1 class="title-1">Files &amp; Uploads</h1> <span class="sr">&gt; </span>Files &amp; Uploads
</div> </h1>
<nav class="nav-actions"> <nav class="nav-actions">
<h3 class="sr">Page Actions</h3> <h3 class="sr">Page Actions</h3>
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Tools</span> <small class="subtitle">Tools</small>
<h1 class="title-1">Course Checklists</h1> <span class="sr">&gt; </span>Course Checklists
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
$(document).ready(function(){ $(document).ready(function(){
var course_updates = new CMS.Models.CourseUpdateCollection(); var course_updates = new CMS.Models.CourseUpdateCollection();
course_updates.urlbase = '${url_base}'; course_updates.urlbase = '${url_base}';
course_updates.fetch(); course_updates.fetch({reset: true});
var course_handouts = new CMS.Models.ModuleInfo({ var course_handouts = new CMS.Models.ModuleInfo({
id: '${handouts_location}' id: '${handouts_location}'
...@@ -44,10 +44,10 @@ ...@@ -44,10 +44,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Course Content</span> <small class="subtitle">Course Content</small>
<h1 class="title-1">Course Updates</h1> <span class="sr">&gt; </span>Course Updates
</div> </h1>
<nav class="nav-actions"> <nav class="nav-actions">
<h3 class="sr">Page Actions</h3> <h3 class="sr">Page Actions</h3>
......
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Course Content</span> <small class="subtitle">Course Content</small>
<h1 class="title-1">Static Pages</h1> <span class="sr">&gt; </span>Static Pages
</div> </h1>
<nav class="nav-actions"> <nav class="nav-actions">
<h3 class="sr">Page Actions</h3> <h3 class="sr">Page Actions</h3>
......
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</%block> </%block>
<%block name="jsextra"> <%block name="jsextra">
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-subtitle"> <header class="mast has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Tools</span> <small class="subtitle">Tools</small>
<h1 class="title-1">Course Export</h1> <span class="sr">&gt; </span>Course Export
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-subtitle"> <header class="mast has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Tools</span> <small class="subtitle">Tools</small>
<h1 class="title-1">Course Import</h1> <span class="sr">&gt; </span>Course Import
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -37,9 +37,7 @@ ...@@ -37,9 +37,7 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions"> <header class="mast has-actions">
<div class="title"> <h1 class="page-header">${_("My Courses")}</h1>
<h1 class="title-1">${_("My Courses")}</h1>
</div>
% if user.is_active: % if user.is_active:
<nav class="nav-actions"> <nav class="nav-actions">
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Course Settings</span> <small class="subtitle">Course Settings</small>
<h1 class="title-1">Course Team</h1> <span class="sr">&gt; </span>Course Team
</div> </h1>
<nav class="nav-actions"> <nav class="nav-actions">
<h3 class="sr">Page Actions</h3> <h3 class="sr">Page Actions</h3>
......
...@@ -106,10 +106,10 @@ ...@@ -106,10 +106,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Course Content</span> <small class="subtitle">Course Content</small>
<h1 class="title-1">Course Outline</h1> <span class="sr">&gt; </span>Course Outline
</div> </h1>
<nav class="nav-actions"> <nav class="nav-actions">
<h3 class="sr">Page Actions</h3> <h3 class="sr">Page Actions</h3>
......
...@@ -32,15 +32,15 @@ from contentstore import utils ...@@ -32,15 +32,15 @@ from contentstore import utils
}); });
var model = new CMS.Models.Settings.CourseDetails(); var model = new CMS.Models.Settings.CourseDetails();
model.urlRoot = '${details_url}'; model.urlRoot = '${details_url}';
model.fetch({success : model.fetch({
function(model) { success: function(model) {
var editor = new CMS.Views.Settings.Details({ var editor = new CMS.Views.Settings.Details({
el: $('.settings-details'), el: $('.settings-details'),
model: model model: model
}); });
editor.render(); editor.render();
} },
reset: true
}); });
}); });
...@@ -50,10 +50,10 @@ from contentstore import utils ...@@ -50,10 +50,10 @@ from contentstore import utils
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-subtitle"> <header class="mast has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Settings</span> <small class="subtitle">Settings</small>
<h1 class="title-1">Schedule &amp; Details</h1> <span class="sr">&gt; </span>Schedule &amp; Details
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -44,10 +44,10 @@ editor.render(); ...@@ -44,10 +44,10 @@ editor.render();
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-subtitle"> <header class="mast has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Settings</span> <small class="subtitle">Settings</small>
<h1 class="title-1">Advanced Settings</h1> <span class="sr">&gt; </span>Advanced Settings
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -41,10 +41,10 @@ from contentstore import utils ...@@ -41,10 +41,10 @@ from contentstore import utils
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-subtitle"> <header class="mast has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">Settings</span> <small class="subtitle">Settings</small>
<h1 class="title-1">Grading</h1> <span class="sr">&gt; </span>Grading
</div> </h1>
</header> </header>
</div> </div>
......
...@@ -82,10 +82,10 @@ ...@@ -82,10 +82,10 @@
<%block name="content"> <%block name="content">
<div class="wrapper-mast wrapper"> <div class="wrapper-mast wrapper">
<header class="mast has-actions has-subtitle"> <header class="mast has-actions has-subtitle">
<div class="title"> <h1 class="page-header">
<span class="title-sub">UX Design</span> <small class="subtitle">UX Design</small>
<h1 class="title-1">System Notifications</h1> <span class="sr">&gt; </span>System Notifications
</div> </h1>
</header> </header>
</div> </div>
...@@ -134,10 +134,6 @@ ...@@ -134,10 +134,6 @@
<a href="#notification-changesMade" class="hide-notification">Hide Changes Made (used in Advanced Settings)</a> <a href="#notification-changesMade" class="hide-notification">Hide Changes Made (used in Advanced Settings)</a>
</li> </li>
<li> <li>
<a href="#notification-change" class="show-notification">Show Change Warning</a>
<a href="#notification-change" class="hide-notification">Hide Change Warning</a>
</li>
<li>
<a href="#notification-version" class="show-notification">Show New Version Warning</a> <a href="#notification-version" class="show-notification">Show New Version Warning</a>
<a href="#notification-version" class="hide-notification">Hide New Version Warning</a> <a href="#notification-version" class="hide-notification">Hide New Version Warning</a>
</li> </li>
...@@ -156,10 +152,6 @@ ...@@ -156,10 +152,6 @@
<a href="#notification-help" class="show-notification">Show Help</a> <a href="#notification-help" class="show-notification">Show Help</a>
<a href="#notification-help" class="hide-notification">Hide Help</a> <a href="#notification-help" class="hide-notification">Hide Help</a>
</li> </li>
<li>
<a href="#notification-threeActions" class="show-notification">Show Notification with three actions</a>
<a href="#notification-threeActions" class="hide-notification">Hide Notification with three actions</a>
</li>
</ul> </ul>
</section> </section>
...@@ -403,57 +395,6 @@ ...@@ -403,57 +395,6 @@
<%block name="view_notifications"> <%block name="view_notifications">
<!-- notification: change has been made and a save is needed --> <!-- notification: change has been made and a save is needed -->
<div class="wrapper wrapper-notification wrapper-notification-change" aria-hidden="true" role="dialog" aria-labelledby="notification-change-title" aria-describedby="notification-change-description" id="notification-change">
<div class="notification change has-actions">
<i class="ss-icon ss-symbolicons-block icon icon-change">&#x1F4DD;</i>
<div class="copy">
<h2 class="title title-3" id="notification-change-title">You've Made Some Changes</h2>
<p class="message" id="notification-change-description">Your changes will not take effect until you <strong>save your progress</strong>.</p>
</div>
<nav class="nav-actions">
<h3 class="sr">Notification Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class="action-primary">Save Changes</a>
</li>
<li class="nav-item">
<a href="#" class="action-secondary">Don't Save</a>
</li>
</ul>
</nav>
</div>
</div>
<!-- notification: three actions example -->
<div class="wrapper wrapper-notification wrapper-notification-change" aria-hidden="true" role="dialog" aria-labelledby="notification-threeActions-title" aria-describedby="notification-threeActions-description" id="notification-threeActions">
<div class="notification change has-actions">
<i class="ss-icon ss-symbolicons-block icon icon-change">&#x1F4DD;</i>
<div class="copy">
<h2 class="title title-3" id="notification-threeActions-title">You've Made Some Changes</h2>
<p class="message" id="notification-threeActions-description">Your changes will not take effect until you <strong>save your progress</strong>.</p>
</div>
<nav class="nav-actions">
<h3 class="sr">Notification Actions</h3>
<ul>
<li class="nav-item">
<a href="#" class="action-primary">Save Changes</a>
</li>
<li class="nav-item">
<a href="#" class="action-secondary">Don't Save</a>
</li>
<li class="nav-item">
<a href="#" class="action-secondary">Do something else</a>
</li>
</ul>
</nav>
</div>
</div>
<!-- notification: change has been made and a save is needed -->
<div class="wrapper wrapper-notification wrapper-notification-warning" aria-hidden="true" role="dialog" aria-labelledby="notification-changesMade-title" aria-describedby="notification-changesMade-description" id="notification-changesMade"> <div class="wrapper wrapper-notification wrapper-notification-warning" aria-hidden="true" role="dialog" aria-labelledby="notification-changesMade-title" aria-describedby="notification-changesMade-description" id="notification-changesMade">
<div class="notification warning has-actions"> <div class="notification warning has-actions">
<i class="ss-icon ss-symbolicons-block icon icon-warning">&#x26A0;</i> <i class="ss-icon ss-symbolicons-block icon icon-warning">&#x26A0;</i>
......
...@@ -161,7 +161,7 @@ def submit_feedback_via_zendesk(request): ...@@ -161,7 +161,7 @@ def submit_feedback_via_zendesk(request):
try: try:
ticket_id = zendesk_api.create_ticket(new_ticket) ticket_id = zendesk_api.create_ticket(new_ticket)
except zendesk.ZendeskError as err: except zendesk.ZendeskError as err:
log.error("%s", str(err)) log.error("Error creating Zendesk ticket: %s", str(err))
return HttpResponse(status=500) return HttpResponse(status=500)
# Additional information is provided as a private update so the information # Additional information is provided as a private update so the information
...@@ -170,7 +170,7 @@ def submit_feedback_via_zendesk(request): ...@@ -170,7 +170,7 @@ def submit_feedback_via_zendesk(request):
try: try:
zendesk_api.update_ticket(ticket_id, ticket_update) zendesk_api.update_ticket(ticket_id, ticket_update)
except zendesk.ZendeskError as err: except zendesk.ZendeskError as err:
log.error("%s", str(err)) log.error("Error updating Zendesk ticket: %s", str(err))
# The update is not strictly necessary, so do not indicate failure to the user # The update is not strictly necessary, so do not indicate failure to the user
pass pass
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
# File: courseware/capa/responsetypes.py # File: courseware/capa/responsetypes.py
# #
''' '''
Problem response evaluation. Handles checking of student responses, of a variety of types. Problem response evaluation. Handles checking of student responses,
of a variety of types.
Used by capa_problem.py Used by capa_problem.py
''' '''
...@@ -35,7 +36,7 @@ from datetime import datetime ...@@ -35,7 +36,7 @@ from datetime import datetime
from .util import * from .util import *
from lxml import etree from lxml import etree
from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME? from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful Soup!!! FIXME?
import xqueue_interface import capa.xqueue_interface as xqueue_interface
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -300,7 +301,7 @@ class LoncapaResponse(object): ...@@ -300,7 +301,7 @@ class LoncapaResponse(object):
# response # response
aid = self.answer_ids[-1] aid = self.answer_ids[-1]
new_cmap.set_hint_and_mode(aid, hint_text, hintmode) new_cmap.set_hint_and_mode(aid, hint_text, hintmode)
log.debug('after hint: new_cmap = %s' % new_cmap) log.debug('after hint: new_cmap = %s', new_cmap)
@abc.abstractmethod @abc.abstractmethod
def get_score(self, student_answers): def get_score(self, student_answers):
...@@ -790,6 +791,10 @@ class OptionResponse(LoncapaResponse): ...@@ -790,6 +791,10 @@ class OptionResponse(LoncapaResponse):
class NumericalResponse(LoncapaResponse): class NumericalResponse(LoncapaResponse):
'''
This response type expects a number or formulaic expression that evaluates
to a number (e.g. `4+5/2^2`), and accepts with a tolerance.
'''
response_tag = 'numericalresponse' response_tag = 'numericalresponse'
hint_tag = 'numericalhint' hint_tag = 'numericalhint'
...@@ -806,12 +811,12 @@ class NumericalResponse(LoncapaResponse): ...@@ -806,12 +811,12 @@ class NumericalResponse(LoncapaResponse):
'//*[@id=$id]//responseparam[@type="tolerance"]/@default', '//*[@id=$id]//responseparam[@type="tolerance"]/@default',
id=xml.get('id'))[0] id=xml.get('id'))[0]
self.tolerance = contextualize_text(self.tolerance_xml, context) self.tolerance = contextualize_text(self.tolerance_xml, context)
except Exception: except IndexError: # xpath found an empty list, so (...)[0] is the error
self.tolerance = '0' self.tolerance = '0'
try: try:
self.answer_id = xml.xpath('//*[@id=$id]//textline/@id', self.answer_id = xml.xpath('//*[@id=$id]//textline/@id',
id=xml.get('id'))[0] id=xml.get('id'))[0]
except Exception: except IndexError: # Same as above
self.answer_id = None self.answer_id = None
def get_score(self, student_answers): def get_score(self, student_answers):
...@@ -836,7 +841,6 @@ class NumericalResponse(LoncapaResponse): ...@@ -836,7 +841,6 @@ class NumericalResponse(LoncapaResponse):
except: except:
# Use the traceback-preserving version of re-raising with a # Use the traceback-preserving version of re-raising with a
# different type # different type
import sys
type, value, traceback = sys.exc_info() type, value, traceback = sys.exc_info()
raise StudentInputError, ("Could not interpret '%s' as a number" % raise StudentInputError, ("Could not interpret '%s' as a number" %
...@@ -1869,8 +1873,6 @@ class FormulaResponse(LoncapaResponse): ...@@ -1869,8 +1873,6 @@ class FormulaResponse(LoncapaResponse):
log.debug('formularesponse: error %s in formula' % err) log.debug('formularesponse: error %s in formula' % err)
raise StudentInputError("Invalid input: Could not parse '%s' as a formula" % raise StudentInputError("Invalid input: Could not parse '%s' as a formula" %
cgi.escape(given)) cgi.escape(given))
if numpy.isnan(student_result) or numpy.isinf(student_result):
return "incorrect"
if not compare_with_tolerance(student_result, instructor_result, self.tolerance): if not compare_with_tolerance(student_result, instructor_result, self.tolerance):
return "incorrect" return "incorrect"
return "correct" return "correct"
......
...@@ -438,6 +438,43 @@ class FormulaResponseTest(ResponseTest): ...@@ -438,6 +438,43 @@ class FormulaResponseTest(ResponseTest):
self.assert_grade(problem, incorrect, 'incorrect', self.assert_grade(problem, incorrect, 'incorrect',
msg="Failed on function {0}; the given, incorrect answer was {1} but graded 'correct'".format(func, incorrect)) msg="Failed on function {0}; the given, incorrect answer was {1} but graded 'correct'".format(func, incorrect))
def test_grade_infinity(self):
# This resolves a bug where a problem with relative tolerance would
# pass with any arbitrarily large student answer.
sample_dict = {'x': (1, 2)}
# Test problem
problem = self.build_problem(sample_dict=sample_dict,
num_samples=10,
tolerance="1%",
answer="x")
# Expect such a large answer to be marked incorrect
input_formula = "x*1e999"
self.assert_grade(problem, input_formula, "incorrect")
# Expect such a large negative answer to be marked incorrect
input_formula = "-x*1e999"
self.assert_grade(problem, input_formula, "incorrect")
def test_grade_nan(self):
# Attempt to produce a value which causes the student's answer to be
# evaluated to nan. See if this is resolved correctly.
sample_dict = {'x': (1, 2)}
# Test problem
problem = self.build_problem(sample_dict=sample_dict,
num_samples=10,
tolerance="1%",
answer="x")
# Expect an incorrect answer (+ nan) to be marked incorrect
# Right now this evaluates to 'nan' for a given x (Python implementation-dependent)
input_formula = "10*x + 0*1e999"
self.assert_grade(problem, input_formula, "incorrect")
# Expect an correct answer (+ nan) to be marked incorrect
input_formula = "x + 0*1e999"
self.assert_grade(problem, input_formula, "incorrect")
class StringResponseTest(ResponseTest): class StringResponseTest(ResponseTest):
from response_xml_factory import StringResponseXMLFactory from response_xml_factory import StringResponseXMLFactory
...@@ -714,6 +751,30 @@ class NumericalResponseTest(ResponseTest): ...@@ -714,6 +751,30 @@ class NumericalResponseTest(ResponseTest):
incorrect_responses = ["", "4.5", "3.5", "0"] incorrect_responses = ["", "4.5", "3.5", "0"]
self.assert_multiple_grade(problem, correct_responses, incorrect_responses) self.assert_multiple_grade(problem, correct_responses, incorrect_responses)
def test_grade_infinity(self):
# This resolves a bug where a problem with relative tolerance would
# pass with any arbitrarily large student answer.
problem = self.build_problem(question_text="What is 2 + 2 approximately?",
explanation="The answer is 4",
answer=4,
tolerance="10%")
correct_responses = []
incorrect_responses = ["1e999", "-1e999"]
self.assert_multiple_grade(problem, correct_responses, incorrect_responses)
def test_grade_nan(self):
# Attempt to produce a value which causes the student's answer to be
# evaluated to nan. See if this is resolved correctly.
problem = self.build_problem(question_text="What is 2 + 2 approximately?",
explanation="The answer is 4",
answer=4,
tolerance="10%")
correct_responses = []
# Right now these evaluate to `nan`
# `4 + nan` should be incorrect
incorrect_responses = ["0*1e999", "4 + 0*1e999"]
self.assert_multiple_grade(problem, correct_responses, incorrect_responses)
def test_grade_with_script(self): def test_grade_with_script(self):
script_text = "computed_response = math.sqrt(4)" script_text = "computed_response = math.sqrt(4)"
problem = self.build_problem(question_text="What is sqrt(4)?", problem = self.build_problem(question_text="What is sqrt(4)?",
......
from .calc import evaluator, UndefinedVariable from .calc import evaluator, UndefinedVariable
from cmath import isinf
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# #
...@@ -20,6 +21,13 @@ def compare_with_tolerance(v1, v2, tol): ...@@ -20,6 +21,13 @@ def compare_with_tolerance(v1, v2, tol):
tolerance = tolerance_rel * max(abs(v1), abs(v2)) tolerance = tolerance_rel * max(abs(v1), abs(v2))
else: else:
tolerance = evaluator(dict(), dict(), tol) tolerance = evaluator(dict(), dict(), tol)
if isinf(v1) or isinf(v2):
# If an input is infinite, we can end up with `abs(v1-v2)` and
# `tolerance` both equal to infinity. Then, below we would have
# `inf <= inf` which is a fail. Instead, compare directly.
return v1 == v2
else:
return abs(v1 - v2) <= tolerance return abs(v1 - v2) <= tolerance
...@@ -51,7 +59,8 @@ def convert_files_to_filenames(answers): ...@@ -51,7 +59,8 @@ def convert_files_to_filenames(answers):
new_answers = dict() new_answers = dict()
for answer_id in answers.keys(): for answer_id in answers.keys():
answer = answers[answer_id] answer = answers[answer_id]
if is_list_of_files(answer): # Files are stored as a list, even if one file # Files are stored as a list, even if one file
if is_list_of_files(answer):
new_answers[answer_id] = [f.name for f in answer] new_answers[answer_id] = [f.name for f in answer]
else: else:
new_answers[answer_id] = answers[answer_id] new_answers[answer_id] = answers[answer_id]
......
...@@ -165,7 +165,7 @@ define('WordCloudMain', ['logme'], function (logme) { ...@@ -165,7 +165,7 @@ define('WordCloudMain', ['logme'], function (logme) {
d3.layout.cloud().size([this.width, this.height]) d3.layout.cloud().size([this.width, this.height])
.words(words) .words(words)
.rotate(function () { .rotate(function () {
return Math.floor((Math.random() * 2) * 90); return Math.floor((Math.random() * 2)) * 90;
}) })
.font('Impact') .font('Impact')
.fontSize(function (d) { .fontSize(function (d) {
......
...@@ -11,6 +11,7 @@ import logging ...@@ -11,6 +11,7 @@ import logging
from pkg_resources import resource_string from pkg_resources import resource_string
from xmodule.raw_module import RawDescriptor from xmodule.raw_module import RawDescriptor
from xmodule.editing_module import MetadataOnlyEditingDescriptor
from xmodule.x_module import XModule from xmodule.x_module import XModule
from xblock.core import Scope, String, Object, Boolean, List, Integer from xblock.core import Scope, String, Object, Boolean, List, Integer
...@@ -19,8 +20,13 @@ log = logging.getLogger(__name__) ...@@ -19,8 +20,13 @@ log = logging.getLogger(__name__)
def pretty_bool(value): def pretty_bool(value):
BOOL_DICT = [True, "True", "true", "T", "t", "1"] """Check value for possible `True` value.
return value in BOOL_DICT
Using this function we can manage different type of Boolean value
in xml files.
"""
bool_dict = [True, "True", "true", "T", "t", "1"]
return value in bool_dict
class WordCloudFields(object): class WordCloudFields(object):
...@@ -227,9 +233,8 @@ class WordCloudModule(WordCloudFields, XModule): ...@@ -227,9 +233,8 @@ class WordCloudModule(WordCloudFields, XModule):
return self.content return self.content
class WordCloudDescriptor(WordCloudFields, RawDescriptor): class WordCloudDescriptor(MetadataOnlyEditingDescriptor, RawDescriptor, WordCloudFields):
"""Descriptor for WordCloud Xmodule.""" """Descriptor for WordCloud Xmodule."""
module_class = WordCloudModule module_class = WordCloudModule
template_dir_name = 'word_cloud' template_dir_name = 'word_cloud'
stores_state = True stores_state = True
mako_template = "widgets/raw-edit.html"
// studio - utilities - mixins and extends // studio - utilities - mixins and extends
// ==================== // ====================
// font-sizing // mixins - font sizing
@function em($pxval, $base: 16) {
@return #{$pxval / $base}em;
}
@mixin font-size($sizeValue: 16){ @mixin font-size($sizeValue: 16){
font-size: $sizeValue + px; font-size: $sizeValue + px;
font-size: ($sizeValue/10) + rem; font-size: ($sizeValue/10) + rem;
} }
// ==================== // mixins - line height
@mixin lh($fontSize: auto){
// line-height line-height: ($fontSize*1.48) + px;
@function lh($amount: 1) { line-height: (($fontSize/10)*1.48) + rem;
@return $body-line-height * $amount;
}
// ====================
// image-replacement hidden text
@mixin text-hide() {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
// hidden elems - screenreaders
@mixin text-sr() {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
// ====================
// vertical and horizontal centering
@mixin vertically-and-horizontally-centered ($height, $width) {
left: 50%;
margin-left: -$width / 2;
//margin-top: -$height / 2;
min-height: $height;
min-width: $width;
position: absolute;
top: 150px;
} }
// ==================== // ====================
// sizing // mixins - sizing
@mixin size($width: $baseline, $height: $baseline) { @mixin size($width: $baseline, $height: $baseline) {
height: $height; height: $height;
width: $width; width: $width;
} }
// mixins - sizing
@mixin square($size: $baseline) { @mixin square($size: $baseline) {
@include size($size); @include size($size);
} }
// ==================== // ====================
// placeholder styling // mixins - placeholder styling
@mixin placeholder($color) { @mixin placeholder($color) {
:-moz-placeholder { :-moz-placeholder {
color: $color; color: $color;
...@@ -81,102 +44,148 @@ ...@@ -81,102 +44,148 @@
// ==================== // ====================
// extends - visual // extends - layout
.faded-hr-divider {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 0) 0%, // used for page/view-level wrappers (for centering/grids)
rgba(200,200,200, 1) 50%, .wrapper {
rgba(200,200,200, 0))); @include clearfix();
height: 1px; @include box-sizing(border-box);
width: 100%; width: 100%;
} }
.faded-hr-divider-medium { // removes list styling/spacing when using uls, ols for navigation and less content-centric cases
@include background-image(linear-gradient(180deg, rgba(240,240,240, 0) 0%, .no-list {
rgba(240,240,240, 1) 50%, list-style: none;
rgba(240,240,240, 0))); margin: 0;
height: 1px; padding: 0;
width: 100%; text-indent: 0;
li {
margin: 0;
padding: 0;
}
} }
.faded-hr-divider-light { // extends - image-replacement hidden text
@include background-image(linear-gradient(180deg, rgba(255,255,255, 0) 0%, .text-hide {
rgba(255,255,255, 0.8) 50%, text-indent: 100%;
rgba(255,255,255, 0))); white-space: nowrap;
height: 1px; overflow: hidden;
width: 100%;
} }
.faded-vertical-divider { // extends - hidden elems - screenreaders
@include background-image(linear-gradient(90deg, rgba(200,200,200, 0) 0%, .text-sr {
rgba(200,200,200, 1) 50%, border: 0;
rgba(200,200,200, 0))); clip: rect(0 0 0 0);
height: 100%; height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px; width: 1px;
} }
.faded-vertical-divider-light { // extends - wrapping
@include background-image(linear-gradient(90deg, rgba(255,255,255, 0) 0%, .text-wrap {
rgba(255,255,255, 0.6) 50%, text-wrap: wrap;
rgba(255,255,255, 0))); white-space: pre-wrap;
height: 100%; white-space: -moz-pre-wrap;
width: 1px; word-wrap: break-word;
} }
.vertical-divider { // extends - visual link
@extend .faded-vertical-divider; .fake-link {
position: relative; cursor: pointer;
}
&::after { // extends - functional disable
@extend .faded-vertical-divider-light; .disabled {
content: ""; pointer-events: none;
display: block; outline: none;
position: absolute;
left: 1px;
}
} }
.horizontal-divider { // extends - depth levels
border: none; .depth0 { z-index: 0; }
@extend .faded-hr-divider; .depth1 { z-index: 10; }
position: relative; .depth2 { z-index: 100; }
.depth3 { z-index: 1000; }
.depth4 { z-index: 10000; }
.depth5 { z-index: 100000; }
// ====================
// extends - buttons
.btn {
@include box-sizing(border-box);
@include transition(color 0.25s ease-in-out, border-color 0.25s ease-in-out, background 0.25s ease-in-out, box-shadow 0.25s ease-in-out);
display: inline-block;
cursor: pointer;
&:hover, &:active {
&::after {
@extend .faded-hr-divider-light;
content: "";
display: block;
position: absolute;
top: 1px;
} }
}
.fade-right-hr-divider { &.disabled, &[disabled] {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 0) 0%, cursor: default;
rgba(200,200,200, 1))); pointer-events: none;
border: none; opacity: 0.5;
}
.icon-inline {
display: inline-block;
vertical-align: middle;
margin-right: ($baseline/4);
}
} }
.fade-left-hr-divider { // pill button
@include background-image(linear-gradient(180deg, rgba(200,200,200, 1) 0%, .btn-pill {
rgba(200,200,200, 0))); @include border-radius($baseline/5);
border: none;
} }
// extends - ui .btn-rounded {
.window { @include border-radius($baseline/2);
@include clearfix();
@include border-radius(3px);
@include box-shadow(0 1px 1px $shadow-l1);
margin-bottom: $baseline;
border: 1px solid $gray-l2;
background: $white;
} }
.elem-d1 { // primary button
@include clearfix(); .btn-primary {
@include box-sizing(border-box); @extend .btn;
@extend .btn-pill;
padding:($baseline/2) $baseline;
border-width: 1px;
border-style: solid;
line-height: 1.5em;
text-align: center;
&:hover, &:active {
@include box-shadow(0 2px 1px $shadow-l1);
}
&.current, &.active {
@include box-shadow(inset 1px 1px 2px $shadow-d1);
&:hover, &:active {
@include box-shadow(inset 1px 1px 1px $shadow-d1);
}
}
} }
.elem-d2 { // secondary button
@include clearfix(); .btn-secondary {
@include box-sizing(border-box); @extend .btn;
@extend .btn-pill;
border-width: 1px;
border-style: solid;
padding:($baseline/2) $baseline;
background: transparent;
line-height: 1.5em;
text-align: center;
&:hover, &:active {
}
&.current, &.active {
}
} }
...@@ -18,12 +18,23 @@ The following attributes can be specified for this tag:: ...@@ -18,12 +18,23 @@ The following attributes can be specified for this tag::
[display_name| AUTOGENERATE] – Display name of xmodule. When this attribute is not defined - display name autogenerate with some hash. [display_name| AUTOGENERATE] – Display name of xmodule. When this attribute is not defined - display name autogenerate with some hash.
[num_inputs| 5] – Number of inputs. [num_inputs| 5] – Number of inputs.
[num_top_words| 250] – Number of max words, which will be displayed. [num_top_words| 250] – Number of max words, which will be displayed.
[display_student_percents| True] – Display usage percents for each word. [display_student_percents| True] – Display usage percents for each word on the same line together with words.
.. note::
Percent is shown always when mouse over the word in cloud.
.. note::
Possible answer for boolean type attributes:
True – "True", "true", "T", "t", "1"
False – "False", "false", "F", "f", "0"
.. note:: .. note::
If you want to use the same word cloud (the same storage of words), you must use the same display_name value. If you want to use the same word cloud (the same storage of words), you must use the same display_name value.
Code Example Code Example
============ ============
......
##
## requires >= 1.3.0 of the Jenkins git plugin
##
function github_status { function github_status {
gcli status create edx mitx $GIT_COMMIT \
if [[ ! ${GIT_URL} =~ git@github.com:([^/]+)/([^\.]+).git ]]; then
echo "Cannot parse Github org or repo from URL, using defaults."
ORG="edx"
REPO="mitx"
else
ORG=${BASH_REMATCH[1]}
REPO=${BASH_REMATCH[2]}
fi
gcli status create $ORG $REPO $GIT_COMMIT \
--params=$1 \ --params=$1 \
target_url:$BUILD_URL \ target_url:$BUILD_URL \
description:"Build #$BUILD_NUMBER is running" \ description:"Build #$BUILD_NUMBER is running" \
......
...@@ -4,7 +4,7 @@ set -e ...@@ -4,7 +4,7 @@ set -e
set -x set -x
function github_status { function github_status {
gcli status create edx mitx $GIT_COMMIT \ gcli status create edx edx-platform $GIT_COMMIT \
--params=$1 \ --params=$1 \
target_url:$BUILD_URL \ target_url:$BUILD_URL \
description:"Build #$BUILD_NUMBER $2" \ description:"Build #$BUILD_NUMBER $2" \
......
...@@ -33,6 +33,6 @@ PIPELINE_JS['spec'] = { ...@@ -33,6 +33,6 @@ PIPELINE_JS['spec'] = {
JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee' JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/static/coffee'
STATICFILES_DIRS.append(COMMON_ROOT / 'test' / 'phantom-jasmine' / 'lib') STATICFILES_DIRS.append(REPO_ROOT/'node_modules/phantom-jasmine/lib')
INSTALLED_APPS += ('django_jasmine', ) INSTALLED_APPS += ('django_jasmine', )
from dogapi import dog_stats_api
import json import json
import logging import logging
import requests import requests
...@@ -30,8 +31,14 @@ def merge_dict(dic1, dic2): ...@@ -30,8 +31,14 @@ def merge_dict(dic1, dic2):
def perform_request(method, url, data_or_params=None, *args, **kwargs): def perform_request(method, url, data_or_params=None, *args, **kwargs):
if data_or_params is None: if data_or_params is None:
data_or_params = {} data_or_params = {}
tags = [
"{k}:{v}".format(k=k, v=v)
for (k, v) in data_or_params.items() + [("method", method), ("url", url)]
if k != 'api_key'
]
data_or_params['api_key'] = settings.API_KEY data_or_params['api_key'] = settings.API_KEY
try: try:
with dog_stats_api.timer('comment_client.request.time', tags=tags):
if method in ['post', 'put', 'patch']: if method in ['post', 'put', 'patch']:
response = requests.request(method, url, data=data_or_params, timeout=5) response = requests.request(method, url, data=data_or_params, timeout=5)
else: else:
......
...@@ -61,10 +61,12 @@ urlpatterns = ('', # nopep8 ...@@ -61,10 +61,12 @@ urlpatterns = ('', # nopep8
url(r'^heartbeat$', include('heartbeat.urls')), url(r'^heartbeat$', include('heartbeat.urls')),
##
## Only universities without courses should be included here. If
## courses exist, the dynamic profile rule below should win.
##
url(r'^(?i)university_profile/WellesleyX$', 'courseware.views.static_university_profile', url(r'^(?i)university_profile/WellesleyX$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'WellesleyX'}), name="static_university_profile", kwargs={'org_id': 'WellesleyX'}),
url(r'^(?i)university_profile/GeorgetownX$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'GeorgetownX'}),
url(r'^(?i)university_profile/McGillX$', 'courseware.views.static_university_profile', url(r'^(?i)university_profile/McGillX$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'McGillX'}), name="static_university_profile", kwargs={'org_id': 'McGillX'}),
url(r'^(?i)university_profile/TorontoX$', 'courseware.views.static_university_profile', url(r'^(?i)university_profile/TorontoX$', 'courseware.views.static_university_profile',
...@@ -73,8 +75,6 @@ urlpatterns = ('', # nopep8 ...@@ -73,8 +75,6 @@ urlpatterns = ('', # nopep8
name="static_university_profile", kwargs={'org_id': 'RiceX'}), name="static_university_profile", kwargs={'org_id': 'RiceX'}),
url(r'^(?i)university_profile/ANUx$', 'courseware.views.static_university_profile', url(r'^(?i)university_profile/ANUx$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'ANUx'}), name="static_university_profile", kwargs={'org_id': 'ANUx'}),
url(r'^(?i)university_profile/DelftX$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'DelftX'}),
url(r'^(?i)university_profile/EPFLx$', 'courseware.views.static_university_profile', url(r'^(?i)university_profile/EPFLx$', 'courseware.views.static_university_profile',
name="static_university_profile", kwargs={'org_id': 'EPFLx'}), name="static_university_profile", kwargs={'org_id': 'EPFLx'}),
......
{ {
"name": "mitx", "name": "mitx",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "coffee-script": "1.6.x"} "dependencies": {
"coffee-script": "1.6.X",
"phantom-jasmine": "0.1.0"
}
} }
...@@ -14,8 +14,7 @@ LMS_REPORT_DIR = File.join(REPORT_DIR, "lms") ...@@ -14,8 +14,7 @@ LMS_REPORT_DIR = File.join(REPORT_DIR, "lms")
# Packaging constants # Packaging constants
DEPLOY_DIR = "/opt/wwc" DEPLOY_DIR = "/opt/wwc"
PACKAGE_NAME = "mitx" PACKAGE_NAME = "edx-platform"
LINK_PATH = "/opt/wwc/mitx"
PKG_VERSION = "0.1" PKG_VERSION = "0.1"
COMMIT = (ENV["GIT_COMMIT"] || `git rev-parse HEAD`).chomp()[0, 10] COMMIT = (ENV["GIT_COMMIT"] || `git rev-parse HEAD`).chomp()[0, 10]
BRANCH = (ENV["GIT_BRANCH"] || `git symbolic-ref -q HEAD`).chomp().gsub('refs/heads/', '').gsub('origin/', '') BRANCH = (ENV["GIT_BRANCH"] || `git symbolic-ref -q HEAD`).chomp().gsub('refs/heads/', '').gsub('origin/', '')
...@@ -95,7 +94,7 @@ def template_jasmine_runner(lib) ...@@ -95,7 +94,7 @@ def template_jasmine_runner(lib)
if !coffee_files.empty? if !coffee_files.empty?
sh("node_modules/.bin/coffee -c #{coffee_files.join(' ')}") sh("node_modules/.bin/coffee -c #{coffee_files.join(' ')}")
end end
phantom_jasmine_path = File.expand_path("common/test/phantom-jasmine") phantom_jasmine_path = File.expand_path("node_modules/phantom-jasmine")
common_js_root = File.expand_path("common/static/js") common_js_root = File.expand_path("common/static/js")
common_coffee_root = File.expand_path("common/static/coffee/src") common_coffee_root = File.expand_path("common/static/coffee/src")
...@@ -337,7 +336,7 @@ end ...@@ -337,7 +336,7 @@ end
compile_assets() compile_assets()
phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs' phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs'
django_for_jasmine(system, false) do |jasmine_url| django_for_jasmine(system, false) do |jasmine_url|
sh("#{phantomjs} common/test/phantom-jasmine/lib/run_jasmine_test.coffee #{jasmine_url}") sh("#{phantomjs} node_modules/phantom-jasmine/lib/run_jasmine_test.coffee #{jasmine_url}")
end end
end end
end end
...@@ -388,7 +387,7 @@ Dir["common/lib/*"].select{|lib| File.directory?(lib)}.each do |lib| ...@@ -388,7 +387,7 @@ Dir["common/lib/*"].select{|lib| File.directory?(lib)}.each do |lib|
task "phantomjs_jasmine_#{lib}" do task "phantomjs_jasmine_#{lib}" do
phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs' phantomjs = ENV['PHANTOMJS_PATH'] || 'phantomjs'
template_jasmine_runner(lib) do |f| template_jasmine_runner(lib) do |f|
sh("#{phantomjs} common/test/phantom-jasmine/lib/run_jasmine_test.coffee #{f}") sh("#{phantomjs} node_modules/phantom-jasmine/lib/run_jasmine_test.coffee #{f}")
end end
end end
end end
......
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