Convert course home page to Bootstrap

LEARNER-1694

Fix a11y failure

Fix header styling

Fix layout issues

Further layout fixes
This commit is contained in:
Andy Armstrong
2017-09-27 20:33:27 -04:00
parent db6570b754
commit 374cdb0a3d
53 changed files with 795 additions and 689 deletions

View File

@@ -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">

View File

@@ -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
"""

View File

@@ -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>

View File

@@ -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">
<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;">
% 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>
<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>
<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>
<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
% 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="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>
</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>
% endfor
<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>
</div>
% endif
% if dates_fragment:
<div class="section section-dates">
${HTML(dates_fragment.body_html())}
</div>
% endif
% 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>
<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>
</div>
% endif
% if handouts_html:
<div class="section section-handouts">
<h3 class="hd-6">${_("Course Handouts")}</h3>
${HTML(handouts_html)}
</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())}

View File

@@ -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

View File

@@ -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>

View File

@@ -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">

View File

@@ -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">

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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">

View File

@@ -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>