Commit 3d79e3e0 by Harry Rein

Adding unified, responsive header.

parent c27c3930
......@@ -2170,7 +2170,7 @@ def record_registration_attributions(request, user):
def create_account(request, post_override=None):
"""
JSON call to create new edX account.
Used by form in signup_modal.html, which is included into navigation.html
Used by form in signup_modal.html, which is included into header.html
"""
# Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation
if not configuration_helpers.get_value(
......
......@@ -215,7 +215,7 @@ class DashboardPage(PageObject):
"""
Return list username dropdown links.
"""
return self.q(css='.user-dropdown-menu li a').text
return self.q(css='.user-dropdown-menu a').text
@property
def tabs_link_text(self):
......@@ -234,7 +234,7 @@ class DashboardPage(PageObject):
"""
Click on `Account` link.
"""
self.q(css='.user-dropdown-menu li a').nth(2).click()
self.q(css='.user-dropdown-menu a').nth(1).click()
@property
def language_selector(self):
......
/**
* Ensuring collapsible and accessible components on multiple
* screen sizes for the responsive lms header.
*/
function createMobileMenu() {
/**
* Dynamically create a mobile menu from all specified mobile links
* on the page.
*/
'use strict';
$('.mobile-nav-item').each(function() {
var mobileNavItem = $(this).clone().addClass('mobile-nav-link');
mobileNavItem.attr('role', 'menuitem');
// xss-lint: disable=javascript-jquery-append
$('.mobile-menu').append(mobileNavItem);
});
}
$(document).ready(function() {
'use strict';
var $hamburgerMenu;
var $mobileMenu;
// Toggling visibility for the user dropdown
$('.toggle-user-dropdown').click(function() {
var $dropdownMenu = $('.global-header .nav-item .dropdown-user-menu');
var $userMenu = $('.user-dropdown');
if ($dropdownMenu.is(':visible')) {
$dropdownMenu.hide();
$userMenu.attr('aria-expanded', 'false');
} else {
$dropdownMenu.show();
$dropdownMenu.find('.dropdown-item')[0].focus();
$userMenu.attr('aria-expanded', 'true');
}
$('.toggle-user-dropdown').toggleClass('open');
});
// Toggling menu visibility with the hamburger menu
$('.hamburger-menu').click(function() {
$hamburgerMenu = $('.hamburger-menu');
$mobileMenu = $('.mobile-menu');
if ($mobileMenu.is(':visible')) {
$mobileMenu.hide();
$hamburgerMenu.attr('aria-expanded', 'false');
} else {
$mobileMenu.show();
$hamburgerMenu.attr('aria-expanded', 'true');
}
$hamburgerMenu.toggleClass('open');
});
// Hide hamburger menu if no nav items (sign in and register pages)
if ($('.mobile-nav-item').size() === 0) {
$('.hamburger-menu').css('display', 'none');
}
createMobileMenu();
});
// Ensure click away hides the user dropdown
$(window).click(function(e) {
'use strict';
if (!$(e.target).is('.dropdown-item, .toggle-user-dropdown')) {
$('.global-header .nav-item .dropdown-user-menu').hide();
}
});
// Accessibility keyboard controls for user dropdown and mobile menu
$(document).on('keydown', function(e) {
'use strict';
var isNext;
var nextLink;
var loopFirst;
var loopLast;
var isLastItem = $(e.target).parent().is(':last-child');
var isToggle = $(e.target).hasClass('toggle-user-dropdown');
var isHamburgerMenu = $(e.target).hasClass('hamburger-menu');
var isMobileOption = $(e.target).parent().hasClass('mobile-nav-link');
var isDropdownOption = !isMobileOption && $(e.target).parent().hasClass('dropdown-item');
var $userMenu = $('.user-dropdown');
var $hamburgerMenu = $('.hamburger-menu');
var $toggleUserDropdown = $('.toggle-user-dropdown');
// Open or close relevant menu on enter or space click and focus on first element.
if ((e.keyCode === 13 || e.keyCode === 32) && (isToggle || isHamburgerMenu)) {
$(e.target).click();
if (isHamburgerMenu) {
if ($('.mobile-menu').is(':visible')) {
$hamburgerMenu.attr('aria-expanded', true);
$('.mobile-menu .mobile-nav-link a').first().focus();
} else {
$hamburgerMenu.attr('aria-expanded', false);
}
} else if (isToggle) {
if ($('.global-header .nav-item .dropdown-user-menu').is(':visible')) {
$userMenu.attr('aria-expanded', 'true');
$('.dropdown-item a:first').focus();
} else {
$userMenu.attr('aria-expanded', false);
}
}
// Don't allow for double click or page jump on Firefox browser
e.preventDefault();
e.stopPropagation();
}
// Enable arrow functionality within the menu.
if (e.keyCode === 38 || e.keyCode === 40 && (isDropdownOption || isMobileOption ||
(isHamburgerMenu && $hamburgerMenu.hasClass('open')) || isToggle && $toggleUserDropdown.hasClass('open'))) {
isNext = e.keyCode === 40;
if (isNext && !isHamburgerMenu && !isToggle && isLastItem) {
// Loop to the start from the final element
nextLink = isDropdownOption ? $toggleUserDropdown : $hamburgerMenu;
} else if (!isNext && (isHamburgerMenu || isToggle)) {
// Loop to the end when up arrow pressed from menu icon
nextLink = isHamburgerMenu ? $('.mobile-menu .mobile-nav-link a').last()
: $('.dropdown-user-menu .dropdown-nav-item').last().find('a');
} else if (isNext && (isHamburgerMenu || isToggle)) {
// Loop to the first element from the menu icon
nextLink = isHamburgerMenu ? $('.mobile-menu .mobile-nav-link a').first()
: $('.dropdown-user-menu .dropdown-nav-item').first().find('a');
} else {
// Loop up to the menu icon if first element in menu
if (!isNext && $(e.target).parent().is(':first-child') && !isHamburgerMenu && !isToggle) {
nextLink = isDropdownOption ? $toggleUserDropdown : $hamburgerMenu;
} else {
nextLink = isNext ?
$(e.target).parent().next().find('a') : // eslint-disable-line newline-per-chained-call
$(e.target).parent().prev().find('a'); // eslint-disable-line newline-per-chained-call
}
}
nextLink.focus();
// Don't let the screen scroll on navigation
e.preventDefault();
e.stopPropagation();
}
// Escape clears out of the menu
if (e.keyCode === 27 && (isDropdownOption || isHamburgerMenu || isMobileOption || isToggle)) {
if (isDropdownOption || isToggle) {
$('.global-header .nav-item .dropdown-user-menu').hide();
$toggleUserDropdown.focus();
$userMenu.attr('aria-expanded', 'false');
$('.toggle-user-dropdown').removeClass('open');
} else {
$('.mobile-menu').hide();
$hamburgerMenu.focus();
$hamburgerMenu.attr('aria-expanded', 'false');
$hamburgerMenu.removeClass('open');
}
}
// Loop when tabbing and using arrows
if ((e.keyCode === 9) && ((isDropdownOption && isLastItem) || (isMobileOption && isLastItem) || (isHamburgerMenu
&& $hamburgerMenu.hasClass('open')) || (isToggle && $toggleUserDropdown.hasClass('open')))) {
nextLink = null;
loopFirst = isLastItem && !e.shiftKey && !isHamburgerMenu && !isToggle;
loopLast = (isHamburgerMenu || isToggle) && e.shiftKey;
if (!(loopFirst || loopLast)) {
return;
}
if (isDropdownOption || isToggle) {
nextLink = loopFirst ? $toggleUserDropdown : $('.dropdown-user-menu .dropdown-nav-item a').last();
} else {
nextLink = loopFirst ? $hamburgerMenu : $('.mobile-menu .mobile-nav-link a').last();
}
nextLink.focus();
e.preventDefault();
}
});
......@@ -8,6 +8,15 @@
@import 'base/mixins';
@import 'base/theme';
// edX Bootstrap theme and variables support
@import 'bootstrap/theme';
@import 'bootstrap/variables';
// Core Bootstrap functions, variables and mixins
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins/breakpoints';
// Pattern Library shims
@import 'edx-pattern-library-shims/base/variables';
@import 'edx-pattern-library-shims/buttons';
......@@ -3,11 +3,14 @@
// 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
// edX Bootstrap theme and variables support
@import 'bootstrap/theme';
@import 'bootstrap/variables';
// Core Bootstrap functions, variables and mixins
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import "bootstrap/scss/mixins/breakpoints";
@import 'bootstrap/scss/mixins/breakpoints';
// Base
@import 'base/base';
......@@ -75,6 +78,7 @@
// responsive
@import 'base/layouts'; // temporary spot for responsive course
@import 'header';
// features
@import 'features/course-sock';
......@@ -3,12 +3,6 @@
// 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';
......@@ -18,6 +12,15 @@
// base - starter
@import 'base/base';
// edX Bootstrap theme and variables support
@import 'bootstrap/theme';
@import 'bootstrap/variables';
// Core Bootstrap functions, variables and mixins
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins/breakpoints';
// Pattern Library shims
@import 'edx-pattern-library-shims/base/variables';
@import 'edx-pattern-library-shims/breadcrumbs';
......@@ -85,6 +88,9 @@
@import 'mixins-inherited';
@import 'elements/system-feedback';
// Responsive Design
@import 'header';
// overrides
@import 'developer'; // used for any developer-created scss that needs further polish/refactoring
@import 'shame'; // used for any bad-form/orphaned scss
......
......@@ -2,11 +2,14 @@
// LMS: Shared Build Compile
// Version 2 - introduces the Pattern Library
// Bootstrap support for use with shared partials
// edX Bootstrap theme and variables support
@import 'bootstrap/theme';
@import 'bootstrap/variables';
// Core Bootstrap functions, variables and mixins
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import "bootstrap/scss/mixins/breakpoints";
@import 'bootstrap/scss/mixins/breakpoints';
// Configuration
@import 'config';
......@@ -36,3 +39,6 @@
@import 'features/course-search';
@import 'features/course-sock';
@import 'features/course-upgrade-message';
// Responsive Design
@import 'header';
/**
This file contains all the necessary styling for a uniform
navigation bar that can exist on any of the v1, v2 or bootstrap
pages.
*/
.global-header {
box-sizing: border-box;
width: 100%;
overflow: hidden;
padding-bottom: $baseline/2;
border-bottom: 1px solid theme-color("primary");
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.1);
background: theme-color("inverse");
/*
Logo and course identification block
*/
.header-logo {
display: inline;
a {
@include float(left);
@include margin($baseline/2, 0, 0, $baseline);
display: block;
.logo {
@include float(left);
width: $header-logo-width;
}
@include media-breakpoint-down(sm) {
margin-left: calc(50% - 30px);
height: $header-logo-height;
width: auto;
}
}
.course-header {
@include float(left);
@include margin($baseline, 0, 0, $baseline);
font-size: $font-size-lg;
color: theme-color("dark");
line-height: 1em;
display: none;
.provider {
font-weight: $font-weight-bold;
}
// Hide the course header for smaller screen sizes
@include media-breakpoint-up(md) {
display: block;
}
}
}
/*
Main navigation buttons for Courses, programs, profile and explore buttons.
There are two stylings for the two circumstances, first the mobile, followed
by the desktop styling
*/
// Desktop styling
@include media-breakpoint-up(md) {
.nav-links {
.nav-item {
margin: 0 $baseline;
a {
text-decoration: none;
}
}
.main {
@include float(left);
@include margin($baseline, 0, 0, $baseline);
.nav-item {
@include float(left);
}
.nav-tab {
text-transform: none;
padding: 0;
cursor: pointer;
margin: 0;
a {
color: theme-color("secondary");
padding: $baseline*0.35 $baseline*1.25 $baseline*0.75;
font-weight: $font-weight-normal;
display: inline-block;
margin-bottom: -1*$baseline/2;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active,
&:hover {
border-bottom-color: theme-color("dark");
}
&:hover {
cursor: pointer;
border-bottom-color: theme-color("primary");
}
}
}
}
.secondary {
@include float(right);
margin: $baseline*0.6 $baseline 0 0;
// All navigation items
.nav-item {
font-size: $font-size-base;
display: inline-block;
padding: $baseline/2 0 0;
margin: 0 $baseline/2;
a {
color: theme-color("dark");
font-weight: $font-weight-bold;
}
}
// Sign in, Register and Shopping Cart buttons
.btn {
border: 1px solid theme-color("primary");
padding: $baseline/4 $baseline;
border-radius: $baseline/4;
cursor: pointer;
text-decoration: none;
}
a.sign-in-btn,
.nav-item a.shopping-cart {
background-color: theme-color("primary");
color: theme-color("inverse");
border: 1px solid theme-color("inverse");
font-weight: $font-weight-normal;
padding: $baseline/4 $baseline;
&:hover {
background-color: theme-color("inverse");
color: theme-color("primary");
border-color: theme-color("primary");
}
}
a.register-btn {
background: theme-color("inverse");
color: theme-color("primary");
font-weight: $font-weight-normal;
&:hover {
background-color: theme-color("primary");
color: theme-color("inverse");
}
}
// User information
.user-image-frame {
border: 1px solid theme-color("light");
margin: -1*$baseline/2 $baseline/4;
border-radius: $baseline/4;
width: $header-user-image-size;
}
// Dropdown behavior
.toggle-user-dropdown {
text-decoration: none;
cursor: pointer;
}
.dropdown-user-menu {
display: none;
border: 1px solid theme-color("secondary");
position: absolute;
background-color: theme-color("inverse");
color: theme-color("secondary");
right: 30px;
top: 55px;
z-index: 10;
.dropdown-item {
cursor: pointer;
overflow: hidden;
padding: 0;
&:hover {
color: theme-color("dark");
background-color: theme-color("light");
}
&:not(:last-child) {
border-bottom: 1px solid theme-color("light");
}
a {
font-weight: $font-weight-base;
padding: $baseline/2 $baseline*0.75;
display: inline-block;
width: 100%;
&:focus {
outline: none;
color: theme-color("dark");
background-color: theme-color("light");
}
}
}
}
}
}
.hamburger-menu {
display: none;
}
}
// Responsive styling for mobile
@include media-breakpoint-down(sm) {
// Display the menu icon and allow for transition to an X on click
.hamburger-menu {
@include left(22px);
position: absolute;
top: $baseline;
width: 30px;
height: 20px;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transition: 0.5s ease-in-out;
transition: 0.5s ease-in-out;
cursor: pointer;
outline: none;
&:focus,
&:hover {
span {
background: theme-color("primary");
height: 3px;
}
}
span {
display: block;
position: absolute;
height: 2px;
width: 100%;
background: theme-color("secondary");
border-radius: 9px;
opacity: 1;
left: 0;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transition: 0.25s ease-in-out;
transition: 0.25s ease-in-out;
&:nth-child(1) {
top: 0;
}
&:nth-child(2),
&:nth-child(3) {
top: 6px;
}
&:nth-child(4) {
top: 12px;
}
}
&.open span {
&:nth-child(1) {
top: 18px;
width: 0%;
left: 50%;
}
&:nth-child(2) {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
&:nth-child(3) {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
&:nth-child(4) {
top: 18px;
width: 0%;
left: 50%;
}
}
}
}
}
/*
Mobile menu styling
*/
.mobile-menu {
border-bottom: 1px solid theme-color('primary');
@include media-breakpoint-up(md) {
display: none !important;
}
@include media-breakpoint-down(sm) {
display: none;
// Override standard styling for the mobile menu links
.mobile-nav-link {
position: static;
transform: none;
a {
font-size: $font-size-base;
font-weight: 600;
color: theme-color('dark');
text-decoration: none;
outline: none;
display: block;
background-color: theme-color('inverse');
border-radius: 0;
width: 100%;
padding: $baseline*0.6 $baseline;
border-bottom: 1px solid theme-color('light');
text-align: left;
cursor: pointer;
&:hover,
&:focus {
background-color: theme-color('dark');
color: theme-color('inverse');
}
&::after {
content: '\00BB';
padding-left: 4px;
}
}
}
}
}
// Hide elements in menu bar when they exist in mobile
.hidden-mobile {
@include media-breakpoint-down(sm) {
&:not(.mobile-nav-link) {
display: none;
}
}
}
......@@ -254,10 +254,17 @@ mark {
&:focus,
&:active {
position: relative;
top: auto;
@include left(50%);
@include margin-left(-1 * $baseline * 1.5);
position: absolute;
top: $baseline/4;
width: auto;
height: auto;
background-color: black;
margin: 0;
opacity: 0.8;
color: white !important;
text-decoration: none !important;
outline: none;
}
}
......@@ -5,3 +5,11 @@
// #UNITS
// ----------------------------
$baseline: 20px !default;
// ----------------------------
// #COMPONENT SIZING
// ----------------------------
$header-logo-width: 60px !default;
$header-logo-height: 40px !default;
$header-user-image-size: 40px !default;
......@@ -32,3 +32,6 @@
// Individual Pages
@import "views/program-marketing-page";
// Responsive Design
@import '../header';
......@@ -4,11 +4,14 @@
// Set the relative path to the static root
$static-path: '../..' !default;
// Bootstrap support for use with shared partials
// edX Bootstrap theme and variables support
@import 'bootstrap/theme';
@import 'bootstrap/variables';
// Core Bootstrap functions, variables and mixins
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import "bootstrap/scss/mixins/breakpoints";
@import 'bootstrap/scss/mixins/breakpoints';
// Configuration
@import '../config';
......
......@@ -11,7 +11,6 @@
border-bottom: 1px solid $border-color-3;
box-shadow: inset 0 1px 5px 0 $shadow-l1;
height: 280px;
margin-top: $header_image_margin;
padding-top: 150px;
overflow: hidden;
position: relative;
......
......@@ -14,10 +14,19 @@
&:focus,
&:active {
position: relative;
top: auto;
width: auto;
height: auto;
margin: 0;
@include left(50%);
@include margin-left(-6.5em)
margin-top: 0;
padding: 10px 0.5em;
text-align: center;
position: absolute;
width: 12em;
z-index: 1050;
top: 0;
background-color: $black !important;
opacity: 0.8;
color: $white !important;
text-decoration: none;
outline: none;
}
}
## mako
<%page expression_filter="h" args="online_help_token"/>
<%namespace name='static' file='static_content.html'/>
<%include file="${static.get_template_path(relative_path='navigation/navigation.html')}" args="online_help_token=online_help_token" />
<%include file="${static.get_template_path(relative_path='header/header.html')}" args="online_help_token=online_help_token" />
## mako
<%page expression_filter="h" args="online_help_token"/>
<%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 _
from lms.djangoapps.ccx.overrides import get_current_ccx
from openedx.core.djangolib.markup import HTML, Text
# App that handles subdomain specific branding
from branding import api as branding_api
# app that handles site status messages
from status.status import get_site_status_msg
from openedx.core.djangoapps.lang_pref.api import header_language_selector_is_enabled, released_languages
# Waffle flag to enable and disable the responsive header
from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
RESPONSIVE_HEADER_ENABLED = WaffleFlag(WaffleFlagNamespace(name='lms'), 'responsive_header_enabled')
%>
## Provide a hook for themes to inject branding on top.
<%block name="navigation_top" />
## Add UI Toolkit components if using the Pattern Library
% if uses_pattern_library:
<%block name="js_extra">
<%static:require_module module_name="js/header_factory" class_name="HeaderFactory">
HeaderFactory();
</%static:require_module>
</%block>
% endif
<%block>
<%
course_id = course.id if course else None
site_status_msg = get_site_status_msg(course_id)
%>
% if site_status_msg:
<div class="site-status">
<div class="inner-wrapper">
<span class="icon fa fa-warning"></span>
<p>${site_status_msg}</p>
</div>
</div>
% endif
</%block>
% if RESPONSIVE_HEADER_ENABLED.is_enabled():
<header class="global-header ${'slim' if course else ''}">
<%include file="navbar-logo-header.html" args="online_help_token=online_help_token"/>
<div class="hamburger-menu" role="button" aria-label="Options Menu" aria-hidden="true" aria-expanded="false" aria-controls="mobile-menu" tabindex="0"><span></span><span></span><span></span><span></span></div>
% if user.is_authenticated():
<%include file="navbar-authenticated.html" args="online_help_token=online_help_token"/>
% else:
<%include file="navbar-not-authenticated.html" args="online_help_token=online_help_token"/>
% endif
</header>
<div class="mobile-menu" aria-label="More Options" role="menu" id="mobile-menu"></div>
% elif uses_bootstrap:
<header class="navigation-container header-global ${'slim' if course else ''}">
<nav class="navbar navbar-expand-lg">
<%include file="../navigation/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="../navigation/bootstrap/navbar-authenticated.html" args="online_help_token=online_help_token"/>
% else:
<%include file="navbar-not-authenticated.html" args="online_help_token=online_help_token"/>
% endif
</nav>
</header>
% else:
<header id="global-navigation" class="header-global ${"slim" if course else ""}" >
<nav class="wrapper-header" aria-label="${_('Global')}">
<%include file="../navigation/navbar-logo-header.html" args="online_help_token=online_help_token"/>
% if user.is_authenticated():
<%include file="../navigation/navbar-authenticated.html" args="online_help_token=online_help_token"/>
% else:
<%include file="../navigation/navbar-not-authenticated.html" args="online_help_token=online_help_token"/>
% endif
% if header_language_selector_is_enabled():
<% languages = released_languages() %>
% if len(languages) > 1:
<ol class="user">
<li class="primary">
<form action="/i18n/setlang/" method="post" class="settings-language-form" id="language-settings-form">
<input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="${csrf_token}">
% if user.is_authenticated():
<input title="preference api" type="hidden" class="url-endpoint" value="${reverse('preferences_api', kwargs={'username': user.username})}" data-user-is-authenticated="true">
% else:
<input title="session update url" type="hidden" class="url-endpoint" value="${reverse('session_language')}" data-user-is-authenticated="false">
% endif
<label><span class="sr">${_("Choose Language")}</span>
<select class="input select language-selector" id="settings-language-value" name="language">
% for language in languages:
% if language[0] == LANGUAGE_CODE:
<option value="${language[0]}" selected="selected">${language[1]}</option>
% else:
<option value="${language[0]}" >${language[1]}</option>
% endif
% endfor
</select>
</label>
</form>
</li>
</ol>
% endif
% endif
</nav>
</header>
% endif
% if course:
<!--[if lte IE 9]>
<div class="ie-banner" aria-hidden="true">${Text(_('{begin_strong}Warning:{end_strong} Your browser is not fully supported. We strongly recommend using {chrome_link} or {ff_link}.')).format(
begin_strong=HTML('<strong>'),
end_strong=HTML('</strong>'),
chrome_link=HTML('<a href="https://www.google.com/chrome" target="_blank">Chrome</a>'),
ff_link=HTML('<a href="http://www.mozilla.org/firefox" target="_blank">Firefox</a>'),
)}</div>
<![endif]-->
% endif
<%include file="../help_modal.html"/>
% if settings.FEATURES.get('ENABLE_COOKIE_CONSENT', False):
<%include file="../widgets/cookie-consent.html" />
% endif
## 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 _
%>
<%
show_explore_courses = settings.FEATURES.get('COURSES_ARE_BROWSABLE') and not show_program_listing
show_sysadmin_dashboard = settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD','') and user.is_staff
self.real_user = getattr(user, 'real_user', user)
%>
<div class="nav-links">
<%block name="navigation_global_links_authenticated">
<div class="main">
% if show_dashboard_tabs:
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if reverse('dashboard') == request.path else ''}tab-nav-link" href="${reverse('dashboard')}">
${_("Courses")}
</a>
</div>
% if show_program_listing:
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if '/u/' in request.path else ''}tab-nav-link" href="${reverse('learner_profile', args=[self.real_user.username])}">
${_("Profile")}
</a>
</div>
% endif
% if show_explore_courses:
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="btn" href="${marketing_link('COURSES')}">${_('Discover New')}</a>
</div>
% endif
% if show_sysadmin_dashboard:
<div class="mobile-nav-item hidden-mobile nav-item">
## Translators: This is short for "System administration".
<a class="btn" href="${reverse('sysadmin')}">${_("Sysadmin")}</a>
</div>
% endif
</div>
<div class="secondary">
% 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
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="shopping-cart" href="${reverse('shoppingcart.views.show_cart')}">
<span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")}
</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${get_online_help_info(online_help_token)['doc_url']}" target="_blank">${_("Help")}</a>
</div>
<%include file="user_dropdown.html"/>
</div>
</%block>
</div>
## mako
<%page expression_filter="h" args="online_help_token"/>
<%namespace name='static' file='../static_content.html'/>
<%!
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from lms.djangoapps.ccx.overrides import get_current_ccx
# App that handles subdomain specific branding
from branding import api as branding_api
%>
<h1 class="header-logo">
<a href="${reverse('dashboard')}">
<%block name="navigation_logo">
<img class="logo" src="${branding_api.get_logo_url(is_secure)}" alt="${_("{platform_name} Home Page").format(platform_name=static.get_platform_name())}"/>
</%block>
</a>
% 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
</h1>
## 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 _
%>
<%
mktg_site_enabled = static.get_value('ENABLE_MKTG_SITE', settings.FEATURES.get('ENABLE_MKTG_SITE', False))
courses_are_browsable = settings.FEATURES.get('COURSES_ARE_BROWSABLE')
allows_login = not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register
can_discover_courses = settings.FEATURES.get('ENABLE_COURSE_DISCOVERY')
restrict_enroll_for_course = course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain
allow_public_account_creation = static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION'))
%>
<nav class="nav-links">
<div class="main">
% if mktg_site_enabled:
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a>
</div>
% if courses_are_browsable:
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('COURSES')}">${_("Courses")}</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('SCHOOLS')}">${_("Schools")}</a>
</div>
% endif
% if allows_login:
% if can_discover_courses:
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="/courses">${_('Explore courses')}</a>
</div>
%endif
% endif
</div>
<div class="secondary">
<div>
% if allows_login:
% if restrict_enroll_for_course:
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="register-btn btn" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a>
</div>
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="sign-in-btn btn" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
</div>
% else:
% if allow_public_account_creation:
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="register-btn btn" href="/register${login_query()}">${_("Register")}</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="sign-in-btn btn" href="/login${login_query()}">${_("Sign in")}</a>
</div>
% endif
% endif
</div>
</div>
</nav>
## mako
<%page expression_filter="h"/>
<%namespace name='static' file='static_content.html'/>
## This template should not use the target student's details when masquerading, see TNL-4895
<%
self.real_user = getattr(user, 'real_user', user)
%>
<%!
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_urls_for_user
%>
<%
profile_image_url = get_profile_image_urls_for_user(self.real_user)['medium']
username = self.real_user.username
%>
<div class="nav-item hidden-mobile">
<a href="${reverse('dashboard')}" class="menu-title">
<img class="user-image-frame" src="${profile_image_url}" alt="">
<span class="sr-only">${_("Dashboard for:")}</span>
<span class="username">${username}</span>
</a>
</div>
<div class="nav-item hidden-mobile" tabindex="-1">
<div class="user-dropdown" aria-expanded="false" aria-haspopup="true" aria-controls="user-menu">
<span class="sr">user menu</span>
<span class="fa fa-caret-down toggle-user-dropdown" aria-hidden="true" tabindex="0"></span>
</div>
<div class="dropdown-user-menu" aria-label="More Options" role="menu" id="user-menu" tabindex="-1">
<div class="dropdown-item dropdown-nav-item"><a href="${reverse('dashboard')}" role="menuitem">${_("Dashboard")}</a></div>
<div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${reverse('account_settings')}" role="menuitem">${_("Account")}</a></div>
<div class="mobile-nav-item dropdown-item dropdown-nav-item"><a href="${reverse('logout')}" role="menuitem">${_("Sign Out")}</a></div>
</div>
</div>
......@@ -14,7 +14,7 @@ from xmodule.tabs import CourseTabList
% if settings.FEATURES.get('ENABLE_FEEDBACK_SUBMISSION', False):
<div class="help-tab">
<div class="help-tab hidden-mobile">
<a href="#help-modal" rel="leanModal" role="button">${_("Support")}</a>
</div>
......
......@@ -176,6 +176,7 @@ from pipeline_mako import render_require_js_path_overrides
<%include file="widgets/segment-io-footer.html" />
<script type="text/javascript" src="${static.url('js/vendor/noreferrer.js')}" charset="utf-8"></script>
<script type="text/javascript" src="${static.url('js/utils/navigation.js')}" charset="utf-8"></script>
<script type="text/javascript" src="${static.url('js/header/header.js')}"></script>
<%static:optional_include_mako file="body-extra.html" is_theming_enabled="True" />
</body>
</html>
......
## 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" 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>
## mako
## This navigation has been deprecated in favor of the responsive header found in header/header.html
## To use this new header, change the include statement in your templates/header.html file to import
## the header/header.html file as opposed to the navigation/navigation.html file.
<%page expression_filter="h" args="online_help_token"/>
<%namespace name='static' file='../static_content.html'/>
......@@ -18,6 +22,8 @@ from status.status import get_site_status_msg
from openedx.core.djangoapps.lang_pref.api import header_language_selector_is_enabled, released_languages
%>
<script type="text/javascript" src="${static.url('js/header/header.js')}"></script>
## Provide a hook for themes to inject branding on top.
<%block name="navigation_top" />
......@@ -49,6 +55,7 @@ site_status_msg = get_site_status_msg(course_id)
% endif
</%block>
% if uses_bootstrap:
<header class="navigation-container header-global ${'slim' if course else ''}">
<nav class="navbar navbar-expand-lg">
......
## 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 _
%>
<%
courses_are_browsable = settings.FEATURES.get('COURSES_ARE_BROWSABLE')
show_explore_courses = settings.FEATURES.get('COURSES_ARE_BROWSABLE') and not show_program_listing
show_sysadmin_dashboard = settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD','') and user.is_staff
self.real_user = getattr(user, 'real_user', user)
%>
<div class="nav-links">
<%block name="navigation_global_links_authenticated">
<div class="main">
% if not course or disable_courseware_header:
% if not nav_hidden:
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('HOW_IT_WORKS')}">${_("How it Works")}</a>
</div>
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('COURSES')}">${_("Find Courses")}</a>
</div>
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${marketing_link('SCHOOLS')}">${_("Schools & Partners")}</a>
</div>
% endif
% if show_dashboard_tabs:
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if reverse('dashboard') == request.path else ''}tab-nav-link" href="${reverse('dashboard')}">
${_("Courses")}
</a>
</div>
% if show_program_listing:
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if reverse('program_listing_view') in request.path else ''}tab-nav-link" href="${reverse('program_listing_view')}">
${_("Programs")}
</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item nav-tab">
<a class="${'active ' if '/u/' in request.path else ''}tab-nav-link" href="${reverse('learner_profile', args=[self.real_user.username])}">
${_("Profile")}
</a>
</div>
% endif
% endif
</div>
<div class="secondary">
% 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
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="shopping-cart" href="${reverse('shoppingcart.views.show_cart')}">
<span class="icon fa fa-shopping-cart" aria-hidden="true"></span> ${_("Shopping Cart")}
</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item">
<a href="${get_online_help_info(online_help_token)['doc_url']}" target="_blank">${_("Help")}</a>
</div>
<%include file="user_dropdown.html"/>
</div>
</%block>
</div>
## 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 _
%>
<%
allows_login = not settings.FEATURES['DISABLE_LOGIN_BUTTON'] and not combined_login_and_register
can_discover_courses = settings.FEATURES.get('ENABLE_COURSE_DISCOVERY')
restrict_enroll_for_course = course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain
allow_public_account_creation = static.get_value('ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION'))
%>
<nav class="nav-links">
<div class="secondary">
<div>
% if allows_login:
% if restrict_enroll_for_course:
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="register-btn btn" href="${reverse('course-specific-register', args=[course.id.to_deprecated_string()])}">${_("Register")}</a>
</div>
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="sign-in-btn btn" role="button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
</div>
% else:
% if allow_public_account_creation:
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="register-btn btn" href="/register${login_query()}">${_("Register")}</a>
</div>
% endif
<div class="mobile-nav-item hidden-mobile nav-item">
<a class="sign-in-btn btn" role="button" href="/login${login_query()}">${_("Sign in")}</a>
</div>
% endif
% endif
</div>
</div>
</nav>
......@@ -14,7 +14,7 @@ $font-family-sans-serif: cursive;
@import 'edx-bootstrap/sass/open-edx/theme';
// Override the theme to use red as primary
$theme-colors: ();
$theme-colors: () !default;
$theme-colors: map-merge((
primary: $red,
secondary: $gray-600,
......
## mako
<!--
To override this page, add a navigation.html file in the following
location: {your_theme}/lms/templates/navigation/navigation.html
To override this page, add a header.html file in the following
location: {your_theme}/lms/templates/header/header.html.html.
If you do not wish to override the header, you can simply delete
this file from your theme's repository.
-->
<%page expression_filter="h" args="online_help_token"/>
<%namespace name='static' file='static_content.html'/>
<%include file="${static.get_template_path(relative_path='navigation/navigation.html')}" args="online_help_token=online_help_token" />
<%include file="${static.get_template_path(relative_path='header/header.html')}" args="online_help_token=online_help_token" />
## mako
<%namespace name='static' file='/static_content.html'/>
<%inherit file="/navigation/navigation.html"/>
<%inherit file="/header/header.html"/>
<%page expression_filter="h"/>
## TODO: this will eventually be moved to the Sass
<%block name="navigation_logo">
......
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