Remove old program detail page and Waffle switch gating the new page
The new page is released and stable. The switch and old code are no longer necessary. ECOM-7482
This commit is contained in:
committed by
Renzo Lucioni
parent
21a5a42571
commit
131cc0bdbb
@@ -1,5 +1,4 @@
|
|||||||
"""Learner dashboard views"""
|
"""Learner dashboard views"""
|
||||||
import waffle
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
@@ -67,6 +66,7 @@ def program_details(request, program_uuid):
|
|||||||
'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
|
'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# TODO: Tighten this up!
|
||||||
context = {
|
context = {
|
||||||
'urls': urls,
|
'urls': urls,
|
||||||
'show_program_listing': programs_config.enabled,
|
'show_program_listing': programs_config.enabled,
|
||||||
@@ -76,20 +76,15 @@ def program_details(request, program_uuid):
|
|||||||
'user_preferences': get_user_preferences(request.user)
|
'user_preferences': get_user_preferences(request.user)
|
||||||
}
|
}
|
||||||
|
|
||||||
if waffle.switch_is_active('new_program_progress'):
|
course_data = meter.progress(programs=[program_data], count_only=False)[0]
|
||||||
course_data = meter.progress(programs=[program_data], count_only=False)[0]
|
certificate_data = get_certificates(request.user, program_data)
|
||||||
certificate_data = get_certificates(request.user, program_data)
|
|
||||||
|
|
||||||
program_data.pop('courses')
|
program_data.pop('courses')
|
||||||
|
|
||||||
context.update({
|
context.update({
|
||||||
'program_data': program_data,
|
'program_data': program_data,
|
||||||
'course_data': course_data,
|
'course_data': course_data,
|
||||||
'certificate_data': certificate_data,
|
'certificate_data': certificate_data,
|
||||||
})
|
})
|
||||||
|
|
||||||
return render_to_response('learner_dashboard/program_details_2017.html', context)
|
return render_to_response('learner_dashboard/program_details.html', context)
|
||||||
else:
|
|
||||||
context.update({'program_data': program_data})
|
|
||||||
|
|
||||||
return render_to_response('learner_dashboard/program_details.html', context)
|
|
||||||
|
|||||||
@@ -42,22 +42,12 @@
|
|||||||
|
|
||||||
getUnselectedCourseRun: function(courseRuns) {
|
getUnselectedCourseRun: function(courseRuns) {
|
||||||
var unselectedRun = {},
|
var unselectedRun = {},
|
||||||
courseRun,
|
courseRun;
|
||||||
courseImageUrl;
|
|
||||||
|
|
||||||
if (courseRuns && courseRuns.length > 0) {
|
if (courseRuns && courseRuns.length > 0) {
|
||||||
courseRun = courseRuns[0];
|
courseRun = courseRuns[0];
|
||||||
|
|
||||||
if (courseRun.image && courseRun.image.src) {
|
|
||||||
courseImageUrl = courseRun.image.src;
|
|
||||||
} else {
|
|
||||||
// The course_image_url property is attached by setActiveCourseRun.
|
|
||||||
// If that hasn't been called, it won't be present yet.
|
|
||||||
courseImageUrl = courseRun.course_image_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.extend(unselectedRun, {
|
$.extend(unselectedRun, {
|
||||||
course_image_url: courseImageUrl,
|
|
||||||
marketing_url: courseRun.marketing_url,
|
marketing_url: courseRun.marketing_url,
|
||||||
is_enrollment_open: courseRun.is_enrollment_open
|
is_enrollment_open: courseRun.is_enrollment_open
|
||||||
});
|
});
|
||||||
@@ -149,8 +139,8 @@
|
|||||||
formatDateString: function(run) {
|
formatDateString: function(run) {
|
||||||
var pacingType = run.pacing_type,
|
var pacingType = run.pacing_type,
|
||||||
dateString = '',
|
dateString = '',
|
||||||
start = run.start_date || this.get('start_date'),
|
start = this.get('start_date') || run.start_date,
|
||||||
end = run.end_date || this.get('end_date'),
|
end = this.get('end_date') || run.end_date,
|
||||||
now = new Date(),
|
now = new Date(),
|
||||||
startDate = new Date(start),
|
startDate = new Date(start),
|
||||||
endDate = new Date(end);
|
endDate = new Date(end);
|
||||||
@@ -181,8 +171,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
setActiveCourseRun: function(courseRun, userPreferences) {
|
setActiveCourseRun: function(courseRun, userPreferences) {
|
||||||
var startDateString,
|
var startDateString;
|
||||||
courseImageUrl;
|
|
||||||
|
|
||||||
if (courseRun) {
|
if (courseRun) {
|
||||||
if (this.valueIsDefined(courseRun.advertised_start)) {
|
if (this.valueIsDefined(courseRun.advertised_start)) {
|
||||||
@@ -191,16 +180,8 @@
|
|||||||
startDateString = this.formatDate(courseRun.start, userPreferences);
|
startDateString = this.formatDate(courseRun.start, userPreferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (courseRun.image && courseRun.image.src) {
|
|
||||||
courseImageUrl = courseRun.image.src;
|
|
||||||
} else {
|
|
||||||
courseImageUrl = courseRun.course_image_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.set({
|
this.set({
|
||||||
certificate_url: courseRun.certificate_url,
|
certificate_url: courseRun.certificate_url,
|
||||||
course_image_url: courseImageUrl || '',
|
|
||||||
course_run_key: courseRun.key,
|
course_run_key: courseRun.key,
|
||||||
course_url: courseRun.course_url || '',
|
course_url: courseRun.course_url || '',
|
||||||
title: this.context.title,
|
title: this.context.title,
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'js/learner_dashboard/views/program_details_view_2017'
|
|
||||||
],
|
|
||||||
function(ProgramDetailsView) {
|
|
||||||
return function(options) {
|
|
||||||
var ProgramDetails = new ProgramDetailsView(options);
|
|
||||||
return ProgramDetails;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
(function(define) {
|
(function(define) {
|
||||||
'use strict';
|
'use strict';
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'gettext',
|
'gettext',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'text!../../../templates/learner_dashboard/certificate_status.underscore',
|
'text!../../../templates/learner_dashboard/certificate_status.underscore',
|
||||||
'text!../../../templates/learner_dashboard/certificate_icon.underscore'
|
'text!../../../templates/learner_dashboard/certificate_icon.underscore'
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
Backbone,
|
Backbone,
|
||||||
$,
|
$,
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'underscore',
|
|
||||||
'gettext',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'text!../../../templates/learner_dashboard/certificate_status_2017.underscore',
|
|
||||||
'text!../../../templates/learner_dashboard/certificate_icon.underscore'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
Backbone,
|
|
||||||
$,
|
|
||||||
_,
|
|
||||||
gettext,
|
|
||||||
HtmlUtils,
|
|
||||||
certificateStatusTpl,
|
|
||||||
certificateIconTpl
|
|
||||||
) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
statusTpl: HtmlUtils.template(certificateStatusTpl),
|
|
||||||
iconTpl: HtmlUtils.template(certificateIconTpl),
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
this.$el = options.$el;
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var data = this.model.toJSON();
|
|
||||||
|
|
||||||
data = $.extend(data, {certificateSvg: this.iconTpl()});
|
|
||||||
HtmlUtils.setHtml(this.$el, this.statusTpl(data));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -2,16 +2,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'gettext',
|
'gettext',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'js/learner_dashboard/models/course_enroll_model',
|
'js/learner_dashboard/models/course_enroll_model',
|
||||||
'js/learner_dashboard/views/upgrade_message_view',
|
'js/learner_dashboard/views/upgrade_message_view',
|
||||||
'js/learner_dashboard/views/certificate_status_view',
|
'js/learner_dashboard/views/certificate_status_view',
|
||||||
'js/learner_dashboard/views/course_enroll_view',
|
'js/learner_dashboard/views/expired_notification_view',
|
||||||
'text!../../../templates/learner_dashboard/course_card.underscore'
|
'js/learner_dashboard/views/course_enroll_view',
|
||||||
],
|
'text!../../../templates/learner_dashboard/course_card.underscore'
|
||||||
|
],
|
||||||
function(
|
function(
|
||||||
Backbone,
|
Backbone,
|
||||||
$,
|
$,
|
||||||
@@ -21,33 +22,39 @@
|
|||||||
EnrollModel,
|
EnrollModel,
|
||||||
UpgradeMessageView,
|
UpgradeMessageView,
|
||||||
CertificateStatusView,
|
CertificateStatusView,
|
||||||
|
ExpiredNotificationView,
|
||||||
CourseEnrollView,
|
CourseEnrollView,
|
||||||
pageTpl
|
pageTpl
|
||||||
) {
|
) {
|
||||||
return Backbone.View.extend({
|
return Backbone.View.extend({
|
||||||
className: 'course-card card',
|
className: 'program-course-card',
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
tpl: HtmlUtils.template(pageTpl),
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.enrollModel = new EnrollModel();
|
this.enrollModel = new EnrollModel();
|
||||||
if (options.context && options.context.urls) {
|
if (options.context) {
|
||||||
this.urlModel = new Backbone.Model(options.context.urls);
|
this.urlModel = new Backbone.Model(options.context.urls);
|
||||||
this.enrollModel.urlRoot = this.urlModel.get('commerce_api_url');
|
this.enrollModel.urlRoot = this.urlModel.get('commerce_api_url');
|
||||||
}
|
}
|
||||||
|
this.context = options.context || {};
|
||||||
this.render();
|
this.render();
|
||||||
this.listenTo(this.model, 'change', this.render);
|
this.listenTo(this.model, 'change', this.render);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var filledTemplate = this.tpl(this.model.toJSON());
|
var data = $.extend(this.model.toJSON(), {
|
||||||
HtmlUtils.setHtml(this.$el, filledTemplate);
|
enrolled: this.context.enrolled || ''
|
||||||
|
});
|
||||||
|
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
||||||
this.postRender();
|
this.postRender();
|
||||||
},
|
},
|
||||||
|
|
||||||
postRender: function() {
|
postRender: function() {
|
||||||
var $upgradeMessage = this.$('.upgrade-message'),
|
var $upgradeMessage = this.$('.upgrade-message'),
|
||||||
$certStatus = this.$('.certificate-status');
|
$certStatus = this.$('.certificate-status'),
|
||||||
|
$expiredNotification = this.$('.expired-notification'),
|
||||||
|
expired = this.model.get('expired');
|
||||||
|
|
||||||
this.enrollView = new CourseEnrollView({
|
this.enrollView = new CourseEnrollView({
|
||||||
$parentEl: this.$('.course-actions'),
|
$parentEl: this.$('.course-actions'),
|
||||||
@@ -56,14 +63,14 @@
|
|||||||
enrollModel: this.enrollModel
|
enrollModel: this.enrollModel
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.model.get('upgrade_url')) {
|
if (this.model.get('upgrade_url') && !(expired === true)) {
|
||||||
this.upgradeMessage = new UpgradeMessageView({
|
this.upgradeMessage = new UpgradeMessageView({
|
||||||
$el: $upgradeMessage,
|
$el: $upgradeMessage,
|
||||||
model: this.model
|
model: this.model
|
||||||
});
|
});
|
||||||
|
|
||||||
$certStatus.remove();
|
$certStatus.remove();
|
||||||
} else if (this.model.get('certificate_url')) {
|
} else if (this.model.get('certificate_url') && !(expired === true)) {
|
||||||
this.certificateStatus = new CertificateStatusView({
|
this.certificateStatus = new CertificateStatusView({
|
||||||
$el: $certStatus,
|
$el: $certStatus,
|
||||||
model: this.model
|
model: this.model
|
||||||
@@ -75,6 +82,13 @@
|
|||||||
$upgradeMessage.remove();
|
$upgradeMessage.remove();
|
||||||
$certStatus.remove();
|
$certStatus.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (expired) {
|
||||||
|
this.expiredNotification = new ExpiredNotificationView({
|
||||||
|
$el: $expiredNotification,
|
||||||
|
model: this.model
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'underscore',
|
|
||||||
'gettext',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'js/learner_dashboard/models/course_enroll_model',
|
|
||||||
'js/learner_dashboard/views/upgrade_message_view_2017',
|
|
||||||
'js/learner_dashboard/views/certificate_status_view_2017',
|
|
||||||
'js/learner_dashboard/views/expired_notification_view',
|
|
||||||
'js/learner_dashboard/views/course_enroll_view_2017',
|
|
||||||
'text!../../../templates/learner_dashboard/course_card_2017.underscore'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
Backbone,
|
|
||||||
$,
|
|
||||||
_,
|
|
||||||
gettext,
|
|
||||||
HtmlUtils,
|
|
||||||
EnrollModel,
|
|
||||||
UpgradeMessageView,
|
|
||||||
CertificateStatusView,
|
|
||||||
ExpiredNotificationView,
|
|
||||||
CourseEnrollView,
|
|
||||||
pageTpl
|
|
||||||
) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
className: 'program-course-card',
|
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
this.enrollModel = new EnrollModel();
|
|
||||||
if (options.context) {
|
|
||||||
this.urlModel = new Backbone.Model(options.context.urls);
|
|
||||||
this.enrollModel.urlRoot = this.urlModel.get('commerce_api_url');
|
|
||||||
}
|
|
||||||
this.context = options.context || {};
|
|
||||||
this.render();
|
|
||||||
this.listenTo(this.model, 'change', this.render);
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var data = $.extend(this.model.toJSON(), {
|
|
||||||
enrolled: this.context.enrolled || ''
|
|
||||||
});
|
|
||||||
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
|
||||||
this.postRender();
|
|
||||||
},
|
|
||||||
|
|
||||||
postRender: function() {
|
|
||||||
var $upgradeMessage = this.$('.upgrade-message'),
|
|
||||||
$certStatus = this.$('.certificate-status'),
|
|
||||||
$expiredNotification = this.$('.expired-notification'),
|
|
||||||
expired = this.model.get('expired');
|
|
||||||
|
|
||||||
this.enrollView = new CourseEnrollView({
|
|
||||||
$parentEl: this.$('.course-actions'),
|
|
||||||
model: this.model,
|
|
||||||
urlModel: this.urlModel,
|
|
||||||
enrollModel: this.enrollModel
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.model.get('upgrade_url') && !(expired === true)) {
|
|
||||||
this.upgradeMessage = new UpgradeMessageView({
|
|
||||||
$el: $upgradeMessage,
|
|
||||||
model: this.model
|
|
||||||
});
|
|
||||||
|
|
||||||
$certStatus.remove();
|
|
||||||
} else if (this.model.get('certificate_url') && !(expired === true)) {
|
|
||||||
this.certificateStatus = new CertificateStatusView({
|
|
||||||
$el: $certStatus,
|
|
||||||
model: this.model
|
|
||||||
});
|
|
||||||
|
|
||||||
$upgradeMessage.remove();
|
|
||||||
} else {
|
|
||||||
// Styles are applied to these elements which will be visible if they're empty.
|
|
||||||
$upgradeMessage.remove();
|
|
||||||
$certStatus.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expired) {
|
|
||||||
this.expiredNotification = new ExpiredNotificationView({
|
|
||||||
$el: $expiredNotification,
|
|
||||||
model: this.model
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'gettext',
|
'gettext',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'text!../../../templates/learner_dashboard/course_enroll.underscore'
|
'text!../../../templates/learner_dashboard/course_enroll.underscore'
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
Backbone,
|
Backbone,
|
||||||
$,
|
$,
|
||||||
@@ -17,11 +17,12 @@
|
|||||||
pageTpl
|
pageTpl
|
||||||
) {
|
) {
|
||||||
return Backbone.View.extend({
|
return Backbone.View.extend({
|
||||||
|
className: 'course-enroll-view',
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
tpl: HtmlUtils.template(pageTpl),
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .enroll-button': 'handleEnroll',
|
'click .enroll-button': 'handleEnroll'
|
||||||
'change .run-select': 'handleCourseRunSelect'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
@@ -29,9 +30,6 @@
|
|||||||
this.enrollModel = options.enrollModel;
|
this.enrollModel = options.enrollModel;
|
||||||
this.urlModel = options.urlModel;
|
this.urlModel = options.urlModel;
|
||||||
this.render();
|
this.render();
|
||||||
if (this.urlModel) {
|
|
||||||
this.trackSelectionUrl = this.urlModel.get('track_selection_url');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
@@ -41,16 +39,23 @@
|
|||||||
HtmlUtils.setHtml(this.$el, filledTemplate);
|
HtmlUtils.setHtml(this.$el, filledTemplate);
|
||||||
HtmlUtils.setHtml(this.$parentEl, HtmlUtils.HTML(this.$el));
|
HtmlUtils.setHtml(this.$parentEl, HtmlUtils.HTML(this.$el));
|
||||||
}
|
}
|
||||||
|
this.postRender();
|
||||||
|
},
|
||||||
|
|
||||||
|
postRender: function() {
|
||||||
|
if (this.urlModel) {
|
||||||
|
this.trackSelectionUrl = this.urlModel.get('track_selection_url');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEnroll: function() {
|
handleEnroll: function() {
|
||||||
// Enrollment click event handled here
|
// Enrollment click event handled here
|
||||||
if (!this.model.get('course_run_key')) {
|
var courseRunKey = $('.run-select').val() || this.model.get('course_run_key');
|
||||||
this.$('.select-error').css('visibility', 'visible');
|
this.model.updateCourseRun(courseRunKey);
|
||||||
} else if (!this.model.get('is_enrolled')) {
|
if (!this.model.get('is_enrolled')) {
|
||||||
// Create the enrollment.
|
// Create the enrollment.
|
||||||
this.enrollModel.save({
|
this.enrollModel.save({
|
||||||
course_id: this.model.get('course_run_key')
|
course_id: courseRunKey
|
||||||
}, {
|
}, {
|
||||||
success: _.bind(this.enrollSuccess, this),
|
success: _.bind(this.enrollSuccess, this),
|
||||||
error: _.bind(this.enrollError, this)
|
error: _.bind(this.enrollError, this)
|
||||||
@@ -58,19 +63,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleCourseRunSelect: function(event) {
|
|
||||||
var courseRunKey = $(event.target).val();
|
|
||||||
|
|
||||||
if (courseRunKey) {
|
|
||||||
this.model.updateCourseRun(courseRunKey);
|
|
||||||
} else {
|
|
||||||
// Set back the unselected states
|
|
||||||
this.model.setUnselected();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
enrollSuccess: function() {
|
enrollSuccess: function() {
|
||||||
var courseRunKey = this.model.get('course_run_key');
|
var courseRunKey = this.model.get('course_run_key');
|
||||||
|
window.analytics.track('edx.bi.user.program-details.enrollment');
|
||||||
if (this.trackSelectionUrl) {
|
if (this.trackSelectionUrl) {
|
||||||
// Go to track selection page
|
// Go to track selection page
|
||||||
this.redirect(this.trackSelectionUrl + courseRunKey);
|
this.redirect(this.trackSelectionUrl + courseRunKey);
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'underscore',
|
|
||||||
'gettext',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'text!../../../templates/learner_dashboard/course_enroll_2017.underscore'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
Backbone,
|
|
||||||
$,
|
|
||||||
_,
|
|
||||||
gettext,
|
|
||||||
HtmlUtils,
|
|
||||||
pageTpl
|
|
||||||
) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
className: 'course-enroll-view',
|
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
|
||||||
|
|
||||||
events: {
|
|
||||||
'click .enroll-button': 'handleEnroll'
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
this.$parentEl = options.$parentEl;
|
|
||||||
this.enrollModel = options.enrollModel;
|
|
||||||
this.urlModel = options.urlModel;
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var filledTemplate;
|
|
||||||
if (this.$parentEl && this.enrollModel) {
|
|
||||||
filledTemplate = this.tpl(this.model.toJSON());
|
|
||||||
HtmlUtils.setHtml(this.$el, filledTemplate);
|
|
||||||
HtmlUtils.setHtml(this.$parentEl, HtmlUtils.HTML(this.$el));
|
|
||||||
}
|
|
||||||
this.postRender();
|
|
||||||
},
|
|
||||||
|
|
||||||
postRender: function() {
|
|
||||||
if (this.urlModel) {
|
|
||||||
this.trackSelectionUrl = this.urlModel.get('track_selection_url');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEnroll: function() {
|
|
||||||
// Enrollment click event handled here
|
|
||||||
var courseRunKey = $('.run-select').val() || this.model.get('course_run_key');
|
|
||||||
this.model.updateCourseRun(courseRunKey);
|
|
||||||
if (!this.model.get('is_enrolled')) {
|
|
||||||
// Create the enrollment.
|
|
||||||
this.enrollModel.save({
|
|
||||||
course_id: courseRunKey
|
|
||||||
}, {
|
|
||||||
success: _.bind(this.enrollSuccess, this),
|
|
||||||
error: _.bind(this.enrollError, this)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
enrollSuccess: function() {
|
|
||||||
var courseRunKey = this.model.get('course_run_key');
|
|
||||||
window.analytics.track('edx.bi.user.program-details.enrollment');
|
|
||||||
if (this.trackSelectionUrl) {
|
|
||||||
// Go to track selection page
|
|
||||||
this.redirect(this.trackSelectionUrl + courseRunKey);
|
|
||||||
} else {
|
|
||||||
this.model.set({
|
|
||||||
is_enrolled: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
enrollError: function(model, response) {
|
|
||||||
if (response.status === 403 && response.responseJSON.user_message_url) {
|
|
||||||
/**
|
|
||||||
* Check if we've been blocked from the course
|
|
||||||
* because of country access rules.
|
|
||||||
* If so, redirect to a page explaining to the user
|
|
||||||
* why they were blocked.
|
|
||||||
*/
|
|
||||||
this.redirect(response.responseJSON.user_message_url);
|
|
||||||
} else if (this.trackSelectionUrl) {
|
|
||||||
/**
|
|
||||||
* Otherwise, go to the track selection page as usual.
|
|
||||||
* This can occur, for example, when a course does not
|
|
||||||
* have a free enrollment mode, so we can't auto-enroll.
|
|
||||||
*/
|
|
||||||
this.redirect(this.trackSelectionUrl + this.model.get('course_run_key'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
redirect: function(url) {
|
|
||||||
window.location.href = url;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
(function(define) {
|
(function(define) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'gettext',
|
'gettext',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'js/learner_dashboard/collections/course_card_collection',
|
'js/learner_dashboard/collections/course_card_collection',
|
||||||
'js/learner_dashboard/views/program_header_view',
|
'js/learner_dashboard/views/program_header_view',
|
||||||
'js/learner_dashboard/views/collection_list_view',
|
'js/learner_dashboard/views/collection_list_view',
|
||||||
'js/learner_dashboard/views/course_card_view',
|
'js/learner_dashboard/views/course_card_view',
|
||||||
'text!../../../templates/learner_dashboard/program_details_view.underscore'
|
'js/learner_dashboard/views/program_details_sidebar_view',
|
||||||
],
|
'text!../../../templates/learner_dashboard/program_details_view.underscore'
|
||||||
|
],
|
||||||
function(
|
function(
|
||||||
Backbone,
|
Backbone,
|
||||||
$,
|
$,
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
HeaderView,
|
HeaderView,
|
||||||
CollectionListView,
|
CollectionListView,
|
||||||
CourseCardView,
|
CourseCardView,
|
||||||
|
SidebarView,
|
||||||
pageTpl
|
pageTpl
|
||||||
) {
|
) {
|
||||||
return Backbone.View.extend({
|
return Backbone.View.extend({
|
||||||
@@ -32,15 +33,37 @@
|
|||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.programModel = new Backbone.Model(this.options.programData);
|
this.programModel = new Backbone.Model(this.options.programData);
|
||||||
this.courseCardCollection = new CourseCardCollection(
|
this.courseData = new Backbone.Model(this.options.courseData);
|
||||||
this.programModel.get('courses'),
|
this.certificateCollection = new Backbone.Collection(this.options.certificateData);
|
||||||
|
this.completedCourseCollection = new CourseCardCollection(
|
||||||
|
this.courseData.get('completed') || [],
|
||||||
this.options.userPreferences
|
this.options.userPreferences
|
||||||
);
|
);
|
||||||
|
this.inProgressCourseCollection = new CourseCardCollection(
|
||||||
|
this.courseData.get('in_progress') || [],
|
||||||
|
this.options.userPreferences
|
||||||
|
);
|
||||||
|
this.remainingCourseCollection = new CourseCardCollection(
|
||||||
|
this.courseData.get('not_started') || [],
|
||||||
|
this.options.userPreferences
|
||||||
|
);
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
HtmlUtils.setHtml(this.$el, this.tpl());
|
var completedCount = this.completedCourseCollection.length,
|
||||||
|
inProgressCount = this.inProgressCourseCollection.length,
|
||||||
|
remainingCount = this.remainingCourseCollection.length,
|
||||||
|
totalCount = completedCount + inProgressCount + remainingCount,
|
||||||
|
data = {
|
||||||
|
totalCount: totalCount,
|
||||||
|
inProgressCount: inProgressCount,
|
||||||
|
remainingCount: remainingCount,
|
||||||
|
completedCount: completedCount
|
||||||
|
};
|
||||||
|
data = $.extend(data, this.programModel.toJSON());
|
||||||
|
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
||||||
this.postRender();
|
this.postRender();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -48,16 +71,41 @@
|
|||||||
this.headerView = new HeaderView({
|
this.headerView = new HeaderView({
|
||||||
model: new Backbone.Model(this.options)
|
model: new Backbone.Model(this.options)
|
||||||
});
|
});
|
||||||
new CollectionListView({
|
|
||||||
el: '.js-course-list',
|
if (this.remainingCourseCollection.length > 0) {
|
||||||
childView: CourseCardView,
|
new CollectionListView({
|
||||||
collection: this.courseCardCollection,
|
el: '.js-course-list-remaining',
|
||||||
context: this.options,
|
childView: CourseCardView,
|
||||||
titleContext: {
|
collection: this.remainingCourseCollection,
|
||||||
el: 'h2',
|
context: this.options
|
||||||
title: 'Course List'
|
}).render();
|
||||||
}
|
}
|
||||||
}).render();
|
|
||||||
|
if (this.completedCourseCollection.length > 0) {
|
||||||
|
new CollectionListView({
|
||||||
|
el: '.js-course-list-completed',
|
||||||
|
childView: CourseCardView,
|
||||||
|
collection: this.completedCourseCollection,
|
||||||
|
context: this.options
|
||||||
|
}).render();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.inProgressCourseCollection.length > 0) {
|
||||||
|
// This is last because the context is modified below
|
||||||
|
new CollectionListView({
|
||||||
|
el: '.js-course-list-in-progress',
|
||||||
|
childView: CourseCardView,
|
||||||
|
collection: this.inProgressCourseCollection,
|
||||||
|
context: $.extend(this.options, {enrolled: gettext('Enrolled')})
|
||||||
|
}).render();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sidebarView = new SidebarView({
|
||||||
|
el: '.js-program-sidebar',
|
||||||
|
model: this.programModel,
|
||||||
|
courseModel: this.courseData,
|
||||||
|
certificateCollection: this.certificateCollection
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'underscore',
|
|
||||||
'gettext',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'js/learner_dashboard/collections/course_card_collection',
|
|
||||||
'js/learner_dashboard/views/program_header_view_2017',
|
|
||||||
'js/learner_dashboard/views/collection_list_view',
|
|
||||||
'js/learner_dashboard/views/course_card_view_2017',
|
|
||||||
'js/learner_dashboard/views/program_details_sidebar_view',
|
|
||||||
'text!../../../templates/learner_dashboard/program_details_view_2017.underscore'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
Backbone,
|
|
||||||
$,
|
|
||||||
_,
|
|
||||||
gettext,
|
|
||||||
HtmlUtils,
|
|
||||||
CourseCardCollection,
|
|
||||||
HeaderView,
|
|
||||||
CollectionListView,
|
|
||||||
CourseCardView,
|
|
||||||
SidebarView,
|
|
||||||
pageTpl
|
|
||||||
) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
el: '.js-program-details-wrapper',
|
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
this.options = options;
|
|
||||||
this.programModel = new Backbone.Model(this.options.programData);
|
|
||||||
this.courseData = new Backbone.Model(this.options.courseData);
|
|
||||||
this.certificateCollection = new Backbone.Collection(this.options.certificateData);
|
|
||||||
this.completedCourseCollection = new CourseCardCollection(
|
|
||||||
this.courseData.get('completed') || [],
|
|
||||||
this.options.userPreferences
|
|
||||||
);
|
|
||||||
this.inProgressCourseCollection = new CourseCardCollection(
|
|
||||||
this.courseData.get('in_progress') || [],
|
|
||||||
this.options.userPreferences
|
|
||||||
);
|
|
||||||
this.remainingCourseCollection = new CourseCardCollection(
|
|
||||||
this.courseData.get('not_started') || [],
|
|
||||||
this.options.userPreferences
|
|
||||||
);
|
|
||||||
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var completedCount = this.completedCourseCollection.length,
|
|
||||||
inProgressCount = this.inProgressCourseCollection.length,
|
|
||||||
remainingCount = this.remainingCourseCollection.length,
|
|
||||||
totalCount = completedCount + inProgressCount + remainingCount,
|
|
||||||
data = {
|
|
||||||
totalCount: totalCount,
|
|
||||||
inProgressCount: inProgressCount,
|
|
||||||
remainingCount: remainingCount,
|
|
||||||
completedCount: completedCount
|
|
||||||
};
|
|
||||||
data = $.extend(data, this.programModel.toJSON());
|
|
||||||
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
|
||||||
this.postRender();
|
|
||||||
},
|
|
||||||
|
|
||||||
postRender: function() {
|
|
||||||
this.headerView = new HeaderView({
|
|
||||||
model: new Backbone.Model(this.options)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.remainingCourseCollection.length > 0) {
|
|
||||||
new CollectionListView({
|
|
||||||
el: '.js-course-list-remaining',
|
|
||||||
childView: CourseCardView,
|
|
||||||
collection: this.remainingCourseCollection,
|
|
||||||
context: this.options
|
|
||||||
}).render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.completedCourseCollection.length > 0) {
|
|
||||||
new CollectionListView({
|
|
||||||
el: '.js-course-list-completed',
|
|
||||||
childView: CourseCardView,
|
|
||||||
collection: this.completedCourseCollection,
|
|
||||||
context: this.options
|
|
||||||
}).render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.inProgressCourseCollection.length > 0) {
|
|
||||||
// This is last because the context is modified below
|
|
||||||
new CollectionListView({
|
|
||||||
el: '.js-course-list-in-progress',
|
|
||||||
childView: CourseCardView,
|
|
||||||
collection: this.inProgressCourseCollection,
|
|
||||||
context: $.extend(this.options, {enrolled: gettext('Enrolled')})
|
|
||||||
}).render();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sidebarView = new SidebarView({
|
|
||||||
el: '.js-program-sidebar',
|
|
||||||
model: this.programModel,
|
|
||||||
courseModel: this.courseData,
|
|
||||||
certificateCollection: this.certificateCollection
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -2,17 +2,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'text!../../../templates/learner_dashboard/program_header_view.underscore',
|
'text!../../../templates/learner_dashboard/program_header_view.underscore',
|
||||||
'picturefill'
|
'text!../../../images/programs/micromasters-program-details.svg',
|
||||||
],
|
'text!../../../images/programs/xseries-program-details.svg',
|
||||||
function(Backbone, $, HtmlUtils, pageTpl, picturefill) {
|
'text!../../../images/programs/professional-certificate-program-details.svg'
|
||||||
|
],
|
||||||
|
function(Backbone, $, HtmlUtils, pageTpl, MicroMastersLogo,
|
||||||
|
XSeriesLogo, ProfessionalCertificateLogo) {
|
||||||
return Backbone.View.extend({
|
return Backbone.View.extend({
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
min: {
|
min: {
|
||||||
'medium': '768px',
|
medium: '768px',
|
||||||
'large': '1180px'
|
large: '1180px'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -24,32 +27,29 @@
|
|||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLogo: function() {
|
||||||
|
var logo = false,
|
||||||
|
type = this.model.get('programData').type;
|
||||||
|
|
||||||
|
if (type === 'MicroMasters') {
|
||||||
|
logo = MicroMastersLogo;
|
||||||
|
} else if (type === 'XSeries') {
|
||||||
|
logo = XSeriesLogo;
|
||||||
|
} else if (type === 'Professional Certificate') {
|
||||||
|
logo = ProfessionalCertificateLogo;
|
||||||
|
}
|
||||||
|
return logo;
|
||||||
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var data = $.extend(this.model.toJSON(), {
|
var data = $.extend(this.model.toJSON(), {
|
||||||
breakpoints: this.breakpoints
|
breakpoints: this.breakpoints,
|
||||||
|
logo: this.getLogo()
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.model.get('programData')) {
|
if (this.model.get('programData')) {
|
||||||
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
||||||
this.postRender();
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
postRender: function() {
|
|
||||||
// To resolve a bug in IE with picturefill reevaluate images
|
|
||||||
if (navigator.userAgent.indexOf('MSIE') !== -1 ||
|
|
||||||
navigator.appVersion.indexOf('Trident/') > 0) {
|
|
||||||
/* Microsoft Internet Explorer detected in. */
|
|
||||||
window.setTimeout(function() {
|
|
||||||
this.reEvaluatePicture();
|
|
||||||
}.bind(this), 100);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reEvaluatePicture: function() {
|
|
||||||
picturefill({
|
|
||||||
reevaluate: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'text!../../../templates/learner_dashboard/program_header_view_2017.underscore',
|
|
||||||
'text!../../../images/programs/micromasters-program-details.svg',
|
|
||||||
'text!../../../images/programs/xseries-program-details.svg',
|
|
||||||
'text!../../../images/programs/professional-certificate-program-details.svg'
|
|
||||||
],
|
|
||||||
function(Backbone, $, HtmlUtils, pageTpl, MicroMastersLogo,
|
|
||||||
XSeriesLogo, ProfessionalCertificateLogo) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
breakpoints: {
|
|
||||||
min: {
|
|
||||||
medium: '768px',
|
|
||||||
large: '1180px'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
el: '.js-program-header',
|
|
||||||
|
|
||||||
tpl: HtmlUtils.template(pageTpl),
|
|
||||||
|
|
||||||
initialize: function() {
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
getLogo: function() {
|
|
||||||
var logo = false,
|
|
||||||
type = this.model.get('programData').type;
|
|
||||||
|
|
||||||
if (type === 'MicroMasters') {
|
|
||||||
logo = MicroMastersLogo;
|
|
||||||
} else if (type === 'XSeries') {
|
|
||||||
logo = XSeriesLogo;
|
|
||||||
} else if (type === 'Professional Certificate') {
|
|
||||||
logo = ProfessionalCertificateLogo;
|
|
||||||
}
|
|
||||||
return logo;
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var data = $.extend(this.model.toJSON(), {
|
|
||||||
breakpoints: this.breakpoints,
|
|
||||||
logo: this.getLogo()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.model.get('programData')) {
|
|
||||||
HtmlUtils.setHtml(this.$el, this.tpl(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -1,25 +1,22 @@
|
|||||||
(function(define) {
|
(function(define) {
|
||||||
'use strict';
|
'use strict';
|
||||||
define(['backbone',
|
define(['backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'underscore',
|
'underscore',
|
||||||
'gettext',
|
'gettext',
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
'edx-ui-toolkit/js/utils/html-utils',
|
||||||
'text!../../../templates/learner_dashboard/upgrade_message.underscore',
|
'text!../../../templates/learner_dashboard/upgrade_message.underscore'
|
||||||
'text!../../../templates/learner_dashboard/certificate_icon.underscore'
|
],
|
||||||
],
|
|
||||||
function(
|
function(
|
||||||
Backbone,
|
Backbone,
|
||||||
$,
|
$,
|
||||||
_,
|
_,
|
||||||
gettext,
|
gettext,
|
||||||
HtmlUtils,
|
HtmlUtils,
|
||||||
upgradeMessageTpl,
|
upgradeMessageTpl
|
||||||
certificateIconTpl
|
|
||||||
) {
|
) {
|
||||||
return Backbone.View.extend({
|
return Backbone.View.extend({
|
||||||
messageTpl: HtmlUtils.template(upgradeMessageTpl),
|
messageTpl: HtmlUtils.template(upgradeMessageTpl),
|
||||||
iconTpl: HtmlUtils.template(certificateIconTpl),
|
|
||||||
|
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.$el = options.$el;
|
this.$el = options.$el;
|
||||||
@@ -29,7 +26,6 @@
|
|||||||
render: function() {
|
render: function() {
|
||||||
var data = this.model.toJSON();
|
var data = this.model.toJSON();
|
||||||
|
|
||||||
data = $.extend(data, {certificateSvg: this.iconTpl()});
|
|
||||||
HtmlUtils.setHtml(this.$el, this.messageTpl(data));
|
HtmlUtils.setHtml(this.$el, this.messageTpl(data));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
(function(define) {
|
|
||||||
'use strict';
|
|
||||||
define(['backbone',
|
|
||||||
'jquery',
|
|
||||||
'underscore',
|
|
||||||
'gettext',
|
|
||||||
'edx-ui-toolkit/js/utils/html-utils',
|
|
||||||
'text!../../../templates/learner_dashboard/upgrade_message_2017.underscore'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
Backbone,
|
|
||||||
$,
|
|
||||||
_,
|
|
||||||
gettext,
|
|
||||||
HtmlUtils,
|
|
||||||
upgradeMessageTpl
|
|
||||||
) {
|
|
||||||
return Backbone.View.extend({
|
|
||||||
messageTpl: HtmlUtils.template(upgradeMessageTpl),
|
|
||||||
|
|
||||||
initialize: function(options) {
|
|
||||||
this.$el = options.$el;
|
|
||||||
this.render();
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
|
||||||
var data = this.model.toJSON();
|
|
||||||
|
|
||||||
HtmlUtils.setHtml(this.$el, this.messageTpl(data));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}).call(this, define || RequireJS.define);
|
|
||||||
@@ -17,7 +17,7 @@ define([
|
|||||||
var programData = $.extend({}, data);
|
var programData = $.extend({}, data);
|
||||||
|
|
||||||
programData.course_runs[0].is_enrolled = isEnrolled;
|
programData.course_runs[0].is_enrolled = isEnrolled;
|
||||||
setFixtures('<div class="course-card card"></div>');
|
setFixtures('<div class="program-course-card"></div>');
|
||||||
courseCardModel = new CourseCardModel(programData);
|
courseCardModel = new CourseCardModel(programData);
|
||||||
view = new CourseCardView({
|
view = new CourseCardView({
|
||||||
model: courseCardModel
|
model: courseCardModel
|
||||||
@@ -26,12 +26,10 @@ define([
|
|||||||
|
|
||||||
validateCourseInfoDisplay = function() {
|
validateCourseInfoDisplay = function() {
|
||||||
// DRY validation for course card in enrolled state
|
// DRY validation for course card in enrolled state
|
||||||
expect(view.$('.header-img').attr('src')).toEqual(course.course_runs[0].image.src);
|
|
||||||
expect(view.$('.course-details .course-title-link').text().trim()).toEqual(course.title);
|
expect(view.$('.course-details .course-title-link').text().trim()).toEqual(course.title);
|
||||||
expect(view.$('.course-details .course-title-link').attr('href')).toEqual(
|
expect(view.$('.course-details .course-title-link').attr('href')).toEqual(
|
||||||
course.course_runs[0].marketing_url
|
course.course_runs[0].marketing_url
|
||||||
);
|
);
|
||||||
expect(view.$('.course-details .course-text .course-key').html()).toEqual(course.key);
|
|
||||||
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
||||||
startDate + ' - ' + endDate
|
startDate + ' - ' + endDate
|
||||||
);
|
);
|
||||||
@@ -99,7 +97,9 @@ define([
|
|||||||
it('should show the course advertised start date', function() {
|
it('should show the course advertised start date', function() {
|
||||||
var advertisedStart = 'A long time ago...';
|
var advertisedStart = 'A long time ago...';
|
||||||
course.course_runs[0].advertised_start = advertisedStart;
|
course.course_runs[0].advertised_start = advertisedStart;
|
||||||
|
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
|
|
||||||
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
expect(view.$('.course-details .course-text .run-period').html()).toEqual(
|
||||||
advertisedStart + ' - ' + endDate
|
advertisedStart + ' - ' + endDate
|
||||||
);
|
);
|
||||||
@@ -108,13 +108,12 @@ define([
|
|||||||
it('should only show certificate status section if a certificate has been earned', function() {
|
it('should only show certificate status section if a certificate has been earned', function() {
|
||||||
var certUrl = 'sample-certificate';
|
var certUrl = 'sample-certificate';
|
||||||
|
|
||||||
expect(view.$('.certificate-status').length).toEqual(0);
|
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||||
view.remove();
|
view.remove();
|
||||||
|
|
||||||
course.course_runs[0].certificate_url = certUrl;
|
course.course_runs[0].certificate_url = certUrl;
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
expect(view.$('.certificate-status').length).toEqual(1);
|
expect(view.$('.course-certificate .certificate-status').length).toEqual(1);
|
||||||
expect(view.$('.certificate-status .cta-secondary').attr('href')).toEqual(certUrl);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should only show upgrade message section if an upgrade is required', function() {
|
it('should only show upgrade message section if an upgrade is required', function() {
|
||||||
@@ -135,7 +134,7 @@ define([
|
|||||||
course.course_runs[0].certificate_url = '';
|
course.course_runs[0].certificate_url = '';
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
expect(view.$('.upgrade-message').length).toEqual(0);
|
expect(view.$('.upgrade-message').length).toEqual(0);
|
||||||
expect(view.$('.certificate-status').length).toEqual(0);
|
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||||
view.remove();
|
view.remove();
|
||||||
|
|
||||||
// Verify that the upgrade message takes priority.
|
// Verify that the upgrade message takes priority.
|
||||||
@@ -143,7 +142,7 @@ define([
|
|||||||
course.course_runs[0].certificate_url = '/path/to/certificate';
|
course.course_runs[0].certificate_url = '/path/to/certificate';
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
expect(view.$('.upgrade-message').length).toEqual(1);
|
expect(view.$('.upgrade-message').length).toEqual(1);
|
||||||
expect(view.$('.certificate-status').length).toEqual(0);
|
expect(view.$('.course-certificate .certificate-status').length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show a message if an there is an upcoming course run', function() {
|
it('should show a message if an there is an upcoming course run', function() {
|
||||||
@@ -151,9 +150,7 @@ define([
|
|||||||
|
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
|
|
||||||
expect(view.$('.header-img').attr('src')).toEqual(course.course_runs[0].image.src);
|
|
||||||
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
||||||
expect(view.$('.course-details .course-text .course-key').html()).toEqual(course.key);
|
|
||||||
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
||||||
expect(view.$('.no-action-message').text().trim()).toBe('Coming Soon');
|
expect(view.$('.no-action-message').text().trim()).toBe('Coming Soon');
|
||||||
expect(view.$('.enrollment-open-date').text().trim()).toEqual(
|
expect(view.$('.enrollment-open-date').text().trim()).toEqual(
|
||||||
@@ -167,27 +164,21 @@ define([
|
|||||||
|
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
|
|
||||||
expect(view.$('.header-img').attr('src')).toEqual(course.course_runs[0].image.src);
|
|
||||||
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
expect(view.$('.course-details .course-title').text().trim()).toEqual(course.title);
|
||||||
expect(view.$('.course-details .course-text .course-key').html()).toEqual(course.key);
|
|
||||||
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
expect(view.$('.course-details .course-text .run-period').length).toBe(0);
|
||||||
expect(view.$('.no-action-message').text().trim()).toBe('Not Currently Available');
|
expect(view.$('.no-action-message').text().trim()).toBe('Not Currently Available');
|
||||||
expect(view.$('.enrollment-opens').length).toEqual(0);
|
expect(view.$('.enrollment-opens').length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should link to the marketing site when a URL is available', function() {
|
it('should link to the marketing site when a URL is available', function() {
|
||||||
$.each(['.course-image-link', '.course-title-link'], function(index, selector) {
|
expect(view.$('.course-title-link').attr('href')).toEqual(course.course_runs[0].marketing_url);
|
||||||
expect(view.$(selector).attr('href')).toEqual(course.course_runs[0].marketing_url);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should link to the course home when no marketing URL is available', function() {
|
it('should link to the course home when no marketing URL is available', function() {
|
||||||
course.course_runs[0].marketing_url = null;
|
course.course_runs[0].marketing_url = null;
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
|
|
||||||
$.each(['.course-image-link', '.course-title-link'], function(index, selector) {
|
expect(view.$('.course-title-link').attr('href')).toEqual(course.course_runs[0].course_url);
|
||||||
expect(view.$(selector).attr('href')).toEqual(course.course_runs[0].course_url);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not link to the marketing site or the course home if neither URL is available', function() {
|
it('should not link to the marketing site or the course home if neither URL is available', function() {
|
||||||
@@ -195,9 +186,7 @@ define([
|
|||||||
course.course_runs[0].course_url = null;
|
course.course_runs[0].course_url = null;
|
||||||
setupView(course, false);
|
setupView(course, false);
|
||||||
|
|
||||||
$.each(['.course-image-link', '.course-title-link'], function(index, selector) {
|
expect(view.$('.course-title-link').length).toEqual(0);
|
||||||
expect(view.$(selector).length).toEqual(0);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
|
// Stub analytics tracking
|
||||||
|
window.analytics = jasmine.createSpyObj('analytics', ['track']);
|
||||||
|
|
||||||
// NOTE: This data is redefined prior to each test case so that tests
|
// NOTE: This data is redefined prior to each test case so that tests
|
||||||
// can't break each other by modifying data copied by reference.
|
// can't break each other by modifying data copied by reference.
|
||||||
singleCourseRunList = [{
|
singleCourseRunList = [{
|
||||||
@@ -132,8 +135,6 @@ define([
|
|||||||
|
|
||||||
it('should render the course enroll view when not enrolled', function() {
|
it('should render the course enroll view when not enrolled', function() {
|
||||||
setupView(singleCourseRunList);
|
setupView(singleCourseRunList);
|
||||||
|
|
||||||
expect(view.$('.enrollment-info').html().trim()).toEqual('Not Enrolled');
|
|
||||||
expect(view.$('.enroll-button').text().trim()).toEqual('Enroll Now');
|
expect(view.$('.enroll-button').text().trim()).toEqual('Enroll Now');
|
||||||
expect(view.$('.run-select').length).toBe(0);
|
expect(view.$('.run-select').length).toBe(0);
|
||||||
});
|
});
|
||||||
@@ -142,24 +143,10 @@ define([
|
|||||||
singleCourseRunList[0].is_enrolled = true;
|
singleCourseRunList[0].is_enrolled = true;
|
||||||
|
|
||||||
setupView(singleCourseRunList);
|
setupView(singleCourseRunList);
|
||||||
|
expect(view.$('.view-course-button').text().trim()).toEqual('View Course');
|
||||||
expect(view.$('.enrollment-info').html().trim()).toEqual('enrolled');
|
|
||||||
expect(view.$('.view-course-link').attr('href')).toEqual(course.course_runs[0].course_url);
|
|
||||||
expect(view.$('.view-course-link').text().trim()).toEqual('View Course');
|
|
||||||
expect(view.$('.run-select').length).toBe(0);
|
expect(view.$('.run-select').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow the learner to view an archived course', function() {
|
|
||||||
// Regression test for ECOM-4974.
|
|
||||||
singleCourseRunList[0].is_enrolled = true;
|
|
||||||
singleCourseRunList[0].is_enrollment_open = false;
|
|
||||||
singleCourseRunList[0].is_course_ended = true;
|
|
||||||
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
|
|
||||||
expect(view.$('.view-course-link').text().trim()).toEqual('View Archived Course');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not render anything if course runs are empty', function() {
|
it('should not render anything if course runs are empty', function() {
|
||||||
setupView([]);
|
setupView([]);
|
||||||
|
|
||||||
@@ -172,24 +159,8 @@ define([
|
|||||||
setupView(multiCourseRunList);
|
setupView(multiCourseRunList);
|
||||||
|
|
||||||
expect(view.$('.run-select').length).toBe(1);
|
expect(view.$('.run-select').length).toBe(1);
|
||||||
expect(view.$('.run-select').val()).toEqual('');
|
expect(view.$('.run-select').val()).toEqual(multiCourseRunList[0].key);
|
||||||
expect(view.$('.run-select option').length).toBe(3);
|
expect(view.$('.run-select option').length).toBe(2);
|
||||||
});
|
|
||||||
|
|
||||||
it('should switch course run context if an option is selected from the dropdown', function() {
|
|
||||||
setupView(multiCourseRunList);
|
|
||||||
|
|
||||||
spyOn(courseCardModel, 'updateCourseRun').and.callThrough();
|
|
||||||
|
|
||||||
expect(view.$('.run-select').val()).toEqual('');
|
|
||||||
|
|
||||||
view.$('.run-select').val(multiCourseRunList[1].key);
|
|
||||||
view.$('.run-select').trigger('change');
|
|
||||||
|
|
||||||
expect(view.$('.run-select').val()).toEqual(multiCourseRunList[1].key);
|
|
||||||
expect(courseCardModel.updateCourseRun)
|
|
||||||
.toHaveBeenCalledWith(multiCourseRunList[1].key);
|
|
||||||
expect(courseCardModel.get('course_key')).toEqual(course.key);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should enroll learner when enroll button is clicked with one course run available', function() {
|
it('should enroll learner when enroll button is clicked with one course run available', function() {
|
||||||
@@ -304,6 +275,15 @@ define([
|
|||||||
response.responseJSON.user_message_url
|
response.responseJSON.user_message_url
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends analytics event when enrollment succeeds', function() {
|
||||||
|
setupView(singleCourseRunList, urls);
|
||||||
|
spyOn(view, 'redirect');
|
||||||
|
view.enrollSuccess();
|
||||||
|
expect(window.analytics.track).toHaveBeenCalledWith(
|
||||||
|
'edx.bi.user.program-details.enrollment'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,289 +0,0 @@
|
|||||||
define([
|
|
||||||
'backbone',
|
|
||||||
'jquery',
|
|
||||||
'js/learner_dashboard/models/course_card_model',
|
|
||||||
'js/learner_dashboard/models/course_enroll_model',
|
|
||||||
'js/learner_dashboard/views/course_enroll_view_2017'
|
|
||||||
], function(Backbone, $, CourseCardModel, CourseEnrollModel, CourseEnrollView) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
describe('Course Enroll View', function() {
|
|
||||||
var view = null,
|
|
||||||
courseCardModel,
|
|
||||||
courseEnrollModel,
|
|
||||||
urlModel,
|
|
||||||
setupView,
|
|
||||||
singleCourseRunList,
|
|
||||||
multiCourseRunList,
|
|
||||||
course = {
|
|
||||||
key: 'WageningenX+FFESx',
|
|
||||||
uuid: '9f8562eb-f99b-45c7-b437-799fd0c15b6a',
|
|
||||||
title: 'Systems thinking and environmental sustainability',
|
|
||||||
owners: [
|
|
||||||
{
|
|
||||||
uuid: '0c6e5fa2-96e8-40b2-9ebe-c8b0df2a3b22',
|
|
||||||
key: 'WageningenX',
|
|
||||||
name: 'Wageningen University & Research'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
urls = {
|
|
||||||
commerce_api_url: '/commerce',
|
|
||||||
track_selection_url: '/select_track/course/'
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
// Stub analytics tracking
|
|
||||||
window.analytics = jasmine.createSpyObj('analytics', ['track']);
|
|
||||||
|
|
||||||
// NOTE: This data is redefined prior to each test case so that tests
|
|
||||||
// can't break each other by modifying data copied by reference.
|
|
||||||
singleCourseRunList = [{
|
|
||||||
key: 'course-v1:WageningenX+FFESx+1T2017',
|
|
||||||
uuid: '2f2edf03-79e6-4e39-aef0-65436a6ee344',
|
|
||||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
|
||||||
image: {
|
|
||||||
src: 'https://example.com/2f2edf03-79e6-4e39-aef0-65436a6ee344.jpg'
|
|
||||||
},
|
|
||||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-ffesx',
|
|
||||||
start: '2017-02-28T05:00:00Z',
|
|
||||||
end: '2017-05-30T23:00:00Z',
|
|
||||||
enrollment_start: '2017-01-18T00:00:00Z',
|
|
||||||
enrollment_end: null,
|
|
||||||
type: 'verified',
|
|
||||||
certificate_url: '',
|
|
||||||
course_url: 'https://courses.example.com/courses/course-v1:edX+DemoX+Demo_Course',
|
|
||||||
enrollment_open_date: 'Jan 18, 2016',
|
|
||||||
is_course_ended: false,
|
|
||||||
is_enrolled: false,
|
|
||||||
is_enrollment_open: true,
|
|
||||||
upgrade_url: ''
|
|
||||||
}];
|
|
||||||
|
|
||||||
multiCourseRunList = [{
|
|
||||||
key: 'course-v1:WageningenX+FFESx+2T2016',
|
|
||||||
uuid: '9bbb7844-4848-44ab-8e20-0be6604886e9',
|
|
||||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
|
||||||
image: {
|
|
||||||
src: 'https://example.com/9bbb7844-4848-44ab-8e20-0be6604886e9.jpg'
|
|
||||||
},
|
|
||||||
short_description: 'Learn how to apply systems thinking to improve food production systems.',
|
|
||||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-stesx',
|
|
||||||
start: '2016-09-08T04:00:00Z',
|
|
||||||
end: '2016-11-11T00:00:00Z',
|
|
||||||
enrollment_start: null,
|
|
||||||
enrollment_end: null,
|
|
||||||
pacing_type: 'instructor_paced',
|
|
||||||
type: 'verified',
|
|
||||||
certificate_url: '',
|
|
||||||
course_url: 'https://courses.example.com/courses/course-v1:WageningenX+FFESx+2T2016',
|
|
||||||
enrollment_open_date: 'Jan 18, 2016',
|
|
||||||
is_course_ended: false,
|
|
||||||
is_enrolled: false,
|
|
||||||
is_enrollment_open: true
|
|
||||||
}, {
|
|
||||||
key: 'course-v1:WageningenX+FFESx+1T2017',
|
|
||||||
uuid: '2f2edf03-79e6-4e39-aef0-65436a6ee344',
|
|
||||||
title: 'Food Security and Sustainability: Systems thinking and environmental sustainability',
|
|
||||||
image: {
|
|
||||||
src: 'https://example.com/2f2edf03-79e6-4e39-aef0-65436a6ee344.jpg'
|
|
||||||
},
|
|
||||||
marketing_url: 'https://www.edx.org/course/food-security-sustainability-systems-wageningenx-ffesx',
|
|
||||||
start: '2017-02-28T05:00:00Z',
|
|
||||||
end: '2017-05-30T23:00:00Z',
|
|
||||||
enrollment_start: '2017-01-18T00:00:00Z',
|
|
||||||
enrollment_end: null,
|
|
||||||
type: 'verified',
|
|
||||||
certificate_url: '',
|
|
||||||
course_url: 'https://courses.example.com/courses/course-v1:WageningenX+FFESx+1T2017',
|
|
||||||
enrollment_open_date: 'Jan 18, 2016',
|
|
||||||
is_course_ended: false,
|
|
||||||
is_enrolled: false,
|
|
||||||
is_enrollment_open: true
|
|
||||||
}];
|
|
||||||
});
|
|
||||||
|
|
||||||
setupView = function(courseRuns, urlMap) {
|
|
||||||
course.course_runs = courseRuns;
|
|
||||||
setFixtures('<div class="course-actions"></div>');
|
|
||||||
courseCardModel = new CourseCardModel(course);
|
|
||||||
courseEnrollModel = new CourseEnrollModel({}, {
|
|
||||||
courseId: courseCardModel.get('course_run_key')
|
|
||||||
});
|
|
||||||
if (urlMap) {
|
|
||||||
urlModel = new Backbone.Model(urlMap);
|
|
||||||
}
|
|
||||||
view = new CourseEnrollView({
|
|
||||||
$parentEl: $('.course-actions'),
|
|
||||||
model: courseCardModel,
|
|
||||||
enrollModel: courseEnrollModel,
|
|
||||||
urlModel: urlModel
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
view.remove();
|
|
||||||
urlModel = null;
|
|
||||||
courseCardModel = null;
|
|
||||||
courseEnrollModel = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should exist', function() {
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
expect(view).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render the course enroll view when not enrolled', function() {
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
expect(view.$('.enroll-button').text().trim()).toEqual('Enroll Now');
|
|
||||||
expect(view.$('.run-select').length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render the course enroll view when enrolled', function() {
|
|
||||||
singleCourseRunList[0].is_enrolled = true;
|
|
||||||
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
expect(view.$('.view-course-button').text().trim()).toEqual('View Course');
|
|
||||||
expect(view.$('.run-select').length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not render anything if course runs are empty', function() {
|
|
||||||
setupView([]);
|
|
||||||
|
|
||||||
expect(view.$('.enrollment-info').length).toBe(0);
|
|
||||||
expect(view.$('.run-select').length).toBe(0);
|
|
||||||
expect(view.$('.enroll-button').length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render run selection dropdown if multiple course runs are available', function() {
|
|
||||||
setupView(multiCourseRunList);
|
|
||||||
|
|
||||||
expect(view.$('.run-select').length).toBe(1);
|
|
||||||
expect(view.$('.run-select').val()).toEqual(multiCourseRunList[0].key);
|
|
||||||
expect(view.$('.run-select option').length).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should enroll learner when enroll button is clicked with one course run available', function() {
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
|
|
||||||
spyOn(courseEnrollModel, 'save');
|
|
||||||
|
|
||||||
view.$('.enroll-button').click();
|
|
||||||
|
|
||||||
expect(courseEnrollModel.save).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should enroll learner when enroll button is clicked with multiple course runs available', function() {
|
|
||||||
setupView(multiCourseRunList);
|
|
||||||
|
|
||||||
spyOn(courseEnrollModel, 'save');
|
|
||||||
|
|
||||||
view.$('.run-select').val(multiCourseRunList[1].key);
|
|
||||||
view.$('.run-select').trigger('change');
|
|
||||||
view.$('.enroll-button').click();
|
|
||||||
|
|
||||||
expect(courseEnrollModel.save).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect to track selection when audit enrollment succeeds', function() {
|
|
||||||
singleCourseRunList[0].is_enrolled = false;
|
|
||||||
singleCourseRunList[0].mode_slug = 'audit';
|
|
||||||
|
|
||||||
setupView(singleCourseRunList, urls);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
expect(view.trackSelectionUrl).toBeDefined();
|
|
||||||
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
|
|
||||||
view.enrollSuccess();
|
|
||||||
|
|
||||||
expect(view.redirect).toHaveBeenCalledWith(
|
|
||||||
view.trackSelectionUrl + courseCardModel.get('course_run_key'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect to track selection when enrollment in an unspecified mode is attempted', function() {
|
|
||||||
singleCourseRunList[0].is_enrolled = false;
|
|
||||||
singleCourseRunList[0].mode_slug = null;
|
|
||||||
|
|
||||||
setupView(singleCourseRunList, urls);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
expect(view.trackSelectionUrl).toBeDefined();
|
|
||||||
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
|
|
||||||
view.enrollSuccess();
|
|
||||||
|
|
||||||
expect(view.redirect).toHaveBeenCalledWith(
|
|
||||||
view.trackSelectionUrl + courseCardModel.get('course_run_key')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not redirect when urls are not provided', function() {
|
|
||||||
singleCourseRunList[0].is_enrolled = false;
|
|
||||||
singleCourseRunList[0].mode_slug = 'verified';
|
|
||||||
|
|
||||||
setupView(singleCourseRunList);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
expect(view.verificationUrl).not.toBeDefined();
|
|
||||||
expect(view.dashboardUrl).not.toBeDefined();
|
|
||||||
expect(view.trackSelectionUrl).not.toBeDefined();
|
|
||||||
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
|
|
||||||
view.enrollSuccess();
|
|
||||||
|
|
||||||
expect(view.redirect).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect to track selection on error', function() {
|
|
||||||
setupView(singleCourseRunList, urls);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
expect(view.trackSelectionUrl).toBeDefined();
|
|
||||||
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
|
|
||||||
view.enrollError(courseEnrollModel, {status: 500});
|
|
||||||
expect(view.redirect).toHaveBeenCalledWith(
|
|
||||||
view.trackSelectionUrl + courseCardModel.get('course_run_key')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect to login on 403 error', function() {
|
|
||||||
var response = {
|
|
||||||
status: 403,
|
|
||||||
responseJSON: {
|
|
||||||
user_message_url: 'redirect/to/this'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setupView(singleCourseRunList, urls);
|
|
||||||
|
|
||||||
expect(view.$('.enroll-button').length).toBe(1);
|
|
||||||
expect(view.trackSelectionUrl).toBeDefined();
|
|
||||||
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
|
|
||||||
view.enrollError(courseEnrollModel, response);
|
|
||||||
|
|
||||||
expect(view.redirect).toHaveBeenCalledWith(
|
|
||||||
response.responseJSON.user_message_url
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sends analytics event when enrollment succeeds', function() {
|
|
||||||
setupView(singleCourseRunList, urls);
|
|
||||||
spyOn(view, 'redirect');
|
|
||||||
view.enrollSuccess();
|
|
||||||
expect(window.analytics.track).toHaveBeenCalledWith(
|
|
||||||
'edx.bi.user.program-details.enrollment'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@@ -8,9 +8,6 @@ define([
|
|||||||
describe('Program Details Header View', function() {
|
describe('Program Details Header View', function() {
|
||||||
var view = null,
|
var view = null,
|
||||||
context = {
|
context = {
|
||||||
urls: {
|
|
||||||
program_listing_url: '/dashboard/programs'
|
|
||||||
},
|
|
||||||
programData: {
|
programData: {
|
||||||
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
uuid: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8',
|
||||||
title: 'Food Security and Sustainability',
|
title: 'Food Security and Sustainability',
|
||||||
@@ -68,16 +65,12 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should render the header based on the passed in model', function() {
|
it('should render the header based on the passed in model', function() {
|
||||||
var programListUrl = view.$('.breadcrumb-list .crumb:nth-of-type(2) .crumb-link').attr('href');
|
expect(view.$('.program-title').html()).toEqual(context.programData.title);
|
||||||
|
|
||||||
expect(view.$('.title').html()).toEqual(context.programData.title);
|
|
||||||
expect(view.$('.subtitle').html()).toEqual(context.programData.subtitle);
|
|
||||||
expect(view.$('.org-logo').length).toEqual(context.programData.authoring_organizations.length);
|
expect(view.$('.org-logo').length).toEqual(context.programData.authoring_organizations.length);
|
||||||
expect(view.$('.org-logo').attr('src'))
|
expect(view.$('.org-logo').attr('src'))
|
||||||
.toEqual(context.programData.authoring_organizations[0].certificate_logo_image_url);
|
.toEqual(context.programData.authoring_organizations[0].certificate_logo_image_url);
|
||||||
expect(view.$('.org-logo').attr('alt'))
|
expect(view.$('.org-logo').attr('alt'))
|
||||||
.toEqual(context.programData.authoring_organizations[0].name + '\'s logo');
|
.toEqual(context.programData.authoring_organizations[0].name + '\'s logo');
|
||||||
expect(programListUrl).toEqual(context.urls.program_listing_url);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
define([
|
define([
|
||||||
'backbone',
|
'backbone',
|
||||||
'jquery',
|
'jquery',
|
||||||
'js/learner_dashboard/views/program_details_view_2017'
|
'js/learner_dashboard/views/program_details_view'
|
||||||
], function(Backbone, $, ProgramDetailsView) {
|
], function(Backbone, $, ProgramDetailsView) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
'js/groups/views/cohorts_dashboard_factory',
|
'js/groups/views/cohorts_dashboard_factory',
|
||||||
'js/header_factory',
|
'js/header_factory',
|
||||||
'js/learner_dashboard/program_details_factory',
|
'js/learner_dashboard/program_details_factory',
|
||||||
'js/learner_dashboard/program_details_factory_2017',
|
|
||||||
'js/learner_dashboard/program_list_factory',
|
'js/learner_dashboard/program_list_factory',
|
||||||
'js/search/course/course_search_factory',
|
'js/search/course/course_search_factory',
|
||||||
'js/search/dashboard/dashboard_search_factory',
|
'js/search/dashboard/dashboard_search_factory',
|
||||||
|
|||||||
@@ -746,7 +746,6 @@
|
|||||||
'js/spec/learner_dashboard/program_details_sidebar_view_spec.js',
|
'js/spec/learner_dashboard/program_details_sidebar_view_spec.js',
|
||||||
'js/spec/learner_dashboard/course_card_view_spec.js',
|
'js/spec/learner_dashboard/course_card_view_spec.js',
|
||||||
'js/spec/learner_dashboard/course_enroll_view_spec.js',
|
'js/spec/learner_dashboard/course_enroll_view_spec.js',
|
||||||
'js/spec/learner_dashboard/course_enroll_view_spec_2017.js',
|
|
||||||
'js/spec/markdown_editor_spec.js',
|
'js/spec/markdown_editor_spec.js',
|
||||||
'js/spec/dateutil_factory_spec.js',
|
'js/spec/dateutil_factory_spec.js',
|
||||||
'js/spec/navigation_spec.js',
|
'js/spec/navigation_spec.js',
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<article class="course" role="region" aria-label="<%- content.display_name %>">
|
|
||||||
<a href="/courses/<%- course %>/about">
|
|
||||||
<section class="course-info" aria-hidden="true">
|
|
||||||
<h2 class="course-name">
|
|
||||||
<span class="course-organization"><%- org %></span>
|
|
||||||
<span class="course-code"><%- content.number %></span>
|
|
||||||
<span class="course-title"><%- content.display_name %></span>
|
|
||||||
</h2>
|
|
||||||
<div class="course-date" aria-hidden="true">
|
|
||||||
<%- interpolate(
|
|
||||||
gettext("Starts: %(start_date)s"),
|
|
||||||
{ start_date: start }, true
|
|
||||||
) %>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<div class="sr">
|
|
||||||
<ul>
|
|
||||||
<li><%- org %></li>
|
|
||||||
<li><%- content.number %></li>
|
|
||||||
<li><%- gettext("Starts") %><time itemprop="startDate" datetime="<%- start %>"><%- start %></time></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</article>
|
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
<div class="message col-12 md-col-8">
|
<p class="certificate-status col-12 md-col-8">
|
||||||
<% // safe-lint: disable=underscore-not-escaped %>
|
<span class="card-msg"><%- gettext('Certificate Status:') %></span>
|
||||||
<span class="certificate-icon green-icon" aria-hidden="true"><%= certificateSvg %></span>
|
<span class="fa fa-check-circle" aria-hidden="true"></span>
|
||||||
<span class="card-msg"><%- gettext('Congratulations! You have earned a certificate for this course.') %></span>
|
<span class="certificate-status-msg"><%- gettext('Certificate Purchased') %></span>
|
||||||
</div>
|
</p>
|
||||||
<div class="action col-12 md-col-4">
|
|
||||||
<a href="<%- certificate_url %>" class="btn-brand cta-secondary">
|
|
||||||
<% // safe-lint: disable=underscore-not-escaped %>
|
|
||||||
<span class="certificate-icon blue-icon" aria-hidden="true"><%= certificateSvg %></span>
|
|
||||||
<%- gettext('View Certificate') %>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
<p class="certificate-status col-12 md-col-8">
|
|
||||||
<span class="card-msg"><%- gettext('Certificate Status:') %></span>
|
|
||||||
<span class="fa fa-check-circle" aria-hidden="true"></span>
|
|
||||||
<span class="certificate-status-msg"><%- gettext('Certificate Purchased') %></span>
|
|
||||||
</p>
|
|
||||||
@@ -1,21 +1,7 @@
|
|||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="course-meta-container col-12 md-col-8 sm-col-12">
|
<div class="course-meta-container col-12 md-col-8 sm-col-12">
|
||||||
<div class="course-image-container">
|
|
||||||
<% if ( marketing_url || course_url ) { %>
|
|
||||||
<a href="<%- marketing_url || course_url %>" class="course-image-link">
|
|
||||||
<img
|
|
||||||
class="header-img"
|
|
||||||
src="<%- course_image_url %>"
|
|
||||||
<% // safe-lint: disable=underscore-not-escaped %>
|
|
||||||
alt="<%= interpolate(gettext('%(courseName)s Home Page.'), {courseName: title}, true) %>"/>
|
|
||||||
</a>
|
|
||||||
<% } else { %>
|
|
||||||
<img class="header-img" src="<%- course_image_url %>" alt=""/>
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="course-details">
|
<div class="course-details">
|
||||||
<h3 class="course-title">
|
<h5 class="course-title">
|
||||||
<% if ( marketing_url || course_url ) { %>
|
<% if ( marketing_url || course_url ) { %>
|
||||||
<a href="<%- marketing_url || course_url %>" class="course-title-link">
|
<a href="<%- marketing_url || course_url %>" class="course-title-link">
|
||||||
<%- title %>
|
<%- title %>
|
||||||
@@ -23,19 +9,20 @@
|
|||||||
<% } else { %>
|
<% } else { %>
|
||||||
<%- title %>
|
<%- title %>
|
||||||
<% } %>
|
<% } %>
|
||||||
</h3>
|
</h5>
|
||||||
<div class="course-text">
|
<div class="course-text">
|
||||||
<% if (start_date && end_date) { %>
|
<% if (enrolled) { %>
|
||||||
<span class="run-period"><%- start_date %> - <%- end_date %></span>
|
<span class="enrolled"><%- enrolled %>: </span>
|
||||||
-
|
<% } %>
|
||||||
|
<% if (dateString) { %>
|
||||||
|
<span class="run-period"><%- dateString %></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
<span class="course-key"><%- course_key %></span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="course-actions col-12 md-col-4 sm-col-12"></div>
|
||||||
<div class="course-actions col-12 md-col-4 sm-col-12">
|
<div class="course-certificate certificate-status"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section action-msg-view"></div>
|
<div class="section action-msg-view"></div>
|
||||||
<div class="section upgrade-message"></div>
|
<div class="section upgrade-message"></div>
|
||||||
<div class="section certificate-status"></div>
|
<div class="section expired-notification"></div>
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<div class="section">
|
|
||||||
<div class="course-meta-container col-12 md-col-8 sm-col-12">
|
|
||||||
<div class="course-details">
|
|
||||||
<h5 class="course-title">
|
|
||||||
<% if ( marketing_url || course_url ) { %>
|
|
||||||
<a href="<%- marketing_url || course_url %>" class="course-title-link">
|
|
||||||
<%- title %>
|
|
||||||
</a>
|
|
||||||
<% } else { %>
|
|
||||||
<%- title %>
|
|
||||||
<% } %>
|
|
||||||
</h5>
|
|
||||||
<div class="course-text">
|
|
||||||
<% if (enrolled) { %>
|
|
||||||
<span class='enrolled'><%- enrolled %>: </span>
|
|
||||||
<% } %>
|
|
||||||
<% if (dateString) { %>
|
|
||||||
<span class="run-period"><%- dateString %></span>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="course-actions col-12 md-col-4 sm-col-12"></div>
|
|
||||||
<div class="course-certificate certificate-status"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="section action-msg-view"></div>
|
|
||||||
<div class="section upgrade-message"></div>
|
|
||||||
<div class="section expired-notification"></div>
|
|
||||||
@@ -1,29 +1,19 @@
|
|||||||
<% if (is_enrolled) { %>
|
<% if (is_enrolled && (typeof expired === 'undefined' || expired === false)) { %>
|
||||||
<div class="enrollment-info"><%- gettext('enrolled') %></div>
|
<a href="<%- course_url %>" class="view-course-button btn-brand btn cta-primary">
|
||||||
<% if (is_enrollment_open || is_course_ended) { %>
|
<% if (is_course_ended) { %>
|
||||||
<a href="<%- course_url %>" class="btn view-course-link">
|
<%- gettext('View Archived Course') %>
|
||||||
<% if (is_enrollment_open) { %>
|
<% } else { %>
|
||||||
<%- gettext('View Course') %>
|
<%- gettext('View Course') %>
|
||||||
<% } else if (is_course_ended) { %>
|
<% } %>
|
||||||
<%- gettext('View Archived Course') %>
|
</a>
|
||||||
<% } %>
|
|
||||||
</a>
|
|
||||||
<% } %>
|
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
<% if (enrollable_course_runs.length > 0) { %>
|
<% if (enrollable_course_runs.length > 0) { %>
|
||||||
<div class="enrollment-info"><%- gettext('Not Enrolled') %></div>
|
|
||||||
<% if (enrollable_course_runs.length > 1) { %>
|
<% if (enrollable_course_runs.length > 1) { %>
|
||||||
<div class="run-select-container">
|
<div class="run-select-container">
|
||||||
<div class="select-error">
|
<label class="select-choice" for="select-<%- course_key %>-run">
|
||||||
<%- gettext('Please select a course date') %>
|
<%- gettext('Choose a course run:') %>
|
||||||
</div>
|
|
||||||
<label class="sr-only" for="select-<%- course_key %>-run">
|
|
||||||
<%- gettext('Select Course Run') %>
|
|
||||||
</label>
|
</label>
|
||||||
<select id="select-<%- course_key %>-run" class="run-select" autocomplete="off">
|
<select id="select-<%- course_key %>-run" class="run-select field-input input-select" autocomplete="off">
|
||||||
<option value="" selected="selected">
|
|
||||||
<%- gettext('Choose Course Date') %>
|
|
||||||
</option>
|
|
||||||
<% _.each (enrollable_course_runs, function(courseRun) { %>
|
<% _.each (enrollable_course_runs, function(courseRun) { %>
|
||||||
<option
|
<option
|
||||||
value="<%- courseRun.key %>"
|
value="<%- courseRun.key %>"
|
||||||
@@ -31,19 +21,17 @@
|
|||||||
selected="selected"
|
selected="selected"
|
||||||
<% }%>
|
<% }%>
|
||||||
>
|
>
|
||||||
<%= interpolate(
|
<%- courseRun.dateString %>
|
||||||
gettext('Starts %(start)s'),
|
|
||||||
{ start: courseRun.start_date },
|
|
||||||
true)
|
|
||||||
%>
|
|
||||||
</option>
|
</option>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
<button type="button" class="btn-brand btn cta-primary enroll-button">
|
<div class="enroll-button">
|
||||||
<%- gettext('Enroll Now') %>
|
<button type="button" class="btn-brand btn cta-primary">
|
||||||
</button>
|
<%- gettext('Enroll Now') %>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<% } else if (upcoming_course_runs.length > 0) {%>
|
<% } else if (upcoming_course_runs.length > 0) {%>
|
||||||
<div class="no-action-message">
|
<div class="no-action-message">
|
||||||
<%- gettext('Coming Soon') %>
|
<%- gettext('Coming Soon') %>
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<% if (is_enrolled && (typeof expired === 'undefined' || expired === false)) { %>
|
|
||||||
<a href="<%- course_url %>" class="view-course-button btn-brand btn cta-primary">
|
|
||||||
<% if (is_course_ended) { %>
|
|
||||||
<%- gettext('View Archived Course') %>
|
|
||||||
<% } else { %>
|
|
||||||
<%- gettext('View Course') %>
|
|
||||||
<% } %>
|
|
||||||
</a>
|
|
||||||
<% } else { %>
|
|
||||||
<% if (enrollable_course_runs.length > 0) { %>
|
|
||||||
<% if (enrollable_course_runs.length > 1) { %>
|
|
||||||
<div class="run-select-container">
|
|
||||||
<label class="select-choice" for="select-<%- course_key %>-run">
|
|
||||||
<%- gettext('Choose a course run:') %>
|
|
||||||
</label>
|
|
||||||
<select id="select-<%- course_key %>-run" class="run-select field-input input-select" autocomplete="off">
|
|
||||||
<% _.each (enrollable_course_runs, function(courseRun) { %>
|
|
||||||
<option
|
|
||||||
value="<%- courseRun.key %>"
|
|
||||||
<% if (key === courseRun.key) { %>
|
|
||||||
selected="selected"
|
|
||||||
<% }%>
|
|
||||||
>
|
|
||||||
<%- courseRun.dateString %>
|
|
||||||
</option>
|
|
||||||
<% }); %>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<div class="enroll-button">
|
|
||||||
<button type="button" class="btn-brand btn cta-primary">
|
|
||||||
<%- gettext('Enroll Now') %>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<% } else if (upcoming_course_runs.length > 0) {%>
|
|
||||||
<div class="no-action-message">
|
|
||||||
<%- gettext('Coming Soon') %>
|
|
||||||
</div>
|
|
||||||
<div class="enrollment-opens">
|
|
||||||
<%- gettext('Enrollment Opens on') %>
|
|
||||||
<span class="enrollment-open-date">
|
|
||||||
<%- upcoming_course_runs[0].enrollment_open_date %>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<% } else { %>
|
|
||||||
<div class="no-action-message">
|
|
||||||
<%- gettext('Not Currently Available') %>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<% } %>
|
|
||||||
@@ -15,6 +15,8 @@ from openedx.core.djangolib.js_utils import (
|
|||||||
<%static:require_module module_name="js/learner_dashboard/program_details_factory" class_name="ProgramDetailsFactory">
|
<%static:require_module module_name="js/learner_dashboard/program_details_factory" class_name="ProgramDetailsFactory">
|
||||||
ProgramDetailsFactory({
|
ProgramDetailsFactory({
|
||||||
programData: ${program_data | n, dump_js_escaped_json},
|
programData: ${program_data | n, dump_js_escaped_json},
|
||||||
|
courseData: ${course_data | n, dump_js_escaped_json},
|
||||||
|
certificateData: ${certificate_data | n, dump_js_escaped_json},
|
||||||
urls: ${urls | n, dump_js_escaped_json},
|
urls: ${urls | n, dump_js_escaped_json},
|
||||||
userPreferences: ${user_preferences | n, dump_js_escaped_json},
|
userPreferences: ${user_preferences | n, dump_js_escaped_json},
|
||||||
});
|
});
|
||||||
@@ -24,8 +26,6 @@ ProgramDetailsFactory({
|
|||||||
<%block name="pagetitle">${_("Program Details")}</%block>
|
<%block name="pagetitle">${_("Program Details")}</%block>
|
||||||
<%block name="bodyclass">program-details</%block>
|
<%block name="bodyclass">program-details</%block>
|
||||||
|
|
||||||
<%include file="_dashboard_navigation_programs.html"/>
|
|
||||||
|
|
||||||
<main id="main" aria-label="Content" tabindex="-1">
|
<main id="main" aria-label="Content" tabindex="-1">
|
||||||
<div class="js-program-details-wrapper"></div>
|
<div class="js-program-details-wrapper program-details-wrapper"></div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
## Override the default styles_version to the Pattern Library version (version 2)
|
|
||||||
<%! main_css = "style-learner-dashboard" %>
|
|
||||||
|
|
||||||
<%page expression_filter="h"/>
|
|
||||||
<%inherit file="../main.html" />
|
|
||||||
<%namespace name='static' file='../static_content.html'/>
|
|
||||||
<%!
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from openedx.core.djangolib.js_utils import (
|
|
||||||
dump_js_escaped_json, js_escaped_string
|
|
||||||
)
|
|
||||||
%>
|
|
||||||
|
|
||||||
<%block name="js_extra">
|
|
||||||
<%static:require_module module_name="js/learner_dashboard/program_details_factory_2017" class_name="ProgramDetailsFactory2017">
|
|
||||||
ProgramDetailsFactory2017({
|
|
||||||
programData: ${program_data | n, dump_js_escaped_json},
|
|
||||||
courseData: ${course_data | n, dump_js_escaped_json},
|
|
||||||
certificateData: ${certificate_data | n, dump_js_escaped_json},
|
|
||||||
urls: ${urls | n, dump_js_escaped_json},
|
|
||||||
userPreferences: ${user_preferences | n, dump_js_escaped_json},
|
|
||||||
});
|
|
||||||
</%static:require_module>
|
|
||||||
</%block>
|
|
||||||
|
|
||||||
<%block name="pagetitle">${_("Program Details")}</%block>
|
|
||||||
<%block name="bodyclass">program-details</%block>
|
|
||||||
|
|
||||||
<main id="main" aria-label="Content" tabindex="-1">
|
|
||||||
<div class="js-program-details-wrapper program-details-wrapper"></div>
|
|
||||||
</main>
|
|
||||||
@@ -1,6 +1,59 @@
|
|||||||
<header class="js-program-header program-header full-width-banner"></header>
|
<header class="js-program-header program-header full-width-banner"></header>
|
||||||
<div class="program-details-content grid-container">
|
<section class="program-details-content">
|
||||||
<div class="js-program-progress-view"></div>
|
<div class="program-heading">
|
||||||
<div class="js-course-list row"></div>
|
<% if (inProgressCount === totalCount) { %>
|
||||||
<aside class="js-course-sidebar"></aside>
|
<h3 class="program-heading-title"><%- gettext('Congratulations!') %></h3>
|
||||||
</div>
|
<div class="program-heading-message">
|
||||||
|
<div><%- interpolate(gettext(
|
||||||
|
'You have successfully completed all the requirements for the %(title)s %(type)s.'),
|
||||||
|
{ title: title, type: type }, true) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% } else { %>
|
||||||
|
<h3 class="program-heading-title"><%- gettext('Your Program Journey') %></h3>
|
||||||
|
<div class="program-heading-message">
|
||||||
|
<div>
|
||||||
|
<%- interpolate(gettext(
|
||||||
|
'Track and plan your progress through the %(count)s courses in this program.'),
|
||||||
|
{ count: totalCount }, true) %>
|
||||||
|
</div>
|
||||||
|
<div><%- gettext('To complete the program, you must earn a verified certificate for each course.') %></div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
<div class="course-list-headings">
|
||||||
|
<% if (inProgressCount) { %>
|
||||||
|
<div class="in-progress-group">
|
||||||
|
<h4 class="course-list-heading">
|
||||||
|
<span class="status"><%- gettext('COURSES IN PROGRESS') %></span>
|
||||||
|
<span class="count"><%- inProgressCount %></span>
|
||||||
|
</h4>
|
||||||
|
<div class="course-list js-course-list-in-progress row"></div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<% if (remainingCount) { %>
|
||||||
|
<div class="remaining-group">
|
||||||
|
<h4 class="course-list-heading">
|
||||||
|
<span class="status"><%- gettext('REMAINING COURSES') %></span>
|
||||||
|
<span class="count"><%- remainingCount %></span>
|
||||||
|
</h4>
|
||||||
|
<div class="course-list js-course-list-remaining row"></div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<div class="completed-group">
|
||||||
|
<h4 class="course-list-heading">
|
||||||
|
<span class="status"><%- gettext('COMPLETED COURSES') %></span>
|
||||||
|
<span class="count"><%- completedCount %></span>
|
||||||
|
</h4>
|
||||||
|
<% if (completedCount) { %>
|
||||||
|
<div class="course-list js-course-list-completed row"></div>
|
||||||
|
<% } else { %>
|
||||||
|
<div class="motivating-section">
|
||||||
|
<p class='motivating-heading'><%- gettext("As you complete courses, you will see them listed here.") %></p>
|
||||||
|
<p class='motivating-message'><%- gettext('Complete courses on your schedule to ensure you stand out in your field!') %></p>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<aside class="js-program-sidebar program-sidebar"></aside>
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
<header class="js-program-header program-header full-width-banner"></header>
|
|
||||||
<section class="program-details-content">
|
|
||||||
<div class="program-heading">
|
|
||||||
<% if (inProgressCount === totalCount) { %>
|
|
||||||
<h3 class="program-heading-title"><%- gettext('Congratulations!') %></h3>
|
|
||||||
<div class="program-heading-message">
|
|
||||||
<div><%- interpolate(gettext(
|
|
||||||
'You have successfully completed all the requirements for the %(title)s %(type)s.'),
|
|
||||||
{ title: title, type: type }, true) %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% } else { %>
|
|
||||||
<h3 class="program-heading-title"><%- gettext('Your Program Journey') %></h3>
|
|
||||||
<div class="program-heading-message">
|
|
||||||
<div>
|
|
||||||
<%- interpolate(gettext(
|
|
||||||
'Track and plan your progress through the %(count)s courses in this program.'),
|
|
||||||
{ count: totalCount }, true) %>
|
|
||||||
</div>
|
|
||||||
<div><%- gettext('To complete the program, you must earn a verified certificate for each course.') %></div>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
<div class="course-list-headings">
|
|
||||||
<% if (inProgressCount) { %>
|
|
||||||
<div class="in-progress-group">
|
|
||||||
<h4 class="course-list-heading">
|
|
||||||
<span class="status"><%- gettext('COURSES IN PROGRESS') %></span>
|
|
||||||
<span class="count"><%- inProgressCount %></span>
|
|
||||||
</h4>
|
|
||||||
<div class="course-list js-course-list-in-progress row"></div>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<% if (remainingCount) { %>
|
|
||||||
<div class="remaining-group">
|
|
||||||
<h4 class="course-list-heading">
|
|
||||||
<span class="status"><%- gettext('REMAINING COURSES') %></span>
|
|
||||||
<span class="count"><%- remainingCount %></span>
|
|
||||||
</h4>
|
|
||||||
<div class="course-list js-course-list-remaining row"></div>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
<div class="completed-group">
|
|
||||||
<h4 class="course-list-heading">
|
|
||||||
<span class="status"><%- gettext('COMPLETED COURSES') %></span>
|
|
||||||
<span class="count"><%- completedCount %></span>
|
|
||||||
</h4>
|
|
||||||
<% if (completedCount) { %>
|
|
||||||
<div class="course-list js-course-list-completed row"></div>
|
|
||||||
<% } else { %>
|
|
||||||
<div class="motivating-section">
|
|
||||||
<p class='motivating-heading'><%- gettext("As you complete courses, you will see them listed here.") %></p>
|
|
||||||
<p class='motivating-message'><%- gettext('Complete courses on your schedule to ensure you stand out in your field!') %></p>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<aside class="js-program-sidebar program-sidebar"></aside>
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
<div class="banner-background-wrapper">
|
<div class="program-details-header">
|
||||||
<picture>
|
<div class="meta-info grid-container">
|
||||||
<source srcset="<%- programData.banner_image.large.url %>" media="(min-width: <%- breakpoints.min.large %>)">
|
<% if (logo) { %>
|
||||||
<source srcset="<%- programData.banner_image.medium.url %>" media="(min-width: <%- breakpoints.min.medium %>)">
|
<span aria-label="<%- gettext(programData.type) %>" class="<%- programData.type.toLowerCase() %> program-details-icon"><%= logo %></span>
|
||||||
<img class="banner-background-image" srcset="<%- programData.banner_image['x-small'].url %>" alt="">
|
<% } %>
|
||||||
</picture>
|
<h2 class="hd-1 program-title"><%- programData.title %></h2>
|
||||||
|
</div>
|
||||||
<div class="banner-content grid-container">
|
<div class='authoring-organizations'>
|
||||||
<h2 class="hd-1 title row"><%- programData.title %></h2>
|
<h2 class="heading">Institutions</h2>
|
||||||
<p class="hd-4 subtitle row"><%- programData.subtitle %></p>
|
|
||||||
<% if (programData.authoring_organizations.length) { %>
|
<% if (programData.authoring_organizations.length) { %>
|
||||||
<div class="org-wrapper">
|
<div class="orgs">
|
||||||
<% _.each(programData.authoring_organizations, function(org) { %>
|
<% _.each(programData.authoring_organizations, function(org) { %>
|
||||||
<img src="<%- org.certificate_logo_image_url || org.logo_image_url %>" class="org-logo" alt="<%- StringUtils.interpolate(
|
<img src="<%- org.certificate_logo_image_url || org.logo_image_url %>" class="org-logo" alt="<%- StringUtils.interpolate(
|
||||||
gettext('{organization}\'s logo'),
|
gettext('{organization}\'s logo'),
|
||||||
@@ -20,20 +19,3 @@
|
|||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="breadcrumb-wrapper grid-container" aria-label="breadcrumb" role="navigation">
|
|
||||||
<h3 class="sr-only"><%- gettext('You are here') %></h2>
|
|
||||||
<ol class="breadcrumb-list">
|
|
||||||
<li class="crumb">
|
|
||||||
<a href="/" class="crumb-link"><%- gettext('Dashboard') %></a>
|
|
||||||
<span class="crumb-separator fa fa-chevron-right" aria-hidden="true"></span>
|
|
||||||
</li>
|
|
||||||
<li class="crumb">
|
|
||||||
<a href="<%- urls.program_listing_url %>" class="crumb-link"><%- gettext('Programs') %></a>
|
|
||||||
<span class="crumb-separator fa fa-chevron-right" aria-hidden="true"></span>
|
|
||||||
</li>
|
|
||||||
<li class="crumb active">
|
|
||||||
<%- programData.title %>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</nav>
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
<div class="program-details-header">
|
|
||||||
<div class="meta-info grid-container">
|
|
||||||
<% if (logo) { %>
|
|
||||||
<span aria-label="<%- gettext(programData.type) %>" class="<%- programData.type.toLowerCase() %> program-details-icon"><%= logo %></span>
|
|
||||||
<% } %>
|
|
||||||
<h2 class="hd-1 program-title"><%- programData.title %></h2>
|
|
||||||
</div>
|
|
||||||
<div class='authoring-organizations'>
|
|
||||||
<h2 class="heading">Institutions</h2>
|
|
||||||
<% if (programData.authoring_organizations.length) { %>
|
|
||||||
<div class="orgs">
|
|
||||||
<% _.each(programData.authoring_organizations, function(org) { %>
|
|
||||||
<img src="<%- org.certificate_logo_image_url || org.logo_image_url %>" class="org-logo" alt="<%- StringUtils.interpolate(
|
|
||||||
gettext('{organization}\'s logo'),
|
|
||||||
{organization: org.name}
|
|
||||||
) %>">
|
|
||||||
<% }) %>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
<div class="message col-12 md-col-8">
|
<div class="message certificate-status col-12 md-col-8">
|
||||||
<% // safe-lint: disable=underscore-not-escaped %>
|
<span class="card-msg"><%- gettext('Certificate Status:') %></span>
|
||||||
<span class="certificate-icon green-icon" aria-hidden="true"><%= certificateSvg %></span>
|
<span><%- gettext('Needs verified certificate ') %></span>
|
||||||
<span class="card-msg"><%- gettext('You need a certificate in this course to be eligible for a program certificate.') %></span>
|
<span class="price"> <%- price %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="action col-12 md-col-4">
|
<div class="action col-12 md-col-4">
|
||||||
<a href="<%- upgrade_url %>" class="btn-brand cta-primary">
|
<a href="<%- upgrade_url %>" class="btn-brand btn cta-primary upgrade-button">
|
||||||
<% // safe-lint: disable=underscore-not-escaped %>
|
<%- gettext('Buy Certificate') %>
|
||||||
<span class="certificate-icon green-icon" aria-hidden="true"><%= certificateSvg %></span>
|
<a>
|
||||||
<%- gettext('Upgrade Now') %>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<div class="message certificate-status col-12 md-col-8">
|
|
||||||
<span class="card-msg"><%- gettext('Certificate Status:') %></span>
|
|
||||||
<span><%- gettext('Needs verified certificate ') %></span>
|
|
||||||
<span class="price"> <%- price %></span>
|
|
||||||
</div>
|
|
||||||
<div class="action col-12 md-col-4">
|
|
||||||
<a href="<%- upgrade_url %>" class="btn-brand btn cta-primary upgrade-button">
|
|
||||||
<%- gettext('Buy Certificate') %>
|
|
||||||
<a>
|
|
||||||
</div>
|
|
||||||
Reference in New Issue
Block a user