Commit 3f7d8bc9 by Matt Tuchfarber Committed by GitHub

Merge pull request #16187 from edx/tuchfarber/program_marketing

Rewrite program marketing page to use Bootstrap and change design to look more like other marketing design
parents 12e1af27 946421c4
...@@ -864,6 +864,8 @@ def program_marketing(request, program_uuid): ...@@ -864,6 +864,8 @@ def program_marketing(request, program_uuid):
if program.get('is_learner_eligible_for_one_click_purchase') and skus: if program.get('is_learner_eligible_for_one_click_purchase') and skus:
context['buy_button_href'] = ecommerce_service.get_checkout_page_url(*skus) context['buy_button_href'] = ecommerce_service.get_checkout_page_url(*skus)
context['uses_bootstrap'] = True
return render_to_response('courseware/program_marketing.html', context) return render_to_response('courseware/program_marketing.html', context)
......
function initializeCourseSlider() { function playVideo(src) {
'use strict'; 'use strict';
var isMobileResolution = $(window).width() <= 767, document.querySelector('#program_video button').style = 'display:none;';
sliderExists = $('.course-slider-xs').hasClass('slick-slider'); document.querySelector('#program_video iframe').style = 'display:block;';
$('.course-card').toggleClass('slidable', isMobileResolution); document.querySelector('#program_video iframe').src = src;
if (isMobileResolution) { // Second condition will avoid the multiple calls from resize
$('.copy-meta-mobile').show();
$('.copy-meta').hide();
if (!sliderExists) {
$('.course-slider-xs').slick({
arrows: false,
centerMode: true,
centerPadding: '40px',
slidesToShow: 1
});
}
} else {
$('.copy-meta').show();
$('.copy-meta-mobile').hide();
if (sliderExists) {
$('.course-slider-xs').slick('unslick');
$('.course-slider-xs').html();
$('.slick-arrow, .pageInfo').hide();
}
}
} }
function paginate(page, size, total) {
'use strict';
var start = size * page,
end = (start + size - 1) >= total ? total - 1 : (start + size - 1);
$('.profile-item-desktop').each(function(index, item) {
if (index >= start && index <= end) {
$(item).css('display', 'block');
} else {
$(item).css('display', 'none');
}
});
$('.pagination-start').text(start + 1);
$('.pagination-end').text(end + 1);
}
$.fn.getFocusableChildren = function() {
'use strict';
return $(this)
/* eslint max-len: 0 */
.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object:not([disabled]), embed, *[tabindex], *[contenteditable]')
.filter(':visible');
};
$(document).ready(function() {
'use strict';
// Create MutationObserver which prevents the body of
// the page from scrolling when a modal window is displayed
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if ($(mutation.target).css('display') === 'block') {
$('body').css('overflow', 'hidden');
} else {
$('body').css('overflow', 'auto');
}
});
});
// Custom function showing current slide
var $status = $('.pagingInfo');
var $slickElement = $('.course-slider-xs');
// Instructor pagination
var page = 0,
size = 4,
total = parseInt($('.instructor-size').text(), 10),
maxPages = Math.ceil(total / size) - 1;
paginate(page, size, total);
initializeCourseSlider();
// In order to restrict focus, we added two pseudo <a> elements, one before the instructor modal and one after.
// When reaching the first <a>, we focus the last element in the dialog.
// If there is no focusable element, we focus the close button.
// When focusing the last <a>, we focus the first control in the dialog.
$('.focusKeeper:even').on('focus', function(event) {
event.preventDefault();
if ($(this).parent().find('.modal-body')
.getFocusableChildren().length) {
$(this).parent().find('.modal-body')
.getFocusableChildren()
.filter(':last')
.focus();
} else {
$(this).parent().find('.modal_close a')
.focus();
}
});
$('.focusKeeper:odd').on('focus', function(event) {
event.preventDefault();
$(this).parent().find('.modal_close a')
.focus();
});
$(window).resize(function() {
initializeCourseSlider();
});
// Initialize instructor bio modals
$('.instructor-image, .instructor-label').leanModal({closeButton: '.modal_close', top: '10%'});
$('.modal').each(function(index, element) {
observer.observe(element, {attributes: true, attributeFilter: ['style']});
});
$slickElement.on('init reInit afterChange', function(event, slick, currentSlide) {
// currentSlide is undefined on init -- set it to 0 in this case (currentSlide is 0 based)
var i = currentSlide || 1;
$status.text(i + ' of ' + slick.slideCount);
});
// Initialize FAQ
$('ul.faq-links-list li.item').click(function() {
if ($(this).find('.answer').hasClass('hidden')) {
$(this).find('.answer').removeClass('hidden');
$(this).addClass('expanded');
} else {
$(this).find('.answer').addClass('hidden');
$(this).removeClass('expanded');
}
});
if (page < maxPages) {
$('#pagination-next').addClass('active');
$('#pagination-next > span.sr').attr('aria-hidden', 'false');
}
$('#pagination-next').click(function() {
if (page === maxPages) {
return false;
}
if (page + 1 === maxPages) {
$(this).removeClass('active');
$(this).children('span.sr').attr('aria-hidden', 'true');
}
page = page + 1;
paginate(page, size, total);
$('#pagination-previous').addClass('active');
$('#pagination-previous > span.sr').attr('aria-hidden', 'false');
return false;
});
$('#pagination-previous').click(function() {
if (page === 0) {
return false;
}
if (page - 1 === 0) {
$(this).removeClass('active');
$(this).children('span.sr').attr('aria-hidden', 'true');
}
page = page - 1;
paginate(page, size, total);
$('#pagination-next').addClass('active');
$('#pagination-next > span.sr').attr('aria-hidden', 'false');
return false;
});
$('#accordion-group').accordion({
header: '> .accordion-item > .accordion-head',
collapsible: true,
active: false,
heightStyle: 'content'
});
});
...@@ -36,6 +36,3 @@ ...@@ -36,6 +36,3 @@
@import 'features/course-search'; @import 'features/course-search';
@import 'features/course-sock'; @import 'features/course-sock';
@import 'features/course-upgrade-message'; @import 'features/course-upgrade-message';
// Views
@import "views/program-marketing-page";
...@@ -27,3 +27,6 @@ ...@@ -27,3 +27,6 @@
@import 'features/course-search'; @import 'features/course-search';
@import 'features/course-sock'; @import 'features/course-sock';
@import 'features/course-upgrade-message'; @import 'features/course-upgrade-message';
// Individual Pages
@import "views/program-marketing-page";
/* Box shadow mixin */ #program-details-page {
// example: @include box-shadow(2px, 3px, 6px, rgba(0, 0, 0, 0.3)); font-size: 16px;
@mixin box-shadow($x, $y, $blur, $color, $inset: false) {
@if $inset {
-webkit-box-shadow: inset $x $y $blur $color;
-moz-box-shadow: inset $x $y $blur $color;
box-shadow: inset $x $y $blur $color;
}
@else {
-webkit-box-shadow: $x $y $blur $color;
-moz-box-shadow: $x $y $blur $color;
box-shadow: $x $y $blur $color;
}
}
#program-details-page {
.main-banner {
height: 260px;
background: palette(primary, dark);
margin-bottom: 20px;
position: relative;
@media (max-width: 767px){
padding: 0 12px 25px;
height: auto;
}
@media (min-width: 768px) {
height: 333px;
margin-bottom: 20px;
}
@media (min-width: 1024px) {
margin-bottom: 50px
}
.btn-play {
background-image: none;
background-color: transparent;
box-shadow: none;
padding: 0;
margin-left: -moz-calc((100% - 74px) / 2);
margin-left: -webkit-calc((100% - 74px) / 2);
margin-left: calc((100% - 74px) / 2);
margin-top: 125px;
margin-bottom: 94px;
height: 74px;
width: 74px;
color: #fff;
background: none;
border: 4px solid #fff;
border-radius: 50%;
.icon {
padding-left: 8px;
}
&:hover {
opacity: 0.7;
outline: none;
}
}
.org-logo {
display: inline-block;
position: relative;
overflow: hidden;
margin-bottom: 8px;
background: rgba(255, 255, 255, 0.8);
@include box-shadow(0, 3px, 4px, rgba(0, 0, 0, 0.5));
@media (max-width: 767px) {
margin-bottom: 12px;
max-width: 120px;
box-shadow: none;
}
@media (min-width: 768px) {
max-width: 150px;
position: absolute;
top: 0;
}
@media (min-width: 1024px) {
max-width: 200px;
}
img {
max-width: 100%;
max-height: 95px;
}
&::after {
content: "";
position: absolute;
top: 0;
left: -2px;
right: -2px;
box-shadow: 0 1px 3px #333;
height: 1px;
background: #a1a5a5;
z-index: 1;
}
}
.banner-title,
.banner-description {
color: $white;
}
.banner-title {
font-size: 1.5em;
font-weight: 600;
text-align: left;
letter-spacing: inherit;
margin-bottom: 10px;
@media (min-width: 768px) {
margin-top: 105px;
font-size: 1.9em;
}
@media (min-width: 1024px) {
font-size: 2em;
}
@media (min-width: 1280px) {
font-size: 2.25em;
}
}
.banner-description {
min-height: 60px;
font-size: 1.06em;
font-weight: 600;
line-height: 1.35em;
@media (max-width: 767px) {
margin-bottom: 14px;
font-weight: normal;
}
@media (min-width: 768px) {
font-size: 1.1em;
}
@media (min-width: 1024px) {
font-size: 1.25em;
}
}
.grid-manual, .row{
@media (max-width: 767px){
display: block;
}
}
.grid-manual{
.btn-start{
min-width: 300px;
padding: 0.75rem 2rem;
font-size: 1.25rem;
text-decoration: none;
text-align: center;
font-weight: 600;
border-radius: 0;
background: #008100;
background: -moz-linear-gradient(top, #008100 0%, #0a570a 100%);
background: -webkit-linear-gradient(top, #008100 0%,#0a570a 100%);
background: linear-gradient(to bottom, #008100 0%,#0a570a 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#008100', endColorstr='#0a570a',GradientType=0);
border: 0;
&:hover {
background: -moz-linear-gradient(top, #006200 0%, #006200 100%);
background: -webkit-linear-gradient(top, #006200 0%,#006200 100%);
background: linear-gradient(to bottom, #006200 0%,#006200 100%);
}
}
}
}
.left-col,
.right-col {
@media (min-width: 768px) {
padding: 0 0 15px;
}
@media (min-width: 1024px) {
padding: 15px 0;
}
}
.left-col {
@media (min-width: 768px) {
border-right: 1px solid #979797;
padding-right: 20px;
}
@media (min-width: 1024px) {
padding-right: 50px;
}
}
.right-col {
@media (min-width: 768px) {
padding-left: 0;
}
@media (min-width: 1024px) {
padding-left: 30px;
}
}
.courses-in-program .course-card .tbl-view .tbl-col:first-child{
width: 70% !important;
@media (max-width: 768px) {
width: 95% !important;
}
}
.courses-in-program .course-card {
background: $white;
padding: 10px;
margin-bottom: 30px;
border: 1px solid palette(grayscale, back);
@include box-shadow(0, 1px, 5px, rgba(0, 0, 0, 0.4));
border-radius: 4px;
@media (min-width: 768px) {
padding: 20px;
border: 1px solid #979797;
box-shadow: none;
border-radius: 0;
}
.title {
margin-bottom: 10px;
font-size: 18px;
text-decoration: underline;
a{
color: #005686;
}
small {
display: block;
font-size: 0;
margin-top: 5px;
> span {
display: inline-block;
text-decoration: none;
font-size: 1rem !important;
&:first-child {
border-right: 1px solid #4a4a4a;
padding-right: 6px;
margin-right: 6px;
@media (min-width: 768px) {
padding-right: 10px;
margin-right: 10px;
}
}
}
}
}
p {
margin-bottom: 0;
font-weight: normal;
font-size: 1rem;
}
&:last-child {
margin-bottom: 0;
}
}
.courses-in-program.container {
display: block;
padding: 20px 0;
background: #ececec;
margin-top: 15px;
@media (min-width: 768px) {
margin-top: 0;
background: $white;
padding: 20px;
}
.course-cards {
padding-top: 5px;
@media (min-width: 768px) {
width: 100% !important;
transform: none !important;
}
}
> .hd {
padding: 0 1.25rem !important;
margin-bottom: 15px;
@media (min-width: 768px) {
padding: 0;
font-size: 18px !important;
}
@media (min-width: 1024px) {
font-size: 22px !important;
}
}
.course-card {
margin-bottom: 20px;
min-height: 283px;
position: relative;
@media (max-width: 767px) {
min-height: 300px;
margin-left: 5px;
margin-right: 5px;
padding-bottom: 50px;
overflow: hidden;
position: relative;
}
.tbl-view {
.tbl-col {
.btn-enroll-now {
position: absolute;
left: 0;
right: 0;
bottom: 0;
width: 100%;
border-radius: 0;
line-height: 22px;
background: #0f8012;
@media (min-width: 768px) {
position: relative;
border: 1px solid #ccc;
max-width: 200px;
}
}
&:first-child {
@media (min-width: 768px) {
width: 75%;
}
p {
@media (min-width: 768px) {
max-width: 700px;
}
}
}
}
}
.btn-enroll-now{
width: 100% !important;
max-width: 300px !important;
min-height: 50px;
font-size: 1.33rem;
font-weight: bold;
}
}
.pagingInfo {
display: block;
text-align: center;
@media (min-width: 768px) {
display: none;
}
}
}
.copy-meta-mobile{
font-size: 0.875rem;
line-height: 1.6em;
}
//Helper Classes
.pull-left{
float: left !important;
}
.pull-right{
float: right !important;
}
.block{
display: block;
}
a{
text-decoration: none;
&:hover {
opacity: 0.8;
text-decoration: none;
}
&:focus{
text-decoration: none;
}
}
.no-padding{
padding: 0 !important;
}
#success-message{
padding: 0;
.alert {
min-width: 0;
border-left-width: 0;
border-right-width: 0;
border-bottom-width: 0;
box-shadow: none;
}
}
.window-wrap{
background-color: transparent;
}
.content-wrapper {
max-width: none;
padding-top: 0;
padding-bottom: 0;
.container {
border: none;
}
}
.grid-container {
padding: 0 1rem;
}
.show-user-menu{
display: block !important;
right: -16px !important;
}
.hidden-mobile{
display: none;
}
.visible-mobile{
display: block;
}
.btn-success{
background-color: palette(success, text) !important;
color: $white !important;
border-color: palette(success, text);
&:hover {
background-color: palette(success, accent) !important;
}
}
.btn-block{
width: 100% !important;
}
.bookmark-button:hover {
color: #0071bb !important;
border-color: transparent !important;
}
.inner-container {
@include grid-container();
@include span(12);
padding: 0 1.25rem;
}
h2{
font-size: 1.5rem;
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
margin: 1.25rem 0;
text-transform: none;
}
h1, h2, h3, h4, h5, h6{
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
}
.col-centered{
float: none !important;
margin-left: auto !important;
margin-right: auto !important;
}
.input-group{
margin-bottom: 1.25rem;
}
.input-lg{
line-height: 55px !important;
height: 55px !important;
padding: 0 1.25rem !important;
}
.form-block{
label, input, select, button, textarea{
display: block;
width: 100%;
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
font-style: normal;
margin-bottom: 0.5rem !important;
&.has-error {
border-color: palette(error, text);
border-radius: 4px 4px 0 0;
margin-bottom: 0 !important;
+ .field-message{
border-radius: 0 0 4px 4px;
width: 100%;
}
}
}
input{
box-shadow: none;
border: 1px solid palette(grayscale, back);
border-radius: 4px;
font-size: 1rem;
width: 100%;
&:focus, &:active{
box-shadow: none;
border-color: palette(grayscale, base);
}
}
select{
-webkit-appearance: none;
-moz-appearance: none;
border-color: palette(grayscale, back);
appearance: none;
&::-ms-expand{
display: none;
}
}
textarea{
height: 280px;
border-color: palette(grayscale, back);
box-shadow: none;
resize: none;
padding: 1rem;
}
button{
margin-top: 2.5rem;
padding: 1.25rem;
}
}
.list-bulleted{
li{
margin-bottom: 0.2rem !important;
padding-left: 0.5rem !important;
line-height: 1.5rem;
color: palette(grayscale, base);
.brand-link{
display: inline;
}
}
}
.btn-enroll-mobile{
margin-bottom: 2rem;
.btn-enroll{
max-width: 95%;
margin: auto;
border-radius: 3px;
}
}
#course-trailer {
.trailer-link {
color: $white;
font-weight: bold;
span {
text-decoration: underline;
}
&:hover {
cursor: pointer;
}
}
}
#accordion-group {
font-family: "Open Sans", Arial, Helvetica, sans-serif;
.accordion-item {
border-bottom: 1px solid palette(primary, dark);
.accordion-head {
background: #004165;
padding: 18px 18px 18px 84px;
color: $white;
border-radius: 0;
border: none;
margin: 0;
font-size: 1.13em;
position: relative;
&:hover,
&.active,
&:focus{
cursor: pointer;
}
&::before {
content: "\f054";
font-family: FontAwesome;
position: absolute;
left: 44px;
top: 20px;
width: 18px;
height: 22px;
}
&.ui-state-active {
&::before {
content: "\f078";
left: 40px;
}
}
}
.accordion-content {
display: none;
padding: 15px;
background: #f6f6f6;
border: none;
p,
ul {
color: $dark-gray1 !important;
font-size: 1em !important;
line-height: 1.5em;
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
}
p {
&:last-child {
margin: 0;
}
}
ul {
li {
padding-left: 0 !important;
+ div {
color: $dark-gray1;
}
}
}
}
&.show {
.accordion-content {
display: block;
}
}
&:nth-of-type(2) .accordion-head {
background: #004a74;
}
&:nth-of-type(3) .accordion-head {
background: #00527f;
}
&:nth-of-type(4) .accordion-head {
background: #005d91;
}
&:nth-of-type(5) .accordion-head {
background: #016fad;
}
&:nth-of-type(6) .accordion-head {
background: #1878ad;
}
&.instructors-mobile-list {
@extend .visible-sm;
.accordion-content {
background: $white;
padding: 0;
.instructor-profiles {
margin: 0;
.profile-item {
padding: 15px 25px;
margin: 0;
.details {
padding-left: 10px;
.name {
font-size: 0.8em;
}
.dept {
font-size: .7em;
}
}
&:nth-child(even) {
background: #f0f0f0;
}
}
}
}
}
}
}
// Program marketing page
.main-banner {
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
opacity: 0.35;
}
.grid-manual {
z-index: 1;
position: relative;
.btn-start {
color: #fff !important;
text-transform: none;
}
}
}
#courses {
.btn-enroll {
text-align: center;
font-size: 1.3em;
font-weight: bold;
}
}
// Program catalog listing
.program-list {
.programs-listing-item {
box-sizing: border-box;
box-shadow: 1px 2px 5px #ccc;
position: relative;
height: 360px;
overflow: visible;
min-height: 0;
border: none;
display: block;
margin: 0 auto 40px;
background: $white;
border-radius: 0;
.program-image {
height: 142px;
position: relative;
overflow: hidden;
.cover-image {
height: 142px;
img {
width: 100%;
height: auto;
}
&::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background: black;
opacity: 0;
transition: all 0.2s ease-out;
}
.learn-more {
left: calc(50% - 100px);
box-sizing: border-box;
position: absolute;
z-index: 100;
top: 62px;
padding: 0 20px;
width: 200px;
height: 50px;
border-color: #0074b4;
border-radius: 3px;
background: #0074b4;
color: #fff;
line-height: 50px;
text-align: center;
opacity: 0;
text-transform: none;
transition: all 0.25s ease;
}
}
}
.banner {
background: #065784;
color: $white;
padding-right: 15px;
line-height: 18px;
font-weight: bold;
font-size: 0.7em;
text-align: right;
text-transform: uppercase;
}
.program-info {
padding: 12px 15px 5px;
.program-org {
font-weight: normal;
font-size: 0.9em;
color: #3d3e3f;
margin: 0;
line-height: 16px;
}
.program-title {
max-height: 55px;
overflow: hidden;
color: #222;
font-size: 1.25em;
line-height: 1.333em;
margin-bottom: 5px;
}
.program-subtitle {
font-size: 1em;
margin-bottom: 33px;
line-height: 1.25em;
height: 40px;
color: palette(primary, dark);
overflow: hidden;
}
}
.program-footer {
display: table;
width: 100%;
padding: 0 15px 15px;
position: absolute;
bottom: 0;
.availability,
.program-logo {
display: table-cell;
}
.availability {
text-align: left;
font-size: 0.9em;
line-height: 20px;
color: palette(primary, dark);
}
.program-logo {
text-align: right;
width: 75px;
}
}
&::before,
&::after {
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2);
content: '';
position: absolute;
width: 100%;
height: 100%;
background: #d5d5d5;
border: 1px solid #b5b5b5;
}
&::before {
left: -5px;
top: -5px;
z-index: -1;
}
&::after {
left: -10px;
top: -10px;
z-index: -2;
}
&:hover {
opacity: 1;
.program-image {
.cover-image {
.learn-more {
opacity: 1;
}
&::before {
opacity: .6;
}
}
}
}
}
}
.container {
min-width: auto;
border: none;
max-width: 73.125rem;
padding: 20px 1rem;
}
> .grid-manual {
> .row {
align-items: stretch;
[class*='col'] {
@media (max-width: 767px) {
margin: 0 auto;
width: 100%;
padding: 0;
}
}
}
}
.instructors-title {
color: palette(primary, dark);
font-family: $sans-serif;
text-transform: none;
letter-spacing: 0;
@media (min-width: 768px) {
margin-top: 5px;
font-size: 18px !important;
}
@media (min-width: 1024px) {
font-size: 22px !important;
}
}
.instructor-profiles {
margin-bottom: 30px;
.profile-item {
@extend .tbl-view;
margin-bottom: 25px;
.avatar,
.details {
@extend .tbl-col;
display: table-cell;
}
.avatar {
width: 54px;
@media (min-width: 768px) {
width: 60px;
}
.img-holder {
width: 70px;
height: 70px;
border-radius: 50%;
border: 2px solid palette(primary, dark);
overflow: hidden;
img {
max-width: 100%;
}
}
}
.details {
padding-left: 15px;
.name {
color: palette(primary, dark);
font-size: 1em;
margin-bottom: 0;
a{
font-weight: 600;
text-decoration: underline;
}
}
.dept {
font-size: 1em;
line-height: 1.5em;
}
}
&:last-child {
margin-bottom: 0;
}
}
}
.visible-sm {
@media (min-width: 768px) {
display: none !important;
}
}
.hidden-sm {
@media (max-width: 767px) {
display: none !important;
}
}
.pagination {
margin: 10px 0 50px;
width: 100%;
display: block;
.pages{
width: calc(100% - 120px);
text-align: right;
display: inline-block;
font-size: 14px;
}
.controls{
text-align: center;
display: inline-block;
width: 115px;
a{
display: inline-block;
width: 50px;
&:first-child{
border-right: 1px solid $light-gray2;
}
.fa{
font-size: 1.75rem;
color: $border-color;
}
&.active{
.fa{
color: palette(primary, dark);
}
}
}
}
}
.program-desc-tbl {
margin-bottom: 20px;
@extend .tbl-view;
border: 1px solid #e3e3e3;
border-radius: 6px;
@media (min-width: 768px) {
border: 2px solid palette(primary, base);
border-radius: 0;
padding: 5px 15px;
}
@media (min-width: 1024px) {
padding: 8px 15px;
}
.item {
padding: 10px 10px 12px !important;
font-size: .9em;
border-color: #d0d0d0;
margin: 0;
@media (min-width: 768px) {
font-size: 1em;
padding: 15px 0 !important;
}
@media (min-width: 1024px) {
font-size: 1em;
padding: 15px !important;
}
span {
font-size: 1em !important;
+ a{
font-weight: 600;
font-size: 1em !important;
text-decoration: underline;
}
}
> span {
@extend .tbl-col;
display: block;
width: 100%;
color: $dark-gray1 !important;
line-height: 1.4em;
@media (min-width: 768px) {
display: inline-block;
width: 50%;
}
.fa {
display: none;
margin-right: 30px;
margin-left: 20px;
font-size: 1.4em !important;
@media (min-width: 1024px) {
display: inline-block;
}
}
+ a {
@media (max-width: 767px) {
color: palette(primary, dark);
}
}
&:first-child {
color: $dark-gray1 !important;
margin-bottom: 5px;
@media (max-width: 767px) {
margin-bottom: 0;
}
font-size: 0.85em;
@media (max-width: 767px) {
text-transform: uppercase;
}
@media (min-width: 768px) {
width: 48%;
color: $dark-gray1 !important;
margin-bottom: 0;
font-size: 1.024em;
}
}
}
.description {
display: block;
float: left;
}
.price {
.green-highlight {
font-weight: 700;
color: palette(success, text);
}
.original-price {
text-decoration: line-through;
}
.savings {
display: block;
}
}
}
}
.data-table{
@media (max-width: 767px){
padding: 0 20px;
}
.list-divided{
@media (min-width: 767px){
padding: 0 12px !important;
}
.item{
margin-top: 0.625rem;
line-height: 1.4em;
padding: 15px 15px 19px 25px !important;
border-bottom: 1px solid $m-gray-l3 !important;
@media (min-width: 768px) {
padding: 15px 0 19px 0 !important;
}
@media (max-width: 767px){
margin: 0 !important;
}
&:last-child{ .program_title {
border-bottom: 0 !important; font-weight: bold;
}
}
}
} }
.program-quote { .logo {
margin-left: 0; height: 100px;
margin-right: 0;
margin-bottom: 0;
line-height: 1.4;
font-size: 0.8em;
@media (min-width: 768px) {
line-height: 1.8;
font-size: 1em;
}
span {
display: block;
margin-bottom: 10px;
@media (min-width: 768px) {
display: inline;
}
&.writer {
font-weight: 600;
padding-left: 50px;
@media (min-width: 768px) {
padding-left: 0;
}
&::before {
@media (min-width: 768px) {
//content: '&#8212;';
content: '\2014';
margin-right: 3px;
margin-left: 5px;
}
}
}
img{
height: auto;
margin-left: 6px;
width: 100%;
}
}
&.visible-mobile {
font-size: 1em;
line-height: 1.5;
}
} }
.faq-links-list { .section_title {
li { margin-bottom: $baseline;
margin-bottom: 15px; color: theme-color("dark");
a {
display: block;
position: relative;
color: $blue;
padding-left: 30px;
&::before {
font-family: "FontAwesome";
content: "\f105";
position: absolute;
left: 5px;
top: 1px;
}
& + div {
padding: 10px 30px;
font-size: 1rem;
color: $dark-gray1 !important;
}
}
&.expanded {
a::before {
content: "\f107";
}
}
}
} }
.ui-state-default .ui-icon { .thick_rule {
display: none; height: 4px;
border: 0;
background-color: theme-color('secondary');
} }
//Modals .main-banner {
.modal { color: white;
border-radius: 0 !important; margin-bottom: 1px;
background: #fff !important;
.inner-wrapper { .authoring-org-logo {
padding: 0 !important; background-color: $white;
border: none !important; margin-bottom: $baseline;
} }
}
.modal-custom { .btn {
width: 320px; font-size: 20px;
background-color: $white;
padding: 30px 30px;
position: fixed !important;
overflow: auto;
overflow-x: hidden;
top: 10%;
bottom: 10%;
left: calc(50% - 160px) !important;
margin-left: 0 !important;
z-index: 999;
.btn-close {
position: absolute !important;
right: 20px !important;
top: 20px !important;
cursor: pointer;
.fa {
font-size: 1.75em;
color: black;
}
} }
&.custom-video-modal { .btn,
padding: 10px; .authoring-org-logo,
max-height: 360px; h1,
h2,
.inner-wrapper, iframe { a {
height: 100%; margin-bottom: $baseline;
width: 100%;
}
} }
.modal-body{ #program_video {
overflow: hidden !important; display: flex;
position: relative !important; align-items: center;
width: 100%; height: 100%;
.modal-header {
display: block;
width: 100%;
margin-bottom: 2rem !important;
margin-left: 0 !important;
margin-right: 0 !important;
.instructor-data{
display: block;
.thumbnail{
display: block;
width: 100%;
padding-bottom: 0;
img{
border-radius: 50%;
border: 5px solid palette(grayscale, back);
margin-bottom: 1rem;
}
}
h3{
display: block;
width: 100%;
vertical-align: middle;
font-size: 1.5em;
line-height: normal;
color: black;
margin-bottom: 0;
span{ button {
display: block; background-color: transparent;
font-size: 1rem;
line-height: 1.1rem;
color: black;
&:last-child {
color: black;
font-size: 0.8rem;
line-height: 1.1rem;
margin-top: 5px;
}
}
}
}
} }
.instructor-bio { iframe {
line-height: 1.5rem; width: 100%;
margin-bottom: 2rem; max-width: 400px;
color: black; height: 100%;
margin: 0 !important; max-height: 200px;
font-size: 1rem;
} }
.links{ @include media-breakpoint-down(md) {
a{ iframe {
margin-right: 0; margin: 50px 0;
display: block;
margin-bottom: 0.5rem;
} }
} }
} }
} }
//Media Queries .quick-nav {
background-color: theme-color('light');
@media screen and (min-width: 30em) { margin-bottom: $baseline/2;
.hero {
.tint-dark {
.grid-manual {
.text-tint {
.btn-neutral {
padding: 0.8em 2em;
}
}
}
}
}
.courses-section {
.courses-container {
.highlighted-courses {
.courses {
.course-info {
height: 165px;
}
.course-list {
.courses-listing-item {
padding: 0;
}
}
}
}
}
}
.footer-main{
.footer-logo{
text-align: center;
}
}
.visible-mobile{
display: none;
}
.hidden-mobile{
display: block;
}
.testimonial-main{
p{
text-align: left;
}
img{ .nav-item {
margin-bottom: 0; font-size: 18px;
} color: $white;
} }
} }
@media screen and (min-width: 48em){ .program-info {
.btn-enroll-mobile{ .quote {
display: none; font-style: italic;
}
header.header-main{
.logo a img {
height: 44px;
}
.collapsed-button{
display: none;
}
.nav-collapse{
ul{
display: block;
transition: all .2s;
position: relative;
top: inherit;
right: inherit;
left: inherit;
border-top: 0;
background-color: transparent;
box-shadow: none;
padding: 0;
li{
width: auto;
text-align: left;
line-height: 100px;
padding: 0 0.5rem;
a{
&.btn-neutral{
padding: 0.625rem 1.25rem;
}
}
&.user-account{
ul{
position: absolute;
right: 1rem;
top: 100%;
width: 100%;
margin-top: -1.5rem;
li{
display: block;
float: none;
line-height: normal;
a{
padding: 0.5rem;
display: inline-block;
}
}
}
}
}
}
}
} }
.footer-main{ .section {
.footer-logo{ margin-bottom: $baseline;
text-align: left;
}
.open-edx-logo{
ul{
li{
text-align: right;
img{
max-width: 80%;
}
}
}
}
} }
.hero { .facts {
.tint-dark { border: 1px solid theme-color('dark');
max-height: 350px;
.grid-manual {
.text-tint {
p {
font-size: 40px;
span {
display: block;
font-size: 1.5rem;
}
}
}
}
}
&.hero-video{
background: rgba(0,0,0,0.6);
.hero-image { li {
display: block; margin: 0 $baseline;
background-size: cover !important; padding: 15px 0;
} border-bottom: 1px solid theme-color('light');
.tint-dark { .label {
background: -moz-linear-gradient(left, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* FF3.6-15 */ color: theme-color('dark');
background: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* Chrome10-25,Safari5.1-6 */
background: linear-gradient(to right, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#a6000000', endColorstr='#00000000', GradientType=1); /* IE6-9 */
} }
.grid-container { .description {
padding: 0 1rem; .original-price {
text-decoration: line-through;
.row{
height: 22rem;
.description{
.data{
padding: 11.5% 2% 0 0;
h1{
color: $white;
font-size: 2.2rem;
}
p{
color: $white;
font-size: 1.3rem;
}
}
}
.video{
float: right;
padding-left: 1.04167%;
padding-right: 1.04167%;
.video-data{
line-height: 352px;
max-width: 95%;
img{
border: 3px solid $white;
width: auto;
}
}
}
} }
}
&.no-video .grid-container .row .description .data{
margin: 0;
}
}
}
.course-info {
.course-detail {
[class*="col"] {
margin-bottom: 0;
}
.btn-enroll{
margin-top: 0;
}
}
.description-container {
.expandable{
max-height: 224px;
}
}
}
.modal-custom{
display:none;
width: 540px;
padding: 30px 30px;
left: calc(50% - 270px) !important;
.focusKeeper {
width: 0;
height: 0;
overflow: hidden;
}
.modal-body{
.modal-header {
display: table;
width: 100%;
.instructor-data{
display: table-row;
.thumbnail{
display: table-cell;
width: 25%;
padding-bottom: 0;
img{
margin-bottom: 0;
}
}
h3{ .green-highlight {
display: table-cell; font-size: 18px;
width: 65%; color: theme-color('success');
padding: 1rem; font-weight: $font-weight-bold;
}
} }
} }
.links{ .label,
a{ .description {
margin-right: 1.5rem; vertical-align: top;
display: inline-block;
margin-bottom: 0;
}
} }
}
}
.rtl .hero.hero-video .tint-dark .grid-container .row .description{
padding-right: 1.04167%;
}
.course-card{ &:last-child {
.title{ border-bottom: 0;
small{
> span{
font-size: 0.8rem !important;
}
} }
} }
} }
} }
@media screen and (min-width: 64em){ /* 980px */ #courses {
header.header-main { h2 {
.nav-collapse { margin-bottom: $baseline;
ul {
li {
padding: 0 0.9rem;
}
}
}
}
.hero{
&.hero-video .grid-container .row .description .data h1 {
font-size: 2.5rem;
}
} }
.footer-main { .course {
.footer-logo { margin: 50px 0;
text-align: left;
}
}
.course-card{ .course-image {
.title{ img {
small{ max-width: 100%;
> span{
font-size: 1rem !important;
}
} }
} }
}
}
@media screen and (min-width: 80em){
.footer-main {
.footer-logo {
text-align: left;
}
}
}
// For RTL .course-enroll {
.rtl { margin-top: 50px;
header {
&.header-main{
.list-inline li{
float: left;
}
.nav-collapse .collapsed-button{ div {
left: 20px; text-align: center;
right: auto; font-weight: bold;
} }
}
}
.hero.hero-video .grid-container .row {
.description{
padding-right: 2%;
.data { a {
h1 { font-size: 20px;
text-align: right;
}
} }
} }
.video{ @include media-breakpoint-up(lg) {
float: left; .course-enroll {
} margin-top: 0;
}
.footer-main ul li:last-child{
text-align: right;
}
.course-index .accordion .course-navigation .button-chapter .group-heading {
padding: 15px 40px 15px 20px;
}
.ui-state-default.slick-header-column {
float: right !important;
left: inherit !important;
width: 84px !important;
height: 25px;
padding: 5px;
}
.grid-canvas {
width: 1097px !important;
}
.instructor-dashboard-content-2 {
.slickgrid .slick-cell {
float: right;
right: 0;
left: inherit;
position: relative !important;
width: 84px;
&.l0.r0 {
border-right: 1px dotted silver;
}
&.l12.r12 {
border-right: 0;
} }
} }
.content-history-table-inner .slickgrid .slick-cell {
width: 219px;
}
.report-downloads-table .slickgrid .slick-cell {
width: 100%;
}
}
.slick-header-columns {
right: 0 !important;
left: inherit !important;
width: 1097px !important;
}
.content-history-table-inner .ui-state-default.slick-header-column {
width: 219px !important;
} }
} }
@media (min-width: 768px) { #instructors {
header.header-main .list-inline li.user-account ul::before { .instructor {
right: 0.4rem; margin: $baseline 0;
}
.course-card{
display: inline-block;
margin: 0 calc(0.5 * 2.6rem) 30px calc(0.5 * 1rem) !important;
width: calc(50% - 22px);
vertical-align: top;
position: absolute;
height: 283px;
max-height: 283px;
overflow: hidden;
&:nth-child(even){ * {
margin-right: 0 !important; text-align: center;
margin: auto;
} }
.title{ img {
a{ height: 100px;
height: auto; width: 100px;
max-height: 50px; border-radius: 100px;
overflow: hidden;
display: block;
color: #005686;
text-decoration: underline;
}
small{
margin-top: 10px;
> span{
font-size: 0.9rem;
}
}
} }
p{ .instructor-name {
margin-bottom: 30px; font-weight: bold;
min-height: 75px;
max-height: 75px;
overflow: hidden;
position: absolute;
bottom: 66px;
left: 20px;
right: 20px;
} }
.btn-enroll{ .instructor-position {
display: inline-block; font-weight: bold;
background-color: $green !important;
min-width: 220px;
padding: 10px 30px;
font-size: 16px !important;
font-weight: 600 !important;
text-decoration: none;
position: absolute;
bottom: 20px;
left: 20px;
} }
} }
} }
img{ .faqs {
max-width: 100%; margin-bottom: $baseline * 2;
}
@media (min-width: 1024px) { .question {
header.header-main .list-inline li.user-account ul::before { font-weight: bold;
right: 0.72rem; margin-top: $baseline;
} }
} }
} }
## mako
<%page expression_filter="h"/> <%page expression_filter="h"/>
<%inherit file="../main.html"/>
<%inherit file="/main.html" />
<%! <%!
from datetime import datetime from datetime import datetime
...@@ -9,11 +11,14 @@ from mako import exceptions ...@@ -9,11 +11,14 @@ from mako import exceptions
from openedx.core.djangolib.markup import HTML, Text from openedx.core.djangolib.markup import HTML, Text
%> %>
<%namespace name='static' file='../static_content.html'/> <%namespace name='static' file='../static_content.html'/>
## Override the default styles_version to use Bootstrap
<%! main_css = "css/bootstrap/lms-main.css" %>
<% <%
faq = program['faq'] faqs = program['faq']
program_type = program['type'] program_type = program['type']
program_type_slug = program['type_slug'] program_type_slug = program['type_slug']
title = program['title'] title = program['title']
...@@ -26,13 +31,16 @@ job_outlook_items = program['job_outlook_items'] ...@@ -26,13 +31,16 @@ job_outlook_items = program['job_outlook_items']
weeks_to_complete = program['weeks_to_complete'] weeks_to_complete = program['weeks_to_complete']
full_program_price_format = '{0:.0f}' if program['full_program_price'].is_integer() else '{0:.2f}' full_program_price_format = '{0:.0f}' if program['full_program_price'].is_integer() else '{0:.2f}'
full_program_price = full_program_price_format.format(program['full_program_price']) full_program_price = full_program_price_format.format(program['full_program_price'])
endorsement = program['individual_endorsements'][0] if program['individual_endorsements'] else {} corporate_endorsement = program['corporate_endorsements'][0] if program['corporate_endorsements'] else {}
endorsement_quote = endorsement.get('quote', '') corporate_endorsement_name = corporate_endorsement.get('corporation_name')
endorser = endorsement.get('endorser', {}) corporate_endorsement_image = corporate_endorsement.get('image')['src']
endorsement_image = endorser.get('profile_image', {}).get('medium', {}).get('url', '') endorsement = corporate_endorsement['individual_endorsements'][0]
endorsement_name = endorser.get('given_name', '') endorsement_quote = endorsement.get('quote')
endorsement_position = (endorser.get('position') or {}).get('title', '') endorser = endorsement.get('endorser')
endorsement_organization = (endorser.get('position') or {}).get('organization_name', '') endorser_name = endorser.get('given_name') + ' ' + endorser.get('family_name')
endorser_position = endorser.get('position') or {}
endorser_title = endorser_position.get('title')
endorser_org = endorser_position.get('organization_name') or corporate_endorsement_name
expected_learning_items = program['expected_learning_items'] expected_learning_items = program['expected_learning_items']
authoring_organizations = program['authoring_organizations'] authoring_organizations = program['authoring_organizations']
min_hours_effort_per_week = program['min_hours_effort_per_week'] min_hours_effort_per_week = program['min_hours_effort_per_week']
...@@ -42,405 +50,265 @@ banner_image = program.get('banner_image', {}).get('large', {}).get('url', '') ...@@ -42,405 +50,265 @@ banner_image = program.get('banner_image', {}).get('large', {}).get('url', '')
description_max_length = 250 description_max_length = 250
%> %>
<%static:css group='style-main-v2'/>
<%static:css group='style-learner-dashboard'/>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/slick.min.js')}"></script>
<script src="${static.url('js/leanModal.js')}"></script>
<script src="${static.url('js/program_marketing.js')}"></script> <script src="${static.url('js/program_marketing.js')}"></script>
</%block> </%block>
<%block name="pagetitle">${program['title']}</%block> <%block name="pagetitle">${program['title']}</%block>
<div id="program-details-page" class="container">
<div id="program-details-page"> <div class="row main-banner" style="background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5) ), url(${banner_image}) no-repeat center;">
<div class="main-banner" style="background: #000 url(${banner_image}) no-repeat center center / cover;"> <div class="col col-12 col-md-8">
<div class="grid-manual"> % if authoring_organizations and authoring_organizations[0]['logo_image_url']:
<div class="row"> <div>
<div class="col col-12 md-col-8 lg-col-9"> <img class="authoring-org-logo logo" alt="${authoring_organizations[0]['name']}" src="${authoring_organizations[0]['logo_image_url']}"/>
<div class="org-logo"> </div>
% if authoring_organizations and authoring_organizations[0]['logo_image_url']: % endif
<img src="${authoring_organizations[0]['logo_image_url']}" alt="${authoring_organizations[0]['name']}"> <div>
% endif <h1 class="program_title">${program['title']}</h1>
</div> </div>
<h1 class="banner-title">${title}</h1> <div>
<p class="banner-description">${subtitle}</p> <h2>${program['subtitle']}</h2>
% if program.get('is_learner_eligible_for_one_click_purchase'): </div>
<a href="${buy_button_href}" class="btn-brand btn-large btn-start"> <div>
${_('Purchase the Program')} % if program.get('is_learner_eligible_for_one_click_purchase'):
</a> <a href="${buy_button_href}" class="btn btn-success">
% else: ${_('Purchase the Program')}
<a href="#courses" class="btn-brand btn-large btn-start">
${_('Start Learning')}
</a>
% endif
</div>
<div class="col col-12 md-col-4 lg-col-3" id="course-trailer">
<a href="#video-modal" class="media trailer-link visible-sm" rel="leanModal">
<i class="fa fa-play-circle-o" aria-hidden="true"></i>
<span>${_('View Program Trailer')}</span>
</a> </a>
<div class="hidden-sm"> % else:
<button href="#video-modal" class="media btn-play" rel="leanModal"> <a href="#courses" class="btn btn-success">
<span class="sr">Play the ${title} program video</span> ${_('Start Learning')}
<i class="icon fa fa-2x fa-play" alt="${_('Play')}"></i> </a>
</button> % endif
</div> </div>
</div> </div>
<div class="col col-12 col-md-4">
<div id="program_video">
<button type="button" class="btn" aria-label="${_('Play')}" onclick="playVideo('${video_url}')">
<span class="icon fa fa-4x fa-play-circle" aria-hidden="true"></span>
</button>
<iframe class="align-middle" title="${_('YouTube Video')}" src="" frameborder="0" allowfullscreen style="display:none;"></iframe>
</div> </div>
</div> </div>
</div> </div>
<div class="row quick-nav">
<div class="grid-manual data-table"> <ul class="nav nav-fill col-lg-12">
<div class="row"> <li class="nav-item">
<div class="col col-12 md-col-7 lg-col-8 left-col"> <a class="nav-link" href="#courses">${_('View Courses')}</a>
<ul class="list-divided program-desc-tbl"> </li>
<li class="item"> <li class="nav-item">
<span class="description"> <a class="nav-link" href="#instructors">${_('Meet the Instructors')}</a>
<span class="fa fa-book fa-lg" aria-hidden="true"></span> </li>
${_('Number of Courses')} <li class="nav-item">
</span> <a class="nav-link" href="#faqs">${_('Frequenty Asked Questions')}</a>
<a href="#courses"> </li>
${Text(_('{number_of_courses} courses in program')).format( </ul>
number_of_courses=len(courses) </div>
)} <div class="row program-info">
</a> <div class="col col-12 col-lg-7">
</li> <div class="section">
<li class="item"> <p>${HTML(program['overview'])}</p>
<span class="description"> </div>
<div class="section">
% if job_outlook_items:
<h3 class="section_title">${_('Job Outlook')}</h3>
<p>
<ul>
% for item in job_outlook_items:
<li>${item}</li>
% endfor
</ul>
</p>
% endif
</div>
<div class="section">
% if endorsement:
<h3 class="section_title">${_('Real Career Impact')}</h3>
<p>
<img class="logo" alt="${corporate_endorsement_name}" src="${corporate_endorsement_image}"/>
<blockquote class="blockquote">
<p class="quote">"${endorsement_quote}"</p>
<footer class="blockquote-footer">
${endorser_name}, ${endorser_title}, ${endorser_org}
</footer>
</blockquote>
</p>
%endif
</div>
<div class="section">
</div>
<div class="section">
% if expected_learning_items:
<p>
<h3 class="section_title">${_('What You\'ll Learn')}</h3>
<ul>
% for item in expected_learning_items:
<li>${item}</li>
% endfor
</ul>
</p>
%endif
</div>
</div>
<div class="col col-12 col-lg-5">
<div class="facts">
<ul class="list-unstyled">
<li class="row">
<div class="label col col-6">
<span class="fa fa-clock-o fa-lg" aria-hidden="true"></span> <span class="fa fa-clock-o fa-lg" aria-hidden="true"></span>
${_('Average Length')} <span>${_('Average Length')}</span>
</span> </div>
<span> <div class="description col col-6">
${Text(_('{weeks_to_complete} weeks per course')).format( ${Text(_('{weeks_to_complete} weeks per course')).format(
weeks_to_complete=weeks_to_complete weeks_to_complete=weeks_to_complete
)} )}
</span> </div>
</li> </li>
<li class="item"> <li class="row">
<span class="description"> <div class="label col col-6">
<span class="fa fa-tachometer fa-lg" aria-hidden="true"></span> <span class="fa fa-tachometer fa-lg" aria-hidden="true"></span>
${_('Effort')} <span>${_('Effort')}</span>
</span> </div>
<span> <div class="description col col-6">
${Text(_('{min_hours_effort_per_week}-{max_hours_effort_per_week} hours per week, per course')).format( ${Text(_('{min_hours_effort_per_week}-{max_hours_effort_per_week} hours per week, per course')).format(
max_hours_effort_per_week=max_hours_effort_per_week, max_hours_effort_per_week=max_hours_effort_per_week,
min_hours_effort_per_week=min_hours_effort_per_week min_hours_effort_per_week=min_hours_effort_per_week
)} )}
</span> </div>
</li> </li>
<li class="item"> <li class="row">
<span class="description"> <div class="label col col-6">
<span class="fa fa-book fa-lg" aria-hidden="true"></span>
<span>${_('Number of Courses')}</span>
</div>
<div class="description col col-6">
${Text(_('{number_of_courses} courses in program')).format(
number_of_courses=len(courses)
)}
</div>
</li>
<li class="row">
<div class="label col col-6">
<span class="fa fa-tag fa-lg" aria-hidden="true"></span> <span class="fa fa-tag fa-lg" aria-hidden="true"></span>
${_('Price (USD)')} <span>${_('Price (USD)')}</span>
</span> </div>
% if program.get('discount_data') and program['discount_data']['is_discounted']: <div class="description col col-6">
<span class="price"> % if program.get('discount_data') and program['discount_data']['is_discounted']:
<span role="group" aria-label="${_('Original Price')}" class="original-price"> <span class="price">
${Text(_('${oldPrice}')).format( <span aria-label="${_('Original Price')}" class="original-price">
oldPrice=full_program_price_format.format(program['discount_data']['total_incl_tax_excl_discounts']) ${Text(_('${oldPrice}')).format(
)} oldPrice=full_program_price_format.format(program['discount_data']['total_incl_tax_excl_discounts'])
)}
</span>
<span aria-label="${_('Discounted Price')}" class="discount green-highlight">
${Text(_('${newPrice}{htmlEnd} for entire program')).format(
newPrice=full_program_price,
htmlEnd=HTML('</span>')
)}
<span class="savings green-highlight">
${Text(_('You save ${discount_value} {currency}')).format(
discount_value=full_program_price_format.format(program['discount_data']['discount_value']),
currency=program['discount_data']['currency']
)}
</span>
</span> </span>
<span role="group" aria-label="${_('Discounted Price')}" class="discount green-highlight"> % else:
${Text(_('${newPrice}{htmlEnd} for entire program')).format( <span>
newPrice=full_program_price, ${Text(_('${full_program_price} for entire program')).format(
htmlEnd=HTML('</span>') full_program_price=full_program_price
)}
<span class="savings green-highlight">
${Text(_('You save ${discount_value} {currency}')).format(
discount_value=full_program_price_format.format(program['discount_data']['discount_value']),
currency=program['discount_data']['currency']
)} )}
</span> </span>
</span> % endif
% else: </div>
<span>
${Text(_('${full_program_price} for entire program')).format(
full_program_price=full_program_price
)}
</span>
% endif
</li> </li>
</ul> </ul>
<div id="accordion-group"> </div>
<div class="accordion-item"> </div>
<div class="accordion-head">${_('Overview')}</div> </div>
<div class="accordion-content"> <hr class="thick_rule">
<p>${HTML(overview)}</p> <div id="courses">
</div> <div class="row">
</div> <div class="col-12">
% if job_outlook_items: <h2>
<div class="accordion-item"> ${_('Courses in the {}').format(
<div class="accordion-head">${_('Job Outlook')}</div> program_type
<div class="accordion-content"> )}
<ul class="list-bulleted list-disc no-indent"> </h2>
% for item in job_outlook_items: </div>
<li>${item}</li> </div>
% endfor % for course in courses:
</ul> <%
</div> course_run = course['course_runs'][0]
</div> course_img = course_run.get('image')
%>
<div class="row course">
<div class="col-3 col-lg-2 course-image">
% if course_img:
<img alt="" src="${course_img['src']}" alt=""/>
% endif % endif
<div class="accordion-item"> </div>
<div class="accordion-head">${_("What You'll Learn")}</div> <div class="col-9 col-lg-6">
<div class="accordion-content"> <div>
<ul class="list-bulleted list-disc no-indent"> <a href="${course_run['course_url']}">${course_run['title']}</a>
% for item in expected_learning_items:
<li>${item}</li>
% endfor
</ul>
</div>
</div>
<div class="accordion-item instructors-mobile-list">
<div class="accordion-head">${_("Instructors")}</div>
<div class="accordion-content">
<div class="instructor-profiles">
<% index = 0 %>
% for instructor in instructors:
<% index += 1 %>
<div class="profile-item">
<div class="avatar">
<div class="img-holder">
<a href="#instructor-details-mobile-${index}" class="instructor-image">
<img src="${static.url(instructor.get('image'))}" alt="${instructor.get('name')}"/>
</a>
</div>
</div>
<div class="details">
<div class="name">
<a href="#instructor-details-mobile-${index}" class="instructor-label">${instructor.get('name')}</a>
</div>
% if instructor.get('position'):
<div class="dept">${instructor['position'].get('organization_name')}</div>
% endif
</div>
<div class="modal modal-custom" id="instructor-details-mobile-${index}">
<a href="#" class="focusKeeper"></a>
<div class="btn-close modal_close"><a href="#"><i class="fa fa-close"></i></a></div>
<div class="modal-body">
<div class="modal-header">
<div class="instructor-data">
<div class="thumbnail">
<img src="${instructor['image']}" alt="${instructor.get('name')}">
</div>
<h3>
<span class="instructor-name">${instructor.get('name')}</span>
% if instructor.get('position'):
<span>
${Text(_('{position} at {organization}')).format(
position=instructor['position'].get('title'),
organization=instructor['position'].get('organization_name')
)}
</span>
% endif
</h3>
</div>
</div>
<div class="instructor-bio">${HTML(instructor['bio'])}</div>
</div>
<a href="#" class="focusKeeper"></a>
</div>
</div>
%endfor
</div>
</div>
</div> </div>
<div>${course_run['short_description']}</div>
% try: <div>
<%include file="_${program_type_slug}_faq.html" args="program_type=program_type" /> <a href="${course_run['course_url']}">${_('Learn More')}</a>
% except exceptions.TemplateLookupException:
## pass
% endtry
<div class="accordion-item">
<div class="accordion-head">${_("FAQ")}</div>
<div class="accordion-content">
<ul class="list-unstyled faq-links-list">
% for item in faq:
<li class="item">
<a href="#!">${item['question']}</a>
<div class="answer hidden">${item['answer']}</div>
</li>
% endfor
</ul>
</div>
</div> </div>
</div> </div>
<blockquote class="program-quote visible-sm"> <div class="col-12 col-lg-4 course-enroll">
<div class="quote"> <div>
% if endorsement: ${Text(_('Starts on {}')).format(
<span>"${endorsement_quote}"</span> datetime.strptime(course_run['start'], '%Y-%m-%dT%H:%M:%SZ').strftime('%B %-d, %Y')
% if endorser: )}
% if endorsement_image:
<img class="visible-sm pull-left" src="${endorsement_image}" width="40" height="40" alt="${_('Endorser Image')}"/>
% endif
<span class="writer">
${endorsement_name},
${endorsement_position},
${endorsement_organization}
</span>
% endif
% endif
</div> </div>
</blockquote> % if program.get('is_learner_eligible_for_one_click_purchase') != True:
</div> % if course_run['is_enrollment_open'] and course_run['can_enroll'] and not course_run['is_course_ended']:
<div>
<div class="col col-12 md-col-5 lg-col-4 right-col hidden-sm"> <a class="btn btn-primary btn-block btn-success" href="${course_run['course_url']}about">Enroll Now</a>
<h2 class="instructors-title">
${_('Meet the Instructors')}
<span>(${len(instructors)})</span>
</h2>
<div class="instructor-profiles">
<% index = 0 %>
% for instructor in instructors:
<% index += 1 %>
<div class="profile-item profile-item-desktop">
<div class="avatar">
<div class="img-holder">
<a href="#instructor-details-${index}" class="instructor-image">
<img src="${static.url(instructor.get('image'))}"
alt="${instructor.get('name')}"/>
</a>
</div>
</div>
<div class="details">
<div class="name">
<a href="#instructor-details-${index}" class="instructor-label">${instructor.get('name')}</a>
</div>
<div class="dept">${instructor.get('organization')}</div>
</div> </div>
% else:
<div class="modal modal-custom" id="instructor-details-${index}"> <div>
<a href="#" class="focusKeeper"></a> <a class="btn btn-primary btn-block btn-secondary disabled" href="#" >Not Currently Available</a>
<div class="btn-close modal_close"><a href="#"><i class="fa fa-close"></i></a></div>
<div class="modal-body">
<div class="modal-header">
<div class="instructor-data">
<div class="thumbnail">
<img src="${instructor['image']}" alt="${instructor.get('name')}"/>
</div>
<h3>
<span class="instructor-name">${instructor.get('name')}</span>
<span>
${Text(_('{position} at {organization}')).format(
position=instructor.get('title'),
organization=instructor.get('organization')
)}
</span>
</h3>
</div>
</div>
<div class="instructor-bio">${HTML(instructor['bio'])}</div>
</div>
<a href="#" class="focusKeeper"></a>
</div> </div>
</div>
% endfor
<div class="pagination hidden-xs">
<div class="pages">
## Translators: Pagination range contains ordinal numbers of the first and the last instructor
## whose information is shown on the current page.
${Text(_("{pagination_range} of {number_of_instructors}")).format(
pagination_range=HTML('<span class="pagination-start"></span>-<span class="pagination-end"></span>'),
number_of_instructors=HTML('<span class="instructor-size">{number_of_instructors}</span>').format(
number_of_instructors=len(instructors)
)
)}
</div>
<div class="controls">
<a href="#" id="pagination-previous">
<span class="fa fa-chevron-up" aria-hidden="true"></span>
<span class="sr" aria-hidden="true">${_("Previous page")}</span>
</a>
<a href="#" id="pagination-next">
<span class="fa fa-chevron-down" aria-hidden="true"></span>
<span class="sr" aria-hidden="true">${_("Next page")}</span>
</a>
</div>
</div>
</div>
<blockquote class="program-quote">
<div class="quote">
% if endorsement:
<span class="pull-right hidden-sm">
% if endorser and endorsement_image:
<img src="${endorsement_image}" width="90" height="90" alt="${_('Endorser Image')}"/>
% endif
</span>
<span>
"${endorsement_quote}"
</span>
<span class="writer">
% if endorser:
${endorsement_name},
${endorsement_position},
${endorsement_organization}
% endif
</span>
% endif % endif
</div> % endif
</blockquote> </div>
</div> </div>
% endfor
</div>
<hr class="thick_rule">
<div id="instructors" class="row">
<div class="col-12">
<h2>${_('Instructors')}</h2>
</div> </div>
% for instructor in instructors:
<div class="col-6 col-sm-3 instructor">
<div>
<img alt="" src="${instructor['image']}"/>
</div>
<div class="instructor-name">${instructor['name']}</div>
<div class="instructor-position">${instructor['position']['position']}</div>
<div class="instructor-org">${instructor['position']['organization_name']}</div>
</div>
% endfor
</div> </div>
<hr class="thick_rule">
<div class="container courses-in-program" id="courses"> % if faqs:
<h3 class="hd"> <div id="faqs" class="row faqs">
${Text(_('Courses in the {program_type}')).format( <div class="col-12">
program_type=program_type <h2>${_('Frequently Asked Questions')}</h2>
)} </div>
</h3> % for faq in faqs:
<div class="course-cards"> <div class="col-4 faq">
% for course in courses: <div class="question">
% if course.get('course_runs'): ${faq['question']}
<div class="course-card">
<div class="course-content">
<div class="col-full-sm">
<h4 class="hd title">
<a href="/courses/${course['course_runs'][0]['key']}/about"> ${course['title']}</a>
<small>
<span>
<i class="fa fa-clock-o" aria-hidden="true"></i>
${Text(_('Starts {course_start_datetime}')).format(
course_start_datetime=datetime.strptime(course['course_runs'][0]['start'], '%Y-%m-%dT%H:%M:%SZ').strftime('%B %-d, %Y')
)}
</span>
% if course['course_runs'][0]['pacing_type'] == "instructor_paced":
<span>${_('Instructor - Paced')}</span>
% else:
<span>${_('Self - Paced')}</span>
% endif
</small>
</h4>
<p class="copy-meta">
% if course['course_runs'][0]['short_description']:
${course['course_runs'][0]['short_description']}
% endif
</p>
<p class="copy-meta-mobile">
% if course['course_runs'][0]['short_description']:
${course['course_runs'][0]['short_description'][:description_max_length]}
% if len(course['course_runs'][0]['short_description']) > description_max_length:
...
% endif
% endif
</p>
</div>
</div>
</div> </div>
% endif <div class="answer">
${faq['answer']}
</div>
</div>
% endfor % endfor
</div>
<span class="pagingInfo"></span>
</div>
<section id="video-modal" class="modal modal-custom custom-video-modal">
<div class="inner-wrapper">
<iframe title="${_('YouTube Video')}" width="640" height="360"
src="${video_url}"
frameborder="0" allowfullscreen></iframe>
</div> </div>
</section> % endif
</div> </div>
\ No newline at end of file
...@@ -144,7 +144,7 @@ class PersonFactory(DictFactoryBase): ...@@ -144,7 +144,7 @@ class PersonFactory(DictFactoryBase):
class EndorserFactory(DictFactoryBase): class EndorserFactory(DictFactoryBase):
person = PersonFactory() endorser = PersonFactory()
quote = factory.Faker('sentence') quote = factory.Faker('sentence')
...@@ -157,16 +157,22 @@ class FAQFactory(DictFactoryBase): ...@@ -157,16 +157,22 @@ class FAQFactory(DictFactoryBase):
question = factory.Faker('sentence') question = factory.Faker('sentence')
class CorporateEndorsementFactory(DictFactoryBase):
corporation_name = factory.Faker('company')
image = ImageFactory()
individual_endorsements = factory.LazyFunction(partial(generate_instances, EndorserFactory))
class ProgramFactory(DictFactoryBase): class ProgramFactory(DictFactoryBase):
authoring_organizations = factory.LazyFunction(partial(generate_instances, OrganizationFactory, count=1)) authoring_organizations = factory.LazyFunction(partial(generate_instances, OrganizationFactory, count=1))
applicable_seat_types = [] applicable_seat_types = []
banner_image = factory.LazyFunction(generate_sized_stdimage) banner_image = factory.LazyFunction(generate_sized_stdimage)
card_image_url = factory.Faker('image_url') card_image_url = factory.Faker('image_url')
corporate_endorsements = factory.LazyFunction(partial(generate_instances, CorporateEndorsementFactory))
courses = factory.LazyFunction(partial(generate_instances, CourseFactory)) courses = factory.LazyFunction(partial(generate_instances, CourseFactory))
expected_learning_items = factory.LazyFunction(partial(generate_instances, CourseFactory)) expected_learning_items = factory.LazyFunction(partial(generate_instances, CourseFactory))
faq = factory.LazyFunction(partial(generate_instances, FAQFactory)) faq = factory.LazyFunction(partial(generate_instances, FAQFactory))
hidden = False hidden = False
individual_endorsements = factory.LazyFunction(partial(generate_instances, EndorserFactory))
is_program_eligible_for_one_click_purchase = True is_program_eligible_for_one_click_purchase = True
job_outlook_items = factory.LazyFunction(partial(generate_instances, JobOutlookItemFactory)) job_outlook_items = factory.LazyFunction(partial(generate_instances, JobOutlookItemFactory))
marketing_slug = factory.Faker('slug') marketing_slug = factory.Faker('slug')
......
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