From 374cdb0a3d63ab290fdba2c041ec31428b5107ec Mon Sep 17 00:00:00 2001 From: Andy Armstrong <andya@edx.org> Date: Wed, 27 Sep 2017 20:33:27 -0400 Subject: [PATCH] Convert course home page to Bootstrap LEARNER-1694 Fix a11y failure Fix header styling Fix layout issues Further layout fixes --- .../edx-pattern-library-shims/_buttons.scss | 11 +- lms/djangoapps/courseware/testutils.py | 2 +- lms/djangoapps/courseware/views/views.py | 15 +- lms/static/sass/_build-course.scss | 7 + lms/static/sass/_build-lms-v1.scss | 6 + lms/static/sass/_build-lms-v2.scss | 6 + lms/static/sass/_developer.scss | 61 ------ lms/static/sass/bootstrap/_footer.scss | 4 +- lms/static/sass/bootstrap/_header.scss | 13 ++ lms/static/sass/bootstrap/_layouts.scss | 110 ++++++---- lms/static/sass/bootstrap/_legacy.scss | 74 +++++++ lms/static/sass/bootstrap/_navigation.scss | 26 ++- lms/static/sass/bootstrap/_variables.scss | 6 - lms/static/sass/bootstrap/lms-main.scss | 13 +- .../course/layout/_courseware_preview.scss | 60 ++++-- lms/static/sass/elements-v2/_buttons.scss | 4 + .../sass/features/_course-experience.scss | 57 +++-- lms/static/sass/features/_course-sock.scss | 26 ++- .../features/_course-upgrade-message.scss | 28 +-- lms/static/sass/partials/base/_variables.scss | 3 +- lms/static/sass/shared-v2/_components.scss | 11 - lms/static/sass/shared-v2/_layouts.scss | 104 ++++++---- lms/static/sass/shared-v2/_variables.scss | 3 + .../courseware/course_navigation.html | 54 +++-- lms/templates/courseware/tab-view-v2.html | 32 +++ lms/templates/courseware/tab-view.html | 12 +- lms/templates/footer.html | 4 +- lms/templates/header/brand.html | 28 +++ .../bootstrap/navbar-authenticated.html | 83 -------- .../bootstrap/navbar-not-authenticated.html | 61 ------ lms/templates/navigation/navigation.html | 6 +- lms/templates/preview_menu.html | 4 +- lms/templates/user_dropdown.html | 52 +++-- .../reference/bootstrap/course-skeleton.html | 96 ++++----- .../ux/reference/bootstrap/unit-page.html | 2 +- .../course_bookmarks/course-bookmarks.html | 2 +- .../features/course_experience/__init__.py | 3 + .../fixtures/course-home-fragment.html | 8 +- .../course-home-fragment.html | 194 +++++++++--------- .../course-messages-fragment.html | 2 +- .../course-reviews-fragment.html | 4 +- .../course-sock-fragment.html | 2 +- .../course-updates-fragment.html | 2 +- .../course_experience/views/course_home.py | 5 +- .../course_experience/views/course_reviews.py | 6 +- .../course_experience/views/course_updates.py | 6 +- .../course_search/course-search-fragment.html | 2 +- .../learner-achievements-fragment.html | 1 - package.json | 2 +- pavelib/assets.py | 2 +- pavelib/paver_tests/test_assets.py | 2 +- themes/edx.org/lms/templates/header.html | 147 ++++++------- .../sass/partials/bootstrap/_theme.scss | 4 + 53 files changed, 792 insertions(+), 686 deletions(-) create mode 100644 lms/static/sass/bootstrap/_header.scss create mode 100644 lms/static/sass/bootstrap/_legacy.scss create mode 100644 lms/templates/courseware/tab-view-v2.html create mode 100644 lms/templates/header/brand.html delete mode 100644 lms/templates/navigation/bootstrap/navbar-authenticated.html delete mode 100644 lms/templates/navigation/bootstrap/navbar-not-authenticated.html diff --git a/common/static/sass/edx-pattern-library-shims/_buttons.scss b/common/static/sass/edx-pattern-library-shims/_buttons.scss index d0eaf87b925..e17bdc857ce 100644 --- a/common/static/sass/edx-pattern-library-shims/_buttons.scss +++ b/common/static/sass/edx-pattern-library-shims/_buttons.scss @@ -86,9 +86,9 @@ } // ---------------------------- -// #BRAND +// #PRIMARY // ---------------------------- -.btn-brand { +.btn-primary { @extend %btn-shims; border-color: $btn-brand-border-color; @@ -150,3 +150,10 @@ color: $btn-upgrade-color; } } + +// ---------------------------- +// #BRAND +// ---------------------------- +.btn-brand { + @extend .btn-primary; +} diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py index 91ba8d813a8..a9b60f2ed61 100644 --- a/lms/djangoapps/courseware/testutils.py +++ b/lms/djangoapps/courseware/testutils.py @@ -32,7 +32,7 @@ class RenderXBlockTestMixin(object): '<ol class="tabs course-tabs"', '<footer id="footer-openedx"', '<div class="window-wrap"', - '<div class="preview-menu"', + '<div class="preview-menu container"', '<div class="container"', ] diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index aa50c0732c0..6ed25fd0223 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -554,12 +554,19 @@ class CourseTabView(EdxFragmentView): log.exception("Error while rendering courseware-error page") raise + def uses_bootstrap(self, request, course): + """ + Returns true if this view uses Bootstrap. + """ + return False + def create_page_context(self, request, course=None, tab=None, **kwargs): """ Creates the context for the fragment's template. """ staff_access = has_access(request.user, 'staff', course) supports_preview_menu = tab.get('supports_preview_menu', False) + uses_bootstrap = self.uses_bootstrap(request, course) if supports_preview_menu: masquerade, masquerade_user = setup_masquerade(request, course.id, staff_access, reset_masquerade_data=True) request.user = masquerade_user @@ -578,7 +585,8 @@ class CourseTabView(EdxFragmentView): 'staff_access': staff_access, 'masquerade': masquerade, 'supports_preview_menu': supports_preview_menu, - 'uses_pattern_library': True, + 'uses_bootstrap': uses_bootstrap, + 'uses_pattern_library': not uses_bootstrap, 'disable_courseware_js': True, } context.update( @@ -603,7 +611,10 @@ class CourseTabView(EdxFragmentView): if not page_context: page_context = self.create_page_context(request, course=course, tab=tab, **kwargs) page_context['fragment'] = fragment - return render_to_response('courseware/tab-view.html', page_context) + if self.uses_bootstrap(request, course): + return render_to_response('courseware/tab-view.html', page_context) + else: + return render_to_response('courseware/tab-view-v2.html', page_context) @ensure_csrf_cookie diff --git a/lms/static/sass/_build-course.scss b/lms/static/sass/_build-course.scss index c23b8dad174..8f23625a033 100644 --- a/lms/static/sass/_build-course.scss +++ b/lms/static/sass/_build-course.scss @@ -3,6 +3,13 @@ // About: Sass compile for the LMS Courseware Elements that are shared between LTR and RTL UI. Configuration and vendor specific imports happen before this shared set of imports are compiled in the lms-course-*.scss files. +// Bootstrap support for use with shared partials +@import 'bootstrap/theme'; +@import 'bootstrap/scss/functions'; +@import 'bootstrap/scss/variables'; +@import "bootstrap/scss/mixins/breakpoints"; + +// Base @import 'base/base'; @import 'base/headings'; @import 'base/extends'; diff --git a/lms/static/sass/_build-lms-v1.scss b/lms/static/sass/_build-lms-v1.scss index 3a311a74e6e..4a59870a05b 100644 --- a/lms/static/sass/_build-lms-v1.scss +++ b/lms/static/sass/_build-lms-v1.scss @@ -3,6 +3,12 @@ // About: Sass compile for the LMS Elements that are shared between LTR and RTL UI. Configuration and vendor specific imports happen before this shared set of imports are compiled in the lms-main-*.scss files. +// Bootstrap support for use with shared partials +@import 'bootstrap/theme'; +@import 'bootstrap/scss/functions'; +@import 'bootstrap/scss/variables'; +@import "bootstrap/scss/mixins/breakpoints"; + // base - assets @import 'base/font_face'; @import 'base/extends'; diff --git a/lms/static/sass/_build-lms-v2.scss b/lms/static/sass/_build-lms-v2.scss index be8a9bb4e76..100e4b6637d 100644 --- a/lms/static/sass/_build-lms-v2.scss +++ b/lms/static/sass/_build-lms-v2.scss @@ -2,6 +2,12 @@ // LMS: Shared Build Compile // Version 2 - introduces the Pattern Library +// Bootstrap support for use with shared partials +@import 'bootstrap/theme'; +@import 'bootstrap/scss/functions'; +@import 'bootstrap/scss/variables'; +@import "bootstrap/scss/mixins/breakpoints"; + // Configuration @import 'config'; @import 'base/variables'; diff --git a/lms/static/sass/_developer.scss b/lms/static/sass/_developer.scss index b5cedce2cca..56820ac8c8c 100644 --- a/lms/static/sass/_developer.scss +++ b/lms/static/sass/_developer.scss @@ -225,64 +225,3 @@ border: 0; } } - -// pfogg - ECOM-2604 -// styling for date summary blocks on the course info page -.date-summary-container { - .date-summary { - @include clearfix; - padding: 10px; - @include border-left(3px solid $gray-l3); - - .heading { - @extend %t-title7; - color: $gray-d2; - } - - .description { - margin-top: $baseline/2; - margin-bottom: $baseline/2; - display: inline-block; - color: $gray-d1; - @extend %t-title8; - } - - .date-summary-link { - @extend %t-title8; - font-weight: $font-semibold; - a { - color: $link-color; - font-weight: normal; - } - } - - .date { - color: $gray-d1; - @extend %t-title9; - } - - &-todays-date { - @include border-left(3px solid $blue); - - .heading { - @extend %t-title8; - } - } - - &-verified-upgrade-deadline { - @include border-left(3px solid $green); - } - - &-verification-deadline-passed { - @include border-left(3px solid $red); - } - - &-verification-deadline-retry { - @include border-left(3px solid $red); - } - - &-verification-deadline-upcoming { - @include border-left(3px solid $orange); - } - } -} diff --git a/lms/static/sass/bootstrap/_footer.scss b/lms/static/sass/bootstrap/_footer.scss index 9708352beec..450bed64dd7 100644 --- a/lms/static/sass/bootstrap/_footer.scss +++ b/lms/static/sass/bootstrap/_footer.scss @@ -43,12 +43,12 @@ } } - li:not(:first-child) a:before { + li:not(:first-child) a::before { content: "- "; } } - footer-language-selector { + .footer-language-selector { margin: $baseline 0; } diff --git a/lms/static/sass/bootstrap/_header.scss b/lms/static/sass/bootstrap/_header.scss new file mode 100644 index 00000000000..d1581f0954b --- /dev/null +++ b/lms/static/sass/bootstrap/_header.scss @@ -0,0 +1,13 @@ +// Open edX: LMS header +// ==================== + +.header-global { + .logo-header { + margin: 0; + padding: 0; + + .logo-image { + height: 30px; + } + } +} diff --git a/lms/static/sass/bootstrap/_layouts.scss b/lms/static/sass/bootstrap/_layouts.scss index a8b6fa1f4ec..3ea2e58bab0 100644 --- a/lms/static/sass/bootstrap/_layouts.scss +++ b/lms/static/sass/bootstrap/_layouts.scss @@ -1,49 +1,85 @@ // LMS layouts .content-wrapper { - margin-top: $baseline; - - .course-tabs { - padding-bottom: 0; - - .nav-item { - &.active, &:hover{ - .nav-link { - border-bottom-color: theme-color("primary"); - color: theme-color("primary"); - } - } - - .nav-link { - padding: $baseline/2 $baseline*3/4 $baseline*13/20; - border-style: solid; - border-width: 0 0 $baseline/5 0; - border-bottom-color: transparent; - - @include media-breakpoint-down(md) { - border: none; - text-align: left; - padding: 0 0 $baseline/2 0; - } - } - } - } + margin-top: $baseline; + padding-bottom: $baseline*2; + + .course-tabs { + padding: 0; + font-size: $font-size-sm; - .main-container { - border: 1px solid $border-color; - background-color: $body-bg; + .nav-item { + .nav-link { + padding: $baseline/2 $baseline*3/4 $baseline*13/20; + border-style: solid; + border-width: 0 0 $baseline/5 0; + border-bottom-color: transparent; + color: theme-color("secondary"); - .page-header { - border-bottom: 1px solid $border-color; - padding: 20px; + @include media-breakpoint-down(md) { + border: none; + text-align: left; + padding: 0 0 $baseline/2 0; } + } - .page-content { - padding: 20px; + &.active, + &:hover { + .nav-link { + border-bottom-color: theme-color("primary"); + color: theme-color("primary"); } + } + } + } + + &.container-fluid { + max-width: map-get($container-max-widths, xl); + } +} + +.page-header { + display: flex; + flex-wrap: wrap; + border-bottom: 1px solid $border-color; + padding: 20px; + + .page-header-main { + flex-grow: 1; // This column should consume all the available space + } + + .page-header-secondary { + display: flex; + + @include media-breakpoint-up(md) { + margin-left: $baseline; + + &:not(:last-child) { + margin-right: $baseline; + } + } + } +} + +.page-content-container { + border: 1px solid $border-color; + background-color: $body-bg; +} + +.page-content { + padding: $baseline; + + @include media-breakpoint-up(md) { + display: flex; + + .page-content-main { + flex-grow: 1; // This column should consume all the available space } - &.container-fluid { - max-width: map-get($container-max-widths, xl); + .page-content-secondary { + min-width: 350px; // Note: setting width only is not obeyed + max-width: 350px; // Note: setting width only is not obeyed + margin-left: $baseline*2; } + } } diff --git a/lms/static/sass/bootstrap/_legacy.scss b/lms/static/sass/bootstrap/_legacy.scss new file mode 100644 index 00000000000..86e03ce2033 --- /dev/null +++ b/lms/static/sass/bootstrap/_legacy.scss @@ -0,0 +1,74 @@ +// ------------------------------------ +// LMS support for legacy Sass partials +// +// The intention is that this makes it +// easier to reuse existing partials +// that were not built with Bootstrap +// in mind. +// ------------------------------------ + +@import 'vendor/bi-app/bi-app-ltr'; // set the layout for left to right languages + +@mixin font-size($sizeValue: 16) { + font-size: ($sizeValue/10) + rem; +} + +// Support .sr as a synonym for .sr-only +.sr { + @extend .sr-only; +} + +// ---------------------------- +// #LEGACY VARIABLES +// ---------------------------- + +// ---------------------------- +// #GRID +// ---------------------------- + +$lms-max-width: 1180px !default; + +$grid-breakpoints-sm: 576px !default; +$grid-breakpoints-md: 768px !default; +$grid-breakpoints-lg: 992px !default; + +// ---------------------------- +// #FONTS +// ---------------------------- + +$body-font-size: $font-size-base !default; +$font-light: 300 !default; +$font-regular: 400 !default; +$font-semibold: 600 !default; +$font-bold: 700 !default; + +// ---------------------------- +// #COLORS +// ---------------------------- + +$lms-gray: theme-color("secondary") !default; +$lms-background-color: $gray-100 !default; +$lms-container-background-color: theme-color("inverse") !default; +$lms-border-color: $gray-300 !default; +$lms-label-color: theme-color("secondary") !default; +$lms-active-color: theme-color("primary") !default; +$lms-preview-menu-color: $gray-400 !default; +$lms-inactive-color: theme-color("disabled") !default; +$success-color: theme-color("success") !default; +$success-color-hover: theme-color("success") !default; +$lms-hero-color: #005e90 !default; +$lms-purchase-color: theme-color("success") !default; + +// Blacks +$black: rgb(0, 0, 0) !default; +$black-t0: rgba($black, 0.125) !default; +$black-t1: rgba($black, 0.25) !default; +$black-t2: rgba($black, 0.5) !default; +$black-t3: rgba($black, 0.75) !default; + +// Shadows +$shadow: rgba(0, 0, 0, 0.2) !default; +$shadow-l1: rgba(0, 0, 0, 0.1) !default; +$shadow-l2: rgba(0, 0, 0, 0.05) !default; +$shadow-d1: rgba(0, 0, 0, 0.4) !default; +$shadow-d2: rgba($black, 0.6) !default; diff --git a/lms/static/sass/bootstrap/_navigation.scss b/lms/static/sass/bootstrap/_navigation.scss index 7e139633c7d..8f491630359 100644 --- a/lms/static/sass/bootstrap/_navigation.scss +++ b/lms/static/sass/bootstrap/_navigation.scss @@ -13,17 +13,28 @@ margin: 0 auto; max-width: map-get($container-max-widths, xl); + + .logo-header { + display: flex; + align-items: center; + } + .logo.slim a { height: $baseline*3/2; margin-top: $baseline/5; } .course-header { - font-size: $font-size-lg; - margin: $baseline/2 $baseline/2 0 0; + display: none; + + @include media-breakpoint-up(md) { + display: block; + font-size: $font-size-base; + font-weight: $font-weight-light; - .provider { - font-weight: $font-weight-bold; + .provider { + font-weight: $font-weight-bold; + } } } @@ -31,7 +42,6 @@ margin: 0 $baseline 0 0; font-weight: $font-weight-normal; font-family: $font-family-base; - text-transform: uppercase; list-style: none; .nav-link { @@ -49,7 +59,8 @@ } @include media-breakpoint-down(md) { - &.nav-item-open-collapsed, &.nav-item-open-collapsed-only { + &.nav-item-open-collapsed, + &.nav-item-open-collapsed-only { display: initial; margin: $baseline/4 $baseline/2; @@ -63,13 +74,14 @@ } } } + &.nav-item-hidden-collapsed { display: none; } } } - .btn-shopping-cart{ + .btn-shopping-cart { padding-top: 0.7rem; // $btn-padding-y-lg once themed } diff --git a/lms/static/sass/bootstrap/_variables.scss b/lms/static/sass/bootstrap/_variables.scss index 308ac9406d4..e9f009c39d7 100644 --- a/lms/static/sass/bootstrap/_variables.scss +++ b/lms/static/sass/bootstrap/_variables.scss @@ -1,12 +1,6 @@ // lms - bootstrap utilities - variables // ==================== -// #Units: Unit variables -// #GRID: Grid and layout variables -// #COLORS: Base, palette and theme color definitions + application -// #TYPOGRAPHY: Font definitions and scales -// #ICONS: Icon specific colors + other styling - // ---------------------------- // #UNITS // ---------------------------- diff --git a/lms/static/sass/bootstrap/lms-main.scss b/lms/static/sass/bootstrap/lms-main.scss index 0c20be06f00..108c3cfecd6 100644 --- a/lms/static/sass/bootstrap/lms-main.scss +++ b/lms/static/sass/bootstrap/lms-main.scss @@ -5,13 +5,24 @@ // Bootstrap theme @import 'bootstrap/theme'; @import 'bootstrap/scss/bootstrap'; -@import 'bootstrap/scss/mixins'; + +// Legacy support +@import 'legacy'; // Variables @import 'variables'; // Elements +@import 'header'; @import 'footer'; @import 'navigation'; @import 'layouts'; @import 'components'; +@import 'course/layout/courseware_preview'; + +// Features +@import 'features/bookmarks'; +@import 'features/course-experience'; +@import 'features/course-search'; +@import 'features/course-sock'; +@import 'features/course-upgrade-message'; diff --git a/lms/static/sass/course/layout/_courseware_preview.scss b/lms/static/sass/course/layout/_courseware_preview.scss index 22617471887..aa1b76acee3 100644 --- a/lms/static/sass/course/layout/_courseware_preview.scss +++ b/lms/static/sass/course/layout/_courseware_preview.scss @@ -1,9 +1,10 @@ .wrapper-preview-menu { @include clearfix(); - @include box-sizing(border-box); + margin: 0 auto 0; padding: ($baseline*0.75); - background-color: $gray-l3; + background-color: $lms-preview-menu-color; + box-sizing: border-box; @media print { display: none; @@ -11,17 +12,22 @@ .preview-menu { @extend %inner-wrapper; + width: auto; } .preview-actions { + @include padding-left(0); + display: inline-block; + margin-bottom: 0; .action-preview { display: inline-block; .action-preview-label { @include margin-right($baseline/2); + display: inline-block; margin-bottom: 0; vertical-align: middle; @@ -47,6 +53,7 @@ font-size: 90%; } } + .proctored_exam_status { // STATE: Fixed to viewport (used for scrolling) &.is-fixed { @@ -56,70 +63,85 @@ top: 0; width: 100%; } + .exam-timer { + @include font-size(14); + background-color: rgb(229, 234, 236); padding: $baseline ($baseline*2); - border-left: 4px solid $m-blue-l1; + border-left: 4px solid theme-color("primary"); margin: 0 auto; - color: $gray-d2; - @include font-size(14); + color: theme-color("secondary"); + .exam-text { display: inline-block; width: calc(100% - 250px); } + a { color: rgb(9, 121, 186); } + .pull-right { - color: $gray-d1; + color: theme-color("secondary"); + b { - color: $gray-d3; + color: theme-color("dark"); } } + .turn_in_exam { margin-top: -6px; } + &.low-time { - color: $gray-l3; + color: theme-color("light"); background-color: rgb(79, 88, 92); + a { color: $white; text-decoration: underline; } + .pull-right { - color: $gray-l3; + color: theme-color("light"); + b { - color: $white; + color: theme-color("inverse"); } .exam-button-turn-in-exam { background-color: transparent; - border: 1px solid $white; - color: $white; + border: 1px solid theme-color("inverse"); + color: theme-color("inverse"); &:hover { - border: 1px solid $white; - background-color: $white; - color: $action-primary-bg; + border: 1px solid theme-color("inverse"); + background-color: theme-color("inverse"); + color: theme-color("brand"); } } } } + &.warning { - border-left-color: $warning-color; + border-left-color: theme-color("warning"); } + &.critical { - border-left-color: $alert-color; - color: $white; + border-left-color: theme-color("danger"); + color: theme-color("inverse"); } + .exam-button-turn-in-exam { @extend %btn-pl-primary-base; @extend %t-action3; @extend %t-weight4; + margin-right: $baseline; border: 0; background-image: none; - padding: ($baseline/5) ($baseline*.75); + padding: ($baseline/5) ($baseline*0.75); box-shadow: none; text-shadow: none; diff --git a/lms/static/sass/elements-v2/_buttons.scss b/lms/static/sass/elements-v2/_buttons.scss index 00541fc25d0..2c73e4fa0c5 100644 --- a/lms/static/sass/elements-v2/_buttons.scss +++ b/lms/static/sass/elements-v2/_buttons.scss @@ -4,6 +4,10 @@ $upgrade-color: #009b00 !default; $upgrade-dark-color: #008100 !default; +.btn-primary { + @extend .btn-brand; +} + .btn-upgrade { @extend %btn; diff --git a/lms/static/sass/features/_course-experience.scss b/lms/static/sass/features/_course-experience.scss index 7ec3363e4f3..9c73a150319 100644 --- a/lms/static/sass/features/_course-experience.scss +++ b/lms/static/sass/features/_course-experience.scss @@ -1,11 +1,33 @@ // ------------------------------ // Styling for files located in the openedx/features repository. +// Course sidebar sections +.course-sidebar { + .section { + h3 { + font-size: $font-size-base; + font-weight: $font-weight-bold; + } + + .icon { + width: 20px; + text-align: center; + } + + &:not(:first-child) { + margin-top: $baseline; + } + } +} + // Course call to action message .course-message { + display: flex; + .message-author { display: inline-block; width: 70px; + height: 70px; border-radius: $baseline*7/4; border: 1px solid $lms-border-color; @@ -17,11 +39,11 @@ .message-content { @include margin(0, 0, $baseline, $baseline); + flex-grow: 1; position: relative; border: 1px solid $lms-border-color; padding: $baseline; border-radius: $baseline/4; - width: calc(100% - 90px); @media (max-width: $grid-breakpoints-md) { width: 100%; @@ -59,9 +81,10 @@ } .message-header { + @include margin-right($baseline*2); + font-weight: $font-semibold; margin-bottom: $baseline/2; - width: calc(100% - 40px); } a:not(.btn) { @@ -101,7 +124,7 @@ position: absolute; top: $baseline/2; font-size: font-size(small); - color: $uxpl-blue-base; + color: theme-color("primary"); cursor: pointer; &:hover { @@ -162,6 +185,7 @@ // Course Goal Updates .section-goals { @include float(left); + border: 1px solid $lms-border-color; padding: $baseline*0.75 $baseline*0.75 $baseline*0.25; border-radius: 5px; @@ -181,6 +205,7 @@ .edit-icon { @include right($baseline/4); + position: absolute; top: $baseline*0.6; cursor: pointer; @@ -193,7 +218,7 @@ } .current-goal-container { - .title{ + .title { @include float(left); @include margin-right($baseline/4); } @@ -207,18 +232,20 @@ @include padding-left($baseline*0.4); } + .response-icon { @include margin-left($baseline/4); @include right(-1*$baseline); + top: $baseline*0.75; position: absolute; &.fa-check { - color: $success-color; + color: theme-color("success"); } &.fa-close { - color: $error-color; + color: theme-color("error"); } } } @@ -231,10 +258,9 @@ // Course outline .course-outline { - color: $lms-gray; - .block-tree { margin: 0; + padding: 0; list-style-type: none; .section { @@ -253,7 +279,7 @@ padding: 0; - h3 { + .section-title { font-weight: $font-bold; font-size: 1.1rem; margin: 0; @@ -266,7 +292,7 @@ ol.outline-item { padding-bottom: $baseline; - border-bottom: 1px solid $light-grey-solid; + border-bottom: 1px solid $lms-border-color; margin: 0 0 ($baseline / 2) 0; .subsection { @@ -294,7 +320,7 @@ .subsection-text { .details { font-size: $body-font-size; - color: $lms-gray; + color: theme-color("secondary"); } } @@ -332,22 +358,21 @@ .date-summary-container { .date-summary { @include clearfix; - @include border-left(3px solid $gray-l3); + @include border-left(3px solid $gray-300); padding: $baseline/2; .heading { - font-size: 1.1rem; + font-size: 0.9rem; line-height: 1; font-weight: $font-bold; - color: $lms-gray; + color: theme-color("dark"); } .description { margin-top: $baseline/2; margin-bottom: $baseline/2; display: inline-block; - color: $gray-d1; } .date-summary-link { @@ -360,7 +385,7 @@ } .date { - color: $gray-d1; + color: theme-color("dark"); } &-todays-date { diff --git a/lms/static/sass/features/_course-sock.scss b/lms/static/sass/features/_course-sock.scss index d08327c792a..d83eb7d953b 100644 --- a/lms/static/sass/features/_course-sock.scss +++ b/lms/static/sass/features/_course-sock.scss @@ -17,23 +17,23 @@ position: absolute; top: (-1 * $baseline); width: ($baseline * 15); - color: $button-bg-hover-color; - background-color: $success-color; - border-color: $success-color; + color: theme-color("inverse"); + background-color: theme-color("success"); + border-color: theme-color("success"); background-image: none; box-shadow: none; -webkit-transition: background-color 0.5s; transition: background-color 0.5s; &.active { - color: $success-color; - background-color: $button-bg-hover-color; - border-color: $success-color; + color: theme-color("success"); + background-color: theme-color("inverse"); + border-color: theme-color("success"); background-image: none; box-shadow: none; &:hover { - color: $button-bg-hover-color; + color: theme-color("inverse"); background-color: $success-color-hover; border-color: $success-color-hover; background-image: none; @@ -42,7 +42,7 @@ } &:hover { - color: $button-bg-hover-color; + color: theme-color("inverse"); background-color: $success-color-hover; border-color: $success-color-hover; background-image: none; @@ -111,6 +111,10 @@ .action-upgrade-certificate { position: absolute; right: $baseline; + background-color: theme-color("success"); + border-color: theme-color("success"); + background-image: none; + box-shadow: none; @media (max-width: 960px) { & { @@ -154,10 +158,10 @@ top: (-1 * $baseline * 5/4); &:not(.active) { - color: $button-bg-hover-color; - background-color: $success-color; + color: theme-color("inverse"); + background-color: theme-color("success"); box-shadow: none; - border: 1px solid $success-color; + border: 1px solid theme-color("success"); &:hover { background-color: $success-color-hover; diff --git a/lms/static/sass/features/_course-upgrade-message.scss b/lms/static/sass/features/_course-upgrade-message.scss index 0a15a8d5631..6669a519f57 100644 --- a/lms/static/sass/features/_course-upgrade-message.scss +++ b/lms/static/sass/features/_course-upgrade-message.scss @@ -3,11 +3,10 @@ the creative property. This will allow us to better track individual performance of each style of the message. Search for the courseware_verified_certificate_upsell promotion ID. */ -$upgrade-message-background-color: $blue-d1; // Expanded upgrade message .vc-message { - background: $blue-d1; + background: $lms-hero-color; color: $white; padding: $baseline; position: relative; @@ -28,12 +27,9 @@ $upgrade-message-background-color: $blue-d1; font-size: 1.25rem; font-weight: 700; margin-bottom: 1rem; - - @include float(left); } .vc-selling-points { - @include clear(left); @include padding-left(0); font-size: 0.825rem; @@ -59,15 +55,11 @@ $upgrade-message-background-color: $blue-d1; } } - img { - max-width: 100%; - } - // Show/hide button .vc-toggle { @include float(right); - color: $white; + color: theme-color("inverse"); } // Cert image @@ -76,10 +68,12 @@ $upgrade-message-background-color: $blue-d1; @include padding-left(1rem); clear: both; - width: 35%; img { - max-width: 100%; + @include float(right); + + clear: both; + width: 250px; } } } @@ -112,15 +106,7 @@ $upgrade-message-background-color: $blue-d1; } } -@media (max-width: $bp-screen-md) { - .vc-message.polite .vc-title { - clear: both; - width: 100%; - margin-bottom: 1rem; - } -} - -@media (max-width: $bp-screen-sm) { +@media (max-width: $grid-breakpoints-sm) { .vc-message .vc-hero { display: none !important; } diff --git a/lms/static/sass/partials/base/_variables.scss b/lms/static/sass/partials/base/_variables.scss index f954ab5e796..112096a5d4e 100644 --- a/lms/static/sass/partials/base/_variables.scss +++ b/lms/static/sass/partials/base/_variables.scss @@ -252,7 +252,8 @@ $micromasters-color: #005585 !default; $xseries-color: #424242 !default; $professional-certificate-color: #9a1f60 !default; $zebra-stripe-color: rgb(249, 250, 252) !default; -$divider-color: rgb(226,231,236) !default; +$divider-color: rgb(226, 231, 236) !default; +$lms-preview-menu-color: #c8c8c8 !default; // old color variables // DEPRECATED: Do not continue to use these colors, instead use pattern libary and base colors above. diff --git a/lms/static/sass/shared-v2/_components.scss b/lms/static/sass/shared-v2/_components.scss index 12ce69cbef4..e0f2420cd3b 100644 --- a/lms/static/sass/shared-v2/_components.scss +++ b/lms/static/sass/shared-v2/_components.scss @@ -202,14 +202,3 @@ } } } - -.section { - .icon { - width: 20px; - text-align: center; - } -} - -.section:not(:first-child) { - margin-top: $baseline; -} diff --git a/lms/static/sass/shared-v2/_layouts.scss b/lms/static/sass/shared-v2/_layouts.scss index 4e35ed8d1fb..ac36397ebaf 100644 --- a/lms/static/sass/shared-v2/_layouts.scss +++ b/lms/static/sass/shared-v2/_layouts.scss @@ -1,57 +1,77 @@ // LMS layouts .content-wrapper { - max-width: $lms-max-width; - padding-bottom: $baseline*2; + max-width: $lms-max-width; + padding-bottom: $baseline*2; - .container { - @include clearfix(); - border: 1px solid $lms-border-color; - background-color: $lms-container-background-color; + .page-content-container { + @include clearfix(); + + border: 1px solid $lms-border-color; + background-color: $lms-container-background-color; + } + + .page-header { + @include clearfix(); + + border-bottom: 1px solid $lms-border-color; + padding: $baseline; + + .page-title { + @extend %t-title4; + + margin-bottom: ($baseline/4); + text-transform: none; + color: $black; } - .page-header { - @include clearfix(); - border-bottom: 1px solid $lms-border-color; - padding: $baseline; + .page-description { + @extend %t-copy-sub1; - .page-title { - @extend %t-title4; - margin-bottom: ($baseline/4); - text-transform: none; - color: $black; - } + margin-bottom: ($baseline/4); + color: $gray; + } - .page-description { - @extend %t-copy-sub1; - margin-bottom: ($baseline/4); - color: $gray; + &.has-secondary { + .page-header-main { + display: inline-block; + } + + .page-header-secondary { + @include float(right); + @include text-align(right); + + display: inline-block; + vertical-align: text-bottom; + + .form-actions { + @include margin-left($baseline/2); + + display: inline-block; } - &.has-secondary { - .page-header-main { - display: inline-block; - } - - .page-header-secondary { - @include float(right); - @include text-align(right); - display: inline-block; - vertical-align: text-bottom; - - .form-actions { - @include margin-left($baseline/2); - display: inline-block; - } - - .form-actions > *:first-child { - @include margin-left(0); - } - } + .form-actions > *:first-child { + @include margin-left(0); } + } } + } + + .page-content { + padding: $baseline; + + @media (min-width: $grid-breakpoints-md) { + display: flex; + + .page-content-main { + flex-grow: 1; // This column should consume all the available space + } - .page-content { - padding: $baseline; + .page-content-secondary { + min-width: 350px; // Note: setting width only is not obeyed + max-width: 350px; // Note: setting width only is not obeyed + margin-left: $baseline*2; + } } + } } diff --git a/lms/static/sass/shared-v2/_variables.scss b/lms/static/sass/shared-v2/_variables.scss index 6723155c070..5afa2a5c2aa 100644 --- a/lms/static/sass/shared-v2/_variables.scss +++ b/lms/static/sass/shared-v2/_variables.scss @@ -29,6 +29,9 @@ $lms-preview-menu-color: #c8c8c8 !default; $lms-inactive-color: rgb(94,94,94) !default; $success-color: rgb(0, 155, 0) !default; $success-color-hover: palette(success, text) !default; +$lms-hero-color: #005e90 !default; +$lms-purchase-color: $success-color !default; +$lms-purchase-color-hover: $success-color-hover !default; $button-bg-hover-color: $white !default; diff --git a/lms/templates/courseware/course_navigation.html b/lms/templates/courseware/course_navigation.html index 273ecb48370..443232384ef 100644 --- a/lms/templates/courseware/course_navigation.html +++ b/lms/templates/courseware/course_navigation.html @@ -4,9 +4,10 @@ <%namespace name='static' file='/static_content.html'/> <%! -from django.utils.translation import ugettext as _ from courseware.tabs import get_course_tab_list from django.conf import settings +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ %> <% @@ -29,16 +30,43 @@ if course is not None: % endif % if disable_tabs is UNDEFINED or not disable_tabs: - <nav class="${active_page} wrapper-course-material" aria-label="${_('Course Material')}"> - <div class="course-material"> - <% - tab_list = get_course_tab_list(request, course) - tabs_tmpl = static.get_template_path('/courseware/tabs.html') - %> - <ol class="tabs course-tabs"> - <%include file="${tabs_tmpl}" args="tab_list=tab_list,active_page=active_page,default_tab=default_tab,tab_image=tab_image" /> - <%block name="extratabs" /> - </ol> - </div> - </nav> + <% + tab_list = get_course_tab_list(request, course) + %> + % if uses_bootstrap: + <nav class="navbar course-tabs pb-0 navbar-expand-lg"> + <ul class="navbar-nav mr-auto"> + % for tab in tab_list: + <% + tab_is_active = tab.tab_id in (active_page, default_tab) + %> + <li class="nav-item ${'active' if tab_is_active else ''}"> + <a href="${tab.link_func(course, reverse)}" class="nav-link"> + ${_(tab.name)} + % if tab_is_active: + <span class="sr-only">, ${_('current location')}</span> + %endif + % if tab_image: + ## Translators: 'needs attention' is an alternative string for the + ## notification image that indicates the tab "needs attention". + <img src="${tab_image}" alt="${_('needs attention')}" /> + %endif + </a> + </li> + % endfor + </ul> + </nav> + % else: + <nav class="${active_page} wrapper-course-material" aria-label="${_('Course Material')}"> + <div class="course-material"> + <% + tabs_tmpl = static.get_template_path('/courseware/tabs.html') + %> + <ol class="tabs course-tabs"> + <%include file="${tabs_tmpl}" args="tab_list=tab_list,active_page=active_page,default_tab=default_tab,tab_image=tab_image" /> + <%block name="extratabs" /> + </ol> + </div> + </nav> + % endif %endif diff --git a/lms/templates/courseware/tab-view-v2.html b/lms/templates/courseware/tab-view-v2.html new file mode 100644 index 00000000000..cbef28204f7 --- /dev/null +++ b/lms/templates/courseware/tab-view-v2.html @@ -0,0 +1,32 @@ +## mako + +<%! main_css = "style-main-v2" %> + +<%page expression_filter="h"/> +<%! +from openedx.core.djangolib.markup import HTML +%> + +<%inherit file="/main.html" /> +<%namespace name='static' file='/static_content.html'/> + +<%block name="bodyclass">${tab['body_class']}</%block> + +<%def name="online_help_token()"><% return "${tab['online_help_token']}" %></%def> + +<%block name="pagetitle">${tab['name']} | ${course.display_number_with_default}</%block> + +<%include file="/courseware/course_navigation.html" args="active_page=active_page" /> + +<%block name="head_extra"> +${HTML(fragment.head_html())} +</%block> + +<%block name="footer_extra"> +<%include file="/mathjax_include.html" args="disable_fast_preview=True"/> +${HTML(fragment.foot_html())} +</%block> + +<%block name="content"> + ${HTML(fragment.body_html())} +</%block> diff --git a/lms/templates/courseware/tab-view.html b/lms/templates/courseware/tab-view.html index cbef28204f7..65bf854daf5 100644 --- a/lms/templates/courseware/tab-view.html +++ b/lms/templates/courseware/tab-view.html @@ -1,11 +1,9 @@ ## mako -<%! main_css = "style-main-v2" %> - <%page expression_filter="h"/> -<%! -from openedx.core.djangolib.markup import HTML -%> + +## Override the default styles_version to use Bootstrap +<%! main_css = "css/bootstrap/lms-main.css" %> <%inherit file="/main.html" /> <%namespace name='static' file='/static_content.html'/> @@ -18,6 +16,10 @@ from openedx.core.djangolib.markup import HTML <%include file="/courseware/course_navigation.html" args="active_page=active_page" /> +<%! +from openedx.core.djangolib.markup import HTML +%> + <%block name="head_extra"> ${HTML(fragment.head_html())} </%block> diff --git a/lms/templates/footer.html b/lms/templates/footer.html index 10ea5268bf8..743599be27f 100644 --- a/lms/templates/footer.html +++ b/lms/templates/footer.html @@ -14,7 +14,7 @@ <footer> <div class="row"> <div class="col-md-9"> - <nav class="navbar site-nav navbar-expand-sm navbar-light" aria-label="${_('About')}"> + <nav class="navbar site-nav navbar-expand-sm" aria-label="${_('About')}"> <ul class="navbar-nav"> % for item_num, link in enumerate(footer['navigation_links'], start=1): <li class="nav-item"> @@ -27,7 +27,7 @@ ## Site operators: Please do not remove this paragraph! This attributes back to edX and makes your acknowledgement of edX's trademarks clear. <p class="copyright">${footer['copyright']} ${u" | {icp}".format(icp=getattr(settings,'ICP_LICENSE')) if getattr(settings,'ICP_LICENSE',False) else ""}</p> - <nav class="navbar legal-nav navbar-expand-sm navbar-light" aria-label="${_('Legal')}"> + <nav class="navbar legal-nav navbar-expand-sm" aria-label="${_('Legal')}"> <ul class="navbar-nav"> % for item_num, link in enumerate(footer['legal_links'], start=1): <li class="nav-item"> diff --git a/lms/templates/header/brand.html b/lms/templates/header/brand.html new file mode 100644 index 00000000000..12c9ea76ded --- /dev/null +++ b/lms/templates/header/brand.html @@ -0,0 +1,28 @@ +## mako + +<%page expression_filter="h"/> + +<%namespace name='static' file='/static_content.html'/> + +<%! +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext as _ + +# App that handles subdomain specific branding +from branding import api as branding_api +%> + +<h1 class="hd logo-header navbar-brand"> + <div class="logo"> + <a class="navbar-brand" href="${reverse('dashboard')}" itemprop="url"> + <img class="logo-image" src="${static.url("images/logo.png")}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}" itemprop="logo" /> + </a> + </div> + % if course and not disable_courseware_header: + <div class="course-header"> + <span class="provider">${course.display_org_with_default}:</span> + <span class="course-number">${course.display_number_with_default}</span> + <span class="course-name">${course.display_name_with_default}</span> + </div> + % endif +</h1> diff --git a/lms/templates/navigation/bootstrap/navbar-authenticated.html b/lms/templates/navigation/bootstrap/navbar-authenticated.html deleted file mode 100644 index bde233fd526..00000000000 --- a/lms/templates/navigation/bootstrap/navbar-authenticated.html +++ /dev/null @@ -1,83 +0,0 @@ -## mako - -<%page expression_filter="h"/> - -<%namespace name='static' file='../../static_content.html'/> -<%namespace file='../../main.html' import="login_query"/> -<%! -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext as _ -%> - -<div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav mr-auto"> - % if course: - <div class="course-header"> - <span class="provider">${course.display_org_with_default}:</span> - <span class="course-number">${course.display_number_with_default}</span> - <% - display_name = course.display_name_with_default - if settings.FEATURES.get('CUSTOM_COURSES_EDX', False): - ccx = get_current_ccx(course.id) - if ccx: - display_name = ccx.display_name - %> - <span class="course-name">${display_name}</span> - </div> - % endif - - - % if settings.FEATURES.get('COURSES_ARE_BROWSABLE') and not show_program_listing: - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a class="nav-link" href="${marketing_link('COURSES')}">${_('Explore courses')}</a> - </li> - % endif - - % if show_dashboard_tabs: - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a class="nav-link ${'active' if reverse('dashboard') == request.path else ''}" href="${reverse('dashboard')}"> - ${_("Courses")} - </a> - </li> - % if show_program_listing: - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a class="nav-link ${'active' if reverse('program_listing_view') in request.path else ''}" href="${reverse('program_listing_view')}"> - ${_("Programs")} - </a> - </li> - % endif - <% - self.real_user = getattr(user, 'real_user', user) - is_on_profile_page = data and data.get('profile_user_id') is not None - %> - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a class="${'active ' if is_on_profile_page else ''}tab-nav-link" href="${reverse('learner_profile', args=[self.real_user.username])}"> - ${_("Profile")} - </a> - </li> - % endif - - % if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD','') and user.is_staff: - <li class="nav-item mt-2 nav-item-open-collapsed"> - ## Translators: This is short for "System administration". - <a class="nav-link" href="${reverse('sysadmin')}">${_("Sysadmin")}</a> - </li> - % endif - </ul> - - <ul class="navbar-nav navbar-right"> - % if should_display_shopping_cart_func() and not (course and static.is_request_in_themed_site()): # see shoppingcart.context_processor.user_has_cart_context_processor - <a role="button" class="nav-item-open-collapsed btn-shopping-cart btn btn-secondary mr-3" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> - % endif - - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a href="${get_online_help_info(online_help_token)['doc_url']}" - target="_blank" - class="nav-link">${_("Help")}</a> - </li> - - <%include file="../../user_dropdown.html"/> - </ul> -</div> diff --git a/lms/templates/navigation/bootstrap/navbar-not-authenticated.html b/lms/templates/navigation/bootstrap/navbar-not-authenticated.html deleted file mode 100644 index 6e324670299..00000000000 --- a/lms/templates/navigation/bootstrap/navbar-not-authenticated.html +++ /dev/null @@ -1,61 +0,0 @@ -## mako - -<%page expression_filter="h"/> - -<%namespace name='static' file='../../static_content.html'/> -<%namespace file='../../main.html' import="login_query"/> - -<%! -from django.core.urlresolvers import reverse -from django.utils.translation import ugettext as _ -%> - -<div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav mr-auto"> - % if static.get_value('ENABLE_MKTG_SITE', settings.FEATURES.get('ENABLE_MKTG_SITE', False)): - <li class="nav-item"> - <a class="nav-link mt-2" href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a> - </li> - % if settings.FEATURES.get('COURSES_ARE_BROWSABLE'): - <li class="nav-item"> - <a class="nav-link mt-2" href="${marketing_link('COURSES')}">${_("Courses")}</a> - </li> - % endif - <li class="nav-item"> - <a class="nav-link mt-2" href="${marketing_link('SCHOOLS')}">${_("Schools")}</a> - </li> - % endif - - % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: - % if settings.FEATURES.get('ENABLE_COURSE_DISCOVERY'): - <li class="nav-item"> - <a class="nav-link mt-2" href="/courses">${_('Explore courses')}</a> - </li> - %endif - % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: - <li class="nav-item"> - <a class="nav-link mt-2 btn-register" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a> - </li> - % elif static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION')): - <li class="nav-item"> - <a class="nav-link mt-2" href="/register${login_query()}">${_("Register")}</a> - </li> - % endif - % endif - </ul> - <ul class="navbar-nav"> - <li class="nav-item"> - % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: - % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: - <a class="btn btn-primary mt-2" role="button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}"> - ${_("Sign in")} - </a> - % else: - <a class="btn btn-primary mt-2" role="button" href="/login${login_query()}"> - ${_("Sign in")} - </a> - % endif - % endif - </li> - </ul> -</div> diff --git a/lms/templates/navigation/navigation.html b/lms/templates/navigation/navigation.html index 26d43a9e5f1..77197d610b7 100644 --- a/lms/templates/navigation/navigation.html +++ b/lms/templates/navigation/navigation.html @@ -51,15 +51,15 @@ site_status_msg = get_site_status_msg(course_id) % if uses_bootstrap: <header class="navigation-container header-global ${'slim' if course else ''}"> - <nav class="navbar navbar-expand-lg navbar-light"> + <nav class="navbar navbar-expand-lg"> <%include file="bootstrap/navbar-logo-header.html" args="online_help_token=online_help_token"/> <button class="navbar-toggler navbar-toggler-right mt-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> % if user.is_authenticated(): - <%include file="bootstrap/navbar-authenticated.html" args="online_help_token=online_help_token"/> + <%include file="navbar-authenticated.html" args="online_help_token=online_help_token"/> % else: - <%include file="bootstrap/navbar-not-authenticated.html" args="online_help_token=online_help_token"/> + <%include file="navbar-not-authenticated.html" args="online_help_token=online_help_token"/> % endif </nav> </header> diff --git a/lms/templates/preview_menu.html b/lms/templates/preview_menu.html index d5de16c7b7a..822fadecced 100644 --- a/lms/templates/preview_menu.html +++ b/lms/templates/preview_menu.html @@ -27,7 +27,7 @@ show_preview_menu = course and staff_access and supports_preview_menu student_selected = selected(not staff_selected and not specific_student_selected and not masquerade_group_id) %> <nav class="wrapper-preview-menu" aria-label="${_('Course View')}"> - <div class="preview-menu"> + <div class="preview-menu container"> <ol class="preview-actions"> <li class="action-preview"> <form action="#" class="action-preview-form" method="post"> @@ -50,7 +50,7 @@ show_preview_menu = course and staff_access and supports_preview_menu <label for="action-preview-username" class="action-preview-label">${_("Username or email:")}</label> <input type="text" class="action-preview-username" id="action-preview-username"> </div> - <button type="submit" class="sr" name="submit" value="submit">${_("Set preview mode")}</button> + <button type="submit" class="sr-only" name="submit" value="submit">${_("Set preview mode")}</button> </form> </li> </ol> diff --git a/lms/templates/user_dropdown.html b/lms/templates/user_dropdown.html index 80bd8bdea6a..66bc256ea0a 100644 --- a/lms/templates/user_dropdown.html +++ b/lms/templates/user_dropdown.html @@ -5,6 +5,8 @@ ## This template should not use the target student's details when masquerading, see TNL-4895 <% self.real_user = getattr(user, 'real_user', user) +username = self.real_user.username +profile_image_url = get_profile_image_urls_for_user(self.real_user)['medium'] %> <%! @@ -14,34 +16,32 @@ from django.utils.translation import ugettext as _ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_urls_for_user %> % if uses_bootstrap: - <li class="nav-item nav-item-hidden-collapsed"> - <a href="${reverse('dashboard')}" class="menu-title"> - <span class="sr-only">${_("Dashboard for:")}</span> - <% profile_image_url = get_profile_image_urls_for_user(self.real_user)['medium'] %> - <img class="user-image-frame" src="${profile_image_url}" alt=""> - </a> - </li> - <li class="nav-item dropdown mt-2 nav-item-hidden-collapsed"> - <% username = self.real_user.username %> - <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${username}</a> - <ul class="dropdown-menu dropdown-menu-right" id="${_("Usermenu")}" aria-labelledby="dropdownMenuLink" tabindex="-1"> - <a class="dropdown-item" href="${reverse('dashboard')}">${_("Dashboard")}</a> - <a class="dropdown-item" href="${reverse('account_settings')}">${_("Account")}</a> - <a class="dropdown-item" href="${reverse('logout')}">${_("Sign Out")}</a> - </ul> - </li> - <li class="nav-item nav-item-open-collapsed-only collapse"><a href="${reverse('dashboard')}">${_("Dashboard")}</a></li> - <li class="nav-item nav-item-open-collapsed-only"><a href="${reverse('account_settings')}">${_("Account")}</a></li> - <li class="nav-item nav-item-open-collapsed-only"><a href="${reverse('logout')}">${_("Sign Out")}</a></li> + <div class="nav-item nav-item-hidden-collapsed container"> + <div class="nav align-items-center"> + <a class="menu-title mr-2" href="${reverse('dashboard')}"> + <span class="sr-only">${_("Dashboard for:")}</span> + <img class="user-image-frame" src="${profile_image_url}" alt="${username}"> + </a> + <div class="dropdown"> + <a class="dropdown-toggle" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">${username}</a> + <ul role="menu" class="dropdown-menu dropdown-menu-right" id="${_("Usermenu")}" aria-labelledby="dropdownMenuLink" tabindex="-1"> + <li role="presentation"><a role="menuitem" class="dropdown-item" href="${reverse('dashboard')}">${_("Dashboard")}</a></li> + <li role="presentation"><a role="menuitem" class="dropdown-item" href="${reverse('account_settings')}">${_("Account")}</a></li> + <li role="presentation"><a role="menuitem" class="dropdown-item" href="${reverse('logout')}">${_("Sign Out")}</a></li> + </ul> + </div> + </div> + </div> + <ul role="menu" class="nav flex-column align-items-center"> + <li role="presentation" class="nav-item nav-item-open-collapsed-only collapse"><a role="menuitem" href="${reverse('dashboard')}">${_("Dashboard")}</a></li> + <li role="presentation" class="nav-item nav-item-open-collapsed-only"><a role="menuitem" href="${reverse('account_settings')}">${_("Account")}</a></li> + <li role="presentation" class="nav-item nav-item-open-collapsed-only"><a role="menuitem" href="${reverse('logout')}">${_("Sign Out")}</a></li> + </ul> % elif uses_pattern_library: <div class="wrapper-user-menu dropdown-menu-container logged-in js-header-user-menu"> <a href="${reverse('dashboard')}" class="menu-title"> <span class="sr-only">${_("Dashboard for:")}</span> - <% - username = self.real_user.username - profile_image_url = get_profile_image_urls_for_user(self.real_user)['medium'] - %> - <img class="menu-image" src="${profile_image_url}" alt=""> + <img class="menu-image" src="${profile_image_url}" alt="${username}"> ${username} </a> <div role="group" aria-label="User menu" class="user-menu"> @@ -63,10 +63,6 @@ from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_ <li class="primary"> <a href="${reverse('dashboard')}" class="user-link"> <span class="sr">${_("Dashboard for:")}</span> - <% - username = self.real_user.username - profile_image_url = get_profile_image_urls_for_user(self.real_user)['medium'] - %> <img class="user-image-frame" src="${profile_image_url}" alt=""> <div class="label-username">${username}</div> </a> diff --git a/lms/templates/ux/reference/bootstrap/course-skeleton.html b/lms/templates/ux/reference/bootstrap/course-skeleton.html index 4230356d0e2..095ff23487d 100644 --- a/lms/templates/ux/reference/bootstrap/course-skeleton.html +++ b/lms/templates/ux/reference/bootstrap/course-skeleton.html @@ -10,68 +10,70 @@ <%block name="bodyclass">course-skeleton</%block> +<%! +from django.utils.translation import ugettext as _ +%> + <%block name="content"> -<nav class="navbar course-tabs pb-0 navbar-expand-lg navbar-light"> +<nav class="navbar course-tabs navbar-expand-lg"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> - <a class="nav-link" href="#">Course <span class="sr-only">(current)</span></a> + <a class="nav-link" href="#">${_('Course')} <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> - <a class="nav-link" href="#">Discussion</a> + <a class="nav-link" href="#">${_('Discussion')}</a> </li> <li class="nav-item"> - <a class="nav-link" href="#">Wiki</a> + <a class="nav-link" href="#">${_('Wiki')}</a> </li> <li class="nav-item"> - <a class="nav-link" href="#">Progress</a> + <a class="nav-link" href="#">${_('Progress')}</a> </li> </ul> </nav> -<section class="main-container"> - <div class="container-fluid"> - <div class="row page-header"> - <div class="col-md-7"> - <h2 class="hd hd-2 page-title">Skeleton Page</h2> - <p class="page-description">This demonstrates the pieces available to a courseware page.</p> - </div> - <div class="col-md-5"> - <div class="row"> - <div class="input-group col"> - <input type="text" class="form-control" placeholder="Search" aria-label="Search"/> - <span class="input-group-addon" id="basic-addon2">Search</span> - </div> - <a href="#"> - <div class="btn btn-primary">Click Me!!</div> - </a> - </div> - </div> +<div class="course-view page-content-container" id="course-container"> + <header class="page-header has-secondary"> + <div class="page-header-main"> + <nav class="sr-is-focusable" tabindex="-1"> + <h2 class="hd hd-3 page-title">${_('Skeleton Page')}</h2> + </nav> </div> - </div> - <div class="container-fluid"> - <div class="row page-content"> - <main id="main" aria-label="Content" tabindex="-1" class="col-md-8"> - <article tabindex="-1" aria-label="Main Content"> - <h3>Main content goes here.</h3> - <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis molestie, orci at viverra ornare, - augue urna fermentum ex, vitae dignissim magna est sit amet diam. Nunc sodales dolor finibus - pulvinar placerat. Suspendisse vitae tellus auctor, sodales erat ac, venenatis quam. Etiam - purus est, consequat nec erat vel, bibendum volutpat ex. Fusce vitae consectetur ante. - Suspendisse elit mauris, iaculis sed diam eu, efficitur tempor dui. Praesent tristique nunc - quam, in tincidunt ligula accumsan et. Etiam augue sem, commodo ac ipsum vel, fringilla dapibus - lacus. Sed facilisis euismod felis, non malesuada massa scelerisque sed. Etiam et placerat - lorem. Nullam quis tincidunt sapien.</p> - </article> - </main> - <div class="col-md-4"> - <h3>Sidebar</h3> - <ul> - <li>Item one</li> - <li>Item two</li> - <li>Item three</li> - </ul> + <div class="page-header-secondary"> + <div class="page-header-search"> + <form class="search-form" role="search" action="#"> + <label class="field-label sr-only" for="search" id="search-hint">${_('Search the course')}</label> + <input type="text" class="form-control" placeholder="Search" aria-label="Search"/> + <button class="btn btn-small search-button" type="submit">${_('Search')}</button> + </form> + </div> + <div class="form-actions"> + <button class="btn btn-brand">${_('Start Course')}</button> </div> </div> + </header> + <div class="page-content"> + <main id="main" aria-label="Content" tabindex="-1" class="page-content-main"> + <article tabindex="-1" aria-label="Main Content"> + <h3>Main content goes here.</h3> + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis molestie, orci at viverra ornare, + augue urna fermentum ex, vitae dignissim magna est sit amet diam. Nunc sodales dolor finibus + pulvinar placerat. Suspendisse vitae tellus auctor, sodales erat ac, venenatis quam. Etiam + purus est, consequat nec erat vel, bibendum volutpat ex. Fusce vitae consectetur ante. + Suspendisse elit mauris, iaculis sed diam eu, efficitur tempor dui. Praesent tristique nunc + quam, in tincidunt ligula accumsan et. Etiam augue sem, commodo ac ipsum vel, fringilla dapibus + lacus. Sed facilisis euismod felis, non malesuada massa scelerisque sed. Etiam et placerat + lorem. Nullam quis tincidunt sapien.</p> + </article> + </main> + <aside class="page-content-secondary"> + <h3>Sidebar</h3> + <ul> + <li>Item one</li> + <li>Item two</li> + <li>Item three</li> + </ul> + </aside> </div> -</section> +</div> </%block> diff --git a/lms/templates/ux/reference/bootstrap/unit-page.html b/lms/templates/ux/reference/bootstrap/unit-page.html index 313198034e2..73df0d1d7ee 100644 --- a/lms/templates/ux/reference/bootstrap/unit-page.html +++ b/lms/templates/ux/reference/bootstrap/unit-page.html @@ -18,7 +18,7 @@ </%block> <%block name="content"> -<nav class="navbar course-tabs pb-0 navbar-expand-lg navbar-light"> +<nav class="navbar course-tabs navbar-expand-lg"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="#">Course <span class="sr-only">(current)</span></a> diff --git a/openedx/features/course_bookmarks/templates/course_bookmarks/course-bookmarks.html b/openedx/features/course_bookmarks/templates/course_bookmarks/course-bookmarks.html index 22682d22003..25248dd6294 100644 --- a/openedx/features/course_bookmarks/templates/course_bookmarks/course-bookmarks.html +++ b/openedx/features/course_bookmarks/templates/course_bookmarks/course-bookmarks.html @@ -36,7 +36,7 @@ ${HTML(bookmarks_fragment.foot_html())} </%block> <%block name="content"> -<div class="course-view container" id="course-container"> +<div class="course-view page-content-container" id="course-container"> <header class="page-header has-secondary"> ## Breadcrumb navigation <div class="page-header-main"> diff --git a/openedx/features/course_experience/__init__.py b/openedx/features/course_experience/__init__.py index a7c48a506c0..abddebae279 100644 --- a/openedx/features/course_experience/__init__.py +++ b/openedx/features/course_experience/__init__.py @@ -40,6 +40,9 @@ UPGRADE_DEADLINE_MESSAGE = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'upgrade_dead # flag even for Superusers. LATEST_UPDATE_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'latest_update') +# Waffle flag to enable the use of Bootstrap for course experience pages +USE_BOOTSTRAP_FLAG = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'use_bootstrap') + def course_home_page_title(course): # pylint: disable=unused-argument """ diff --git a/openedx/features/course_experience/static/course_experience/fixtures/course-home-fragment.html b/openedx/features/course_experience/static/course_experience/fixtures/course-home-fragment.html index 39998df788d..b6650d25b3c 100644 --- a/openedx/features/course_experience/static/course_experience/fixtures/course-home-fragment.html +++ b/openedx/features/course_experience/static/course_experience/fixtures/course-home-fragment.html @@ -1,4 +1,4 @@ -<div class="course-view container" id="course-container"> +<div class="course-view page-content-container" id="course-container"> <header class="page-header has-secondary"> <div class="page-header-main"> <nav aria-label="Course Outline" class="sr-is-focusable" tabindex="-1"> @@ -20,7 +20,7 @@ </form> </div> <div class="form-actions"> - <a class="btn btn-brand action-resume-course" href="/courses/course-v1:edX+DemoX+Demo_Course/courseware/19a30717eff543078a5d94ae9d6c18a5/"> + <a class="btn btn-primary action-resume-course" href="/courses/course-v1:edX+DemoX+Demo_Course/courseware/19a30717eff543078a5d94ae9d6c18a5/"> <span data-action-type="start">Start Course</span> </a> </div> @@ -88,7 +88,7 @@ </main> <aside class="course-sidebar layout-col layout-col-a"> <div class="section section-tools"> - <h3 class="hd-6">Course Tools</h3> + <h3 class="hd-6 section-title">Course Tools</h3> <ul class="list-unstyled"> <li> <a class="course-tool-link" data-analytics-id="edx.bookmarks" href="/courses/course-v1:W3Cx+HTML5.0x+1T2017/bookmarks/"> @@ -111,7 +111,7 @@ </ul> </div> <div class="section section-dates"> - <h3 class="hd hd-6 handouts-header">Important Course Dates</h3> + <h3 class="hd hd-6 section-title handouts-header">Important Course Dates</h3> <div class="date-summary-container"> <div class="date-summary date-summary-todays-date"> <span class="hd hd-6 heading localized-datetime" data-datetime="2017-07-13 17:31:27.952061+00:00" data-string="Today is {date}" data-timezone="None" data-language="en">Today is Jul 13, 2017 13:31 EDT</span> diff --git a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html index 6659929563b..c86f44b0f99 100644 --- a/openedx/features/course_experience/templates/course_experience/course-home-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-home-fragment.html @@ -18,7 +18,7 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REV %> <%block name="content"> -<div class="course-view container" id="course-container"> +<div class="course-view page-content-container" id="course-container"> <header class="page-header has-secondary"> <div class="page-header-main"> <nav aria-label="${_('Course Outline')}" class="sr-is-focusable" tabindex="-1"> @@ -43,7 +43,7 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REV % endif <div class="form-actions"> % if resume_course_url: - <a class="btn btn-brand action-resume-course" href="${resume_course_url}"> + <a class="btn btn-primary action-resume-course" href="${resume_course_url}"> % if has_visited_course: <span data-action-type="resume">${_("Resume Course")}</span> % else: @@ -55,110 +55,108 @@ from openedx.features.course_experience import UNIFIED_COURSE_TAB_FLAG, SHOW_REV </div> </header> <div class="page-content"> - <div class="layout layout-1t2t"> - <main class="layout-col layout-col-b"> - - % if upgrade_url and upgrade_price: - <div class="section"> - <div class="vc-message tex2jax_ignore" role="group" aria-labelledby="vc-title" tabindex="-1" style="display: none;"> - - <h3 class="vc-title vc-fade vc-polite-only">Pursue a verified certificate</h3> - - <button class="vc-toggle vc-fade vc-polite-only btn-link" type="button" aria-controls="moreinfo" - aria-expanded="true" aria-label="${_("Show/Hide")}"> - ${_("Show less")} - </button> - - <div class="vc-hero vc-fade"> - <img src="${static.url('course_experience/images/verified-cert.png')}" - alt="${_("Sample verified certificate with your name, the course title, the logo of the institution and the signatures of the instructors for this course.")}"/> - </div> - - <ul class="vc-selling-points vc-fade"> - <li class="vc-selling-point">${_("Official proof of completion")}</li> - <li class="vc-selling-point">${_("Easily shareable certificate")}</li> - <li class="vc-selling-point">${_("Proven motivator to complete the course")}</li> - <li class="vc-selling-point">${_("Certificate purchases help us continue to offer free courses")}</li> - </ul> - - <div class="vc-cta vc-fade vc-polite-only"> - <a class="btn-upgrade" - href="${ upgrade_url }" - data-creative="hero_matthew_smith" - data-position="hero">${_("Upgrade ({price})").format(price=upgrade_price)}</a> - </div> + <main class="page-content-main"> + + % if upgrade_url and upgrade_price: + <div class="section"> + <div class="vc-message tex2jax_ignore" role="group" aria-labelledby="vc-title" tabindex="-1" style="display: none;"> + + <h3 class="vc-title vc-fade vc-polite-only">Pursue a verified certificate</h3> + + <button class="vc-toggle vc-fade vc-polite-only btn-link" type="button" aria-controls="moreinfo" + aria-expanded="true" aria-label="${_("Show/Hide")}"> + ${_("Show less")} + </button> + + <div class="vc-hero vc-fade"> + <img src="${static.url('course_experience/images/verified-cert.png')}" + alt="${_("Sample verified certificate with your name, the course title, the logo of the institution and the signatures of the instructors for this course.")}"/> </div> - </div> - % endif - % if course_home_message_fragment: - ${HTML(course_home_message_fragment.body_html())} - % endif + <ul class="vc-selling-points vc-fade"> + <li class="vc-selling-point">${_("Official proof of completion")}</li> + <li class="vc-selling-point">${_("Easily shareable certificate")}</li> + <li class="vc-selling-point">${_("Proven motivator to complete the course")}</li> + <li class="vc-selling-point">${_("Certificate purchases help us continue to offer free courses")}</li> + </ul> - % if update_message_fragment and UNIFIED_COURSE_TAB_FLAG.is_enabled(course.id): - <div class="section section-update-message"> - ${HTML(update_message_fragment.body_html())} + <div class="vc-cta vc-fade vc-polite-only"> + <a class="btn-upgrade" + href="${ upgrade_url }" + data-creative="hero_matthew_smith" + data-position="hero">${_("Upgrade ({price})").format(price=upgrade_price)}</a> + </div> </div> - % endif + </div> + % endif - % if outline_fragment: - ${HTML(outline_fragment.body_html())} - % endif - </main> - <aside class="course-sidebar layout-col layout-col-a"> - % if has_goal_permission: - <div class="section section-goals ${'' if current_goal else 'hidden'}"> - <div class="current-goal-container"> - <label class="title title-label hd-6" for="goal"> - <h3 class="hd-6">${_("Goal: ")}</h3> - </label> - <h3 class="title hd-6">${_("Goal: ")}</h3> - <div class="goal"> - <span class="text">${goal_options[current_goal.goal_key] if current_goal else ""}</span> - </div> - <select class="edit-goal-select" id="goal"> - % for goal, goal_text in goal_options.items(): - <option value="${goal}" ${"selected" if current_goal and current_goal.goal_key == goal else ""}>${goal_text}</option> - % endfor - </select> - <span class="sr sr-update-response-msg" aria-live="polite"></span> - <span class="response-icon" aria-hidden="true"></span> - <span class="sr">${_("Edit your course goal:")}</span> - <button class="edit-icon"> - <span class="sr">${_("Edit your course goal:")}</span> - <span class="fa fa-pencil" aria-hidden="true"></span> - </button> + % if course_home_message_fragment: + ${HTML(course_home_message_fragment.body_html())} + % endif + + % if update_message_fragment and UNIFIED_COURSE_TAB_FLAG.is_enabled(course.id): + <div class="section section-update-message"> + ${HTML(update_message_fragment.body_html())} + </div> + % endif + + % if outline_fragment: + ${HTML(outline_fragment.body_html())} + % endif + </main> + <aside class="page-content-secondary course-sidebar"> + % if has_goal_permission: + <div class="section section-goals ${'' if current_goal else 'hidden'}"> + <div class="current-goal-container"> + <label class="title title-label hd-6" for="goal"> + <h3 class="hd-6">${_("Goal: ")}</h3> + </label> + <h3 class="title hd-6">${_("Goal: ")}</h3> + <div class="goal"> + <span class="text">${goal_options[current_goal.goal_key] if current_goal else ""}</span> </div> - </div> - % endif - % if course_tools: - <div class="section section-tools"> - <h3 class="hd-6">${_("Course Tools")}</h3> - <ul class="list-unstyled"> - % for course_tool in course_tools: - <li class="course-tool"> - <a class="course-tool-link" data-analytics-id="${course_tool.analytics_id()}" href="${course_tool.url(course_key)}"> - <span class="icon ${course_tool.icon_classes()}" aria-hidden="true"></span> - ${course_tool.title()} - </a> - </li> + <select class="edit-goal-select" id="goal"> + % for goal, goal_text in goal_options.items(): + <option value="${goal}" ${"selected" if current_goal and current_goal.goal_key == goal else ""}>${goal_text}</option> % endfor - </ul> - </div> - % endif - % if dates_fragment: - <div class="section section-dates"> - ${HTML(dates_fragment.body_html())} - </div> - % endif - % if handouts_html: - <div class="section section-handouts"> - <h3 class="hd-6">${_("Course Handouts")}</h3> - ${HTML(handouts_html)} + </select> + <span class="sr sr-update-response-msg" aria-live="polite"></span> + <span class="response-icon" aria-hidden="true"></span> + <span class="sr">${_("Edit your course goal:")}</span> + <button class="edit-icon"> + <span class="sr">${_("Edit your course goal:")}</span> + <span class="fa fa-pencil" aria-hidden="true"></span> + </button> </div> - % endif - </aside> - </div> + </div> + % endif + % if course_tools: + <div class="section section-tools"> + <h3 class="hd-6 section-title">${_("Course Tools")}</h3> + <ul class="list-unstyled"> + % for course_tool in course_tools: + <li class="course-tool"> + <a class="course-tool-link" data-analytics-id="${course_tool.analytics_id()}" href="${course_tool.url(course_key)}"> + <span class="icon ${course_tool.icon_classes()}" aria-hidden="true"></span> + ${course_tool.title()} + </a> + </li> + % endfor + </ul> + </div> + % endif + % if dates_fragment: + <div class="section section-dates"> + ${HTML(dates_fragment.body_html())} + </div> + % endif + % if handouts_html: + <div class="section section-handouts"> + <h3 class="hd-6 section-title">${_("Course Handouts")}</h3> + ${HTML(handouts_html)} + </div> + % endif + </aside> </div> % if course_sock_fragment: ${HTML(course_sock_fragment.body_html())} diff --git a/openedx/features/course_experience/templates/course_experience/course-messages-fragment.html b/openedx/features/course_experience/templates/course_experience/course-messages-fragment.html index 99fdb263fa0..020e08e0ec5 100644 --- a/openedx/features/course_experience/templates/course_experience/course-messages-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-messages-fragment.html @@ -17,7 +17,7 @@ is_rtl = get_language_bidi() % if course_home_messages: % for message in course_home_messages: - <div class="course-message grid-manual"> + <div class="course-message"> % if not is_rtl: <img class="message-author" alt="" src="${static.url(image_src)}"/> % endif diff --git a/openedx/features/course_experience/templates/course_experience/course-reviews-fragment.html b/openedx/features/course_experience/templates/course_experience/course-reviews-fragment.html index 631463c0173..7bfbed43f94 100644 --- a/openedx/features/course_experience/templates/course_experience/course-reviews-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-reviews-fragment.html @@ -12,7 +12,7 @@ from openedx.features.course_experience import course_home_page_title %> -<div class="course-reviews container" tabindex="-1"> +<div class="course-reviews page-content-container" tabindex="-1"> <header class="page-header has-secondary"> ## Breadcrumb navigation <div class="page-header-main"> @@ -28,7 +28,7 @@ from openedx.features.course_experience import course_home_page_title </div> </nav> % if is_enrolled: - <div class="btn toggle-read-write-reviews"></div> + <div class="btn btn-secondary toggle-read-write-reviews"></div> % endif </div> </header> diff --git a/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html b/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html index 6e881dd8b4e..54d61b7ba0c 100644 --- a/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-sock-fragment.html @@ -15,7 +15,7 @@ from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG style="display: none" %endif > - <button type="button" class="btn btn-brand focusable action-toggle-verification-sock"> + <button type="button" class="btn btn-primary focusable action-toggle-verification-sock"> Learn About Verified Certificates </button> <div class="verification-main-panel"> diff --git a/openedx/features/course_experience/templates/course_experience/course-updates-fragment.html b/openedx/features/course_experience/templates/course_experience/course-updates-fragment.html index 76926c3daa2..7b7d2dfe579 100644 --- a/openedx/features/course_experience/templates/course_experience/course-updates-fragment.html +++ b/openedx/features/course_experience/templates/course_experience/course-updates-fragment.html @@ -11,7 +11,7 @@ from openedx.features.course_experience import course_home_page_title %> <%block name="content"> -<div class="course-updates container" id="course-container"> +<div class="course-updates page-content-container" id="course-container"> <header class="page-header has-secondary"> ## Breadcrumb navigation <div class="page-header-main"> diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index 2729748e923..42e3c3cb213 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -27,7 +27,7 @@ from student.models import CourseEnrollment from util.views import ensure_valid_course_key from web_fragments.fragment import Fragment -from .. import LATEST_UPDATE_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME +from .. import LATEST_UPDATE_FLAG, SHOW_UPGRADE_MSG_ON_COURSE_HOME, USE_BOOTSTRAP_FLAG from ..utils import get_course_outline_block_tree from .course_dates import CourseDatesFragmentView from .course_home_messages import CourseHomeMessageFragmentView @@ -52,6 +52,9 @@ class CourseHomeView(CourseTabView): """ return super(CourseHomeView, self).get(request, course_id, 'courseware', **kwargs) + def uses_bootstrap(self, request, course): + return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = unicode(course.id) home_fragment_view = CourseHomeFragmentView() diff --git a/openedx/features/course_experience/views/course_reviews.py b/openedx/features/course_experience/views/course_reviews.py index 08ac07fd889..5c552e06f8f 100644 --- a/openedx/features/course_experience/views/course_reviews.py +++ b/openedx/features/course_experience/views/course_reviews.py @@ -16,12 +16,13 @@ from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience import default_course_url_name +from .. import USE_BOOTSTRAP_FLAG + class CourseReviewsView(CourseTabView): """ The course reviews page. """ - @method_decorator(login_required) @method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True)) def get(self, request, course_id, **kwargs): @@ -30,6 +31,9 @@ class CourseReviewsView(CourseTabView): """ return super(CourseReviewsView, self).get(request, course_id, 'courseware', **kwargs) + def uses_bootstrap(self, request, course): + return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = unicode(course.id) reviews_fragment_view = CourseReviewsFragmentView() diff --git a/openedx/features/course_experience/views/course_updates.py b/openedx/features/course_experience/views/course_updates.py index b1a99256f06..2a1c9656291 100644 --- a/openedx/features/course_experience/views/course_updates.py +++ b/openedx/features/course_experience/views/course_updates.py @@ -17,6 +17,8 @@ from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.course_experience import default_course_url_name +from .. import USE_BOOTSTRAP_FLAG + STATUS_VISIBLE = 'visible' STATUS_DELETED = 'deleted' @@ -53,7 +55,6 @@ class CourseUpdatesView(CourseTabView): """ The course updates page. """ - @method_decorator(login_required) @method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True)) def get(self, request, course_id, **kwargs): @@ -62,6 +63,9 @@ class CourseUpdatesView(CourseTabView): """ return super(CourseUpdatesView, self).get(request, course_id, 'courseware', **kwargs) + def uses_bootstrap(self, request, course): + return USE_BOOTSTRAP_FLAG.is_enabled(course.id) + def render_to_fragment(self, request, course=None, tab=None, **kwargs): course_id = unicode(course.id) updates_fragment_view = CourseUpdatesFragmentView() diff --git a/openedx/features/course_search/templates/course_search/course-search-fragment.html b/openedx/features/course_search/templates/course_search/course-search-fragment.html index b211f2d97f3..99467cc7576 100644 --- a/openedx/features/course_search/templates/course_search/course-search-fragment.html +++ b/openedx/features/course_search/templates/course_search/course-search-fragment.html @@ -19,7 +19,7 @@ from openedx.features.course_experience import course_home_page_title %> <%block name="content"> -<div class="course-view container" id="course-container"> +<div class="course-view pzge-content-container" id="course-container"> <header class="page-header has-secondary"> <div class="page-header-main"> <nav aria-label="${_('Search Results')}" class="sr-is-focusable" tabindex="-1"> diff --git a/openedx/features/learner_profile/templates/learner_profile/learner-achievements-fragment.html b/openedx/features/learner_profile/templates/learner_profile/learner-achievements-fragment.html index c6c3d3f6752..f62b279d938 100644 --- a/openedx/features/learner_profile/templates/learner_profile/learner-achievements-fragment.html +++ b/openedx/features/learner_profile/templates/learner_profile/learner-achievements-fragment.html @@ -87,4 +87,3 @@ from openedx.core.djangolib.markup import HTML, Text <%static:require_module_async module_name="js/dateutil_factory" class_name="DateUtilFactory"> DateUtilFactory.transform('.localized-datetime'); </%static:require_module_async> - diff --git a/package.json b/package.json index e4cb5fe792d..d4c241246d5 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "coffee-loader": "^0.7.3", "coffee-script": "1.6.1", "@edx/studio-frontend": "0.1.0", - "edx-bootstrap": "^0.2.1", + "@edx/edx-bootstrap": "0.3.3", "edx-pattern-library": "0.18.1", "edx-ui-toolkit": "1.5.2", "exports-loader": "^0.6.4", diff --git a/pavelib/assets.py b/pavelib/assets.py index 282372d9f8e..a199ff8adbf 100644 --- a/pavelib/assets.py +++ b/pavelib/assets.py @@ -43,8 +43,8 @@ SYSTEMS = { COMMON_LOOKUP_PATHS = [ path("common/static"), path("common/static/sass"), + path('node_modules/@edx'), path('node_modules'), - path('node_modules/edx-pattern-library/node_modules'), ] # A list of NPM installed libraries that should be copied into the common diff --git a/pavelib/paver_tests/test_assets.py b/pavelib/paver_tests/test_assets.py index aa710e0f52d..7859d26339f 100644 --- a/pavelib/paver_tests/test_assets.py +++ b/pavelib/paver_tests/test_assets.py @@ -151,8 +151,8 @@ class TestPaverWatchAssetTasks(TestCase): self.expected_sass_directories = [ path('common/static/sass'), path('common/static'), + path('node_modules/@edx'), path('node_modules'), - path('node_modules/edx-pattern-library/node_modules'), path('lms/static/sass/partials'), path('lms/static/sass'), path('lms/static/certificates/sass'), diff --git a/themes/edx.org/lms/templates/header.html b/themes/edx.org/lms/templates/header.html index 069f874aa1e..a86e8c336e8 100644 --- a/themes/edx.org/lms/templates/header.html +++ b/themes/edx.org/lms/templates/header.html @@ -54,47 +54,36 @@ site_status_msg = get_site_status_msg(course_id) % if uses_bootstrap: <nav class="navbar navbar-expand-lg navbar-light" aria-label="${_('Main')}"> - <h1 class="hd logo-header"> - <div class="logo"> - <a class="navbar-brand" href="${reverse('dashboard')}" itemprop="url"> - <img src="${static.url("images/logo.png")}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}" itemprop="logo" /> - </a> - </div> - % if course and not disable_courseware_header: - <div class="course-header"> - <span class="provider">${course.display_org_with_default}:</span> - <span class="course-number">${course.display_number_with_default}</span> - <span class="course-name">${course.display_name_with_default}</span> - </div> - % endif - </h1> - <button class="navbar-toggler navbar-toggler-right mt-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> - <span class="navbar-toggler-icon"></span> + <%include file="/header/brand.html" /> + + <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon" aria-hidden="true"></span> </button> % if user.is_authenticated(): <div class="collapse navbar-collapse" id="navbarSupportedContent"> - % if not course or disable_courseware_header: - % if not nav_hidden or show_dashboard_tabs: - <ul class="navbar-nav mr-auto"> + <div class="navbar-nav align-items-center ml-auto"> + % if not course or disable_courseware_header: + % if not nav_hidden or show_dashboard_tabs: + <ul class="nav align-items-center"> % if not nav_hidden: - <li class="nav-item mt-2 nav-item-open-collapsed nav-global-01"> + <li class="nav-item nav-item-open-collapsed nav-global-01"> <a class="nav-link" href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a> </li> - <li class="nav-item mt-2 nav-item-open-collapsed nav-global-02"> + <li class="nav-item nav-item-open-collapsed nav-global-02"> <a class="nav-link" href="${marketing_link('COURSES')}">${_("Find Courses")}</a> </li> - <li class="nav-item mt-2 nav-item-open-collapsed nav-global-03"> + <li class="nav-item nav-item-open-collapsed nav-global-03"> <a class="nav-link" href="${marketing_link('SCHOOLS')}">${_("Schools & Partners")}</a> </li> % endif % if show_dashboard_tabs: - <li class="nav-item mt-2 nav-item-open-collapsed"> + <li class="nav-item nav-item-open-collapsed"> <a class="${'active' if reverse('dashboard') == request.path else ''} nav-link" href="${reverse('dashboard')}"> ${_("Courses")} </a> </li> % if show_program_listing: - <li class="nav-item mt-2 nav-item-open-collapsed"> + <li class="nav-item nav-item-open-collapsed"> <a class="${'active' if reverse('program_listing_view') in request.path else ''} nav-link" href="${reverse('program_listing_view')}"> ${_("Programs")} </a> @@ -104,76 +93,64 @@ site_status_msg = get_site_status_msg(course_id) self.real_user = getattr(user, 'real_user', user) is_on_profile_page = data and data.get('profile_user_id') is not None %> - <li class="nav-item mt-2 nav-item-open-collapsed"> + <li class="nav-item nav-item-open-collapsed"> <a class="${'active ' if is_on_profile_page else ''}tab-nav-link" href="${reverse('learner_profile', args=[self.real_user.username])}"> ${_("Profile")} </a> </li> - % endif - </ul> - % endif - % endif - <ul class="navbar-nav navbar-right"> - % if should_display_shopping_cart_func(): # see shoppingcart.context_processor.user_has_cart_context_processor - <a role="button" class="nav-item-open-collapsed btn-shopping-cart btn btn-secondary mr-3" href="${reverse('shoppingcart.views.show_cart')}"> - <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} - </a> + % endif + </ul> + % endif % endif - <li class="nav-item mt-2 nav-item-open-collapsed"> - <a href="${get_online_help_info(online_help_token)['doc_url']}" - target="_blank" - class="nav-link">${_("Help")}</a> - </li> - <%include file="user_dropdown.html"/> + <ul class="nav align-items-center"> + % if should_display_shopping_cart_func(): # see shoppingcart.context_processor.user_has_cart_context_processor + <li> + <a class="nav-item-open-collapsed btn-shopping-cart btn btn-secondary mr-3" href="${reverse('shoppingcart.views.show_cart')}"> + <span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")} + </a> + </li> + % endif + <li class="nav-item nav-item-open-collapsed"> + <a href="${get_online_help_info(online_help_token)['doc_url']}" + target="_blank" + class="nav-link">${_("Help")}</a> + </li> </ul> + <%include file="user_dropdown.html"/> </div> + </div> % else: <div class="collapse navbar-collapse" id="navbarSupportedContent" aria-label="${_('Account')}" > - <ul class="navbar-nav mr-auto"></ul> - <ul class="navbar-nav"> - <li class="nav-item"> + <div class="navbar-nav align-items-center ml-auto"> + <ul> % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: - <a class="btn btn-primary mt-2" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a> - % else: - <a class="btn btn-primary mt-2" href="/login${login_query()}">${_("Sign in")}</a> + <li class="nav-item"> + <a class="nav-link" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a> + </li> + % elif static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION')): + <li> + <a class="nav-link" href="/register">${_("Register")}</a> + </li> % endif % endif - </li> - % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: - % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: <li class="nav-item"> - <a class="nav-link mt-2" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a> - </li> - % elif static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION')): - <li> - <a class="nav-link mt-2" href="/register">${_("Register")}</a> + % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: + % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: + <a class="btn btn-primary" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a> + % else: + <a class="btn btn-primary" href="/login${login_query()}">${_("Sign in")}</a> + % endif + % endif </li> - % endif - % endif - </ul> + </ul> + </div> </div> % endif </nav> % else: <div class="${"rwd" if responsive else ""} wrapper-header nav-container"> - <h1 class="hd logo-header"> - <div class="logo"> - <a href="${marketing_link('ROOT')}" itemprop="url"> - <%block name="navigation_logo"> - <img src="${static.url("images/logo.png")}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}" itemprop="logo" /> - </%block> - </a> - </div> - - % if course and not disable_courseware_header: - <div class="course-header"> - <span class="provider">${course.display_org_with_default}:</span> - <span class="course-number">${course.display_number_with_default}</span> - <span class="course-name">${course.display_name_with_default}</span> - </div> - % endif - </h1> + <%include file="/header/brand.html" /> % if user.is_authenticated(): % if not course or disable_courseware_header: @@ -240,26 +217,26 @@ site_status_msg = get_site_status_msg(course_id) % else: <nav aria-label="${_('Account')}" class="nav-account-management"> <div class="right nav-courseware list-inline"> - <div class="item nav-courseware-01"> - % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: - % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: - <a class="btn btn-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a> - % else: - <a class="btn btn-login" href="/login${login_query()}">${_("Sign in")}</a> - % endif - % endif - </div> % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: <div class="item nav-courseware-02"> - <a class="btn btn-neutral btn-register" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a> + <a class="btn btn-register" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a> </div> % elif static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION')): <div class="item nav-courseware-02"> - <a class="btn btn-neutral btn-register" href="/register">${_("Register")}</a> + <a class="btn btn-register" href="/register">${_("Register")}</a> </div> % endif % endif + <div class="item nav-courseware-01"> + % if not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register: + % if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain: + <a class="btn btn-primary btn-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a> + % else: + <a class="btn btn-primary btn-login" href="/login${login_query()}">${_("Sign in")}</a> + % endif + % endif + </div> </div> </nav> % endif diff --git a/themes/red-theme/lms/static/sass/partials/bootstrap/_theme.scss b/themes/red-theme/lms/static/sass/partials/bootstrap/_theme.scss index 3c857145f17..8ecfca16928 100644 --- a/themes/red-theme/lms/static/sass/partials/bootstrap/_theme.scss +++ b/themes/red-theme/lms/static/sass/partials/bootstrap/_theme.scss @@ -25,3 +25,7 @@ $theme-colors: map-merge(( light: $gray-100, dark: $gray-800 ), $theme-colors); + +// Note: for some reason this doesn't obey the primary color as defined above. +// This shouldn't be necessary but it appears to be. +$link-color: $red; -- GitLab