207 lines
7.1 KiB
JavaScript
207 lines
7.1 KiB
JavaScript
define([
|
|
'backbone',
|
|
'backbone.validation',
|
|
'jquery',
|
|
'underscore',
|
|
'js/programs/collections/course_runs_collection',
|
|
'js/programs/models/program_model',
|
|
'js/programs/views/confirm_modal_view',
|
|
'js/programs/views/course_details_view',
|
|
'text!templates/programs/program_details.underscore',
|
|
'edx-ui-toolkit/js/utils/html-utils',
|
|
'gettext',
|
|
'js/programs/utils/validation_config'
|
|
],
|
|
function(Backbone, BackboneValidation, $, _, CourseRunsCollection,
|
|
ProgramModel, ModalView, CourseView, ListTpl,
|
|
HtmlUtils) {
|
|
'use strict';
|
|
|
|
return Backbone.View.extend({
|
|
el: '.js-program-admin',
|
|
|
|
events: {
|
|
'blur .js-inline-edit input': 'checkEdit',
|
|
'click .js-add-course': 'addCourse',
|
|
'click .js-enable-edit': 'editField',
|
|
'click .js-publish-program': 'confirmPublish'
|
|
},
|
|
|
|
tpl: HtmlUtils.template(ListTpl),
|
|
|
|
initialize: function() {
|
|
Backbone.Validation.bind(this);
|
|
|
|
this.courseRuns = new CourseRunsCollection([], {
|
|
organization: this.model.get('organizations')[0]
|
|
});
|
|
this.courseRuns.fetch();
|
|
this.courseRuns.on('sync', this.setAvailableCourseRuns, this);
|
|
this.render();
|
|
},
|
|
|
|
render: function() {
|
|
HtmlUtils.setHtml(this.$el, this.tpl(this.model.toJSON()));
|
|
this.postRender();
|
|
},
|
|
|
|
postRender: function() {
|
|
var courses = this.model.get('course_codes');
|
|
|
|
_.each(courses, function(course) {
|
|
var title = course.key + 'Course';
|
|
|
|
this[title] = new CourseView({
|
|
courseRuns: this.courseRuns,
|
|
programModel: this.model,
|
|
courseData: course
|
|
});
|
|
}.bind(this));
|
|
|
|
// Stop listening to the model sync set when publishing
|
|
this.model.off('sync');
|
|
},
|
|
|
|
addCourse: function() {
|
|
return new CourseView({
|
|
courseRuns: this.courseRuns,
|
|
programModel: this.model
|
|
});
|
|
},
|
|
|
|
checkEdit: function(event) {
|
|
var $input = $(event.target),
|
|
$span = $input.prevAll('.js-model-value'),
|
|
$btn = $input.next('.js-enable-edit'),
|
|
value = $input.val(),
|
|
key = $input.data('field'),
|
|
data = {};
|
|
|
|
data[key] = value;
|
|
|
|
$input.addClass('is-hidden');
|
|
$btn.removeClass('is-hidden');
|
|
$span.removeClass('is-hidden');
|
|
|
|
if (this.model.get(key) !== value) {
|
|
this.model.set(data);
|
|
|
|
if (this.model.isValid(true)) {
|
|
this.model.patch(data);
|
|
$span.text(value);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Loads modal that user clicks a confirmation button
|
|
* in to publish the course (or they can cancel out of it)
|
|
*/
|
|
confirmPublish: function(event) {
|
|
event.preventDefault();
|
|
|
|
/**
|
|
* Update validation to make marketing slug required
|
|
* Note that because this validation is not required for
|
|
* the program creation form and is only happening here
|
|
* it makes sense to have the validation at the view level
|
|
*/
|
|
if (this.model.isValid(true) && this.validateMarketingSlug()) {
|
|
this.modalView = new ModalView({
|
|
model: this.model,
|
|
callback: _.bind(this.publishProgram, this),
|
|
content: this.getModalContent(),
|
|
parentEl: '.js-publish-modal',
|
|
parentView: this
|
|
});
|
|
}
|
|
},
|
|
|
|
editField: function(event) {
|
|
/**
|
|
* Making the assumption that users can only see
|
|
* programs that they have permission to edit
|
|
*/
|
|
var $btn = $(event.currentTarget),
|
|
$el = $btn.prev('input');
|
|
|
|
event.preventDefault();
|
|
|
|
$el.prevAll('.js-model-value').addClass('is-hidden');
|
|
$el.removeClass('is-hidden')
|
|
.addClass('edit')
|
|
.focus();
|
|
$btn.addClass('is-hidden');
|
|
},
|
|
|
|
getModalContent: function() {
|
|
return {
|
|
name: gettext('confirm'),
|
|
title: gettext('Publish this program?'),
|
|
body: gettext(
|
|
'After you publish this program, you cannot add or remove course codes or remove course runs.'
|
|
),
|
|
cta: {
|
|
cancel: gettext('Cancel'),
|
|
confirm: gettext('Publish')
|
|
}
|
|
};
|
|
},
|
|
|
|
publishProgram: function() {
|
|
var data = {
|
|
status: 'active'
|
|
};
|
|
|
|
this.model.set(data, {silent: true});
|
|
this.model.on('sync', this.render, this);
|
|
this.model.patch(data);
|
|
},
|
|
|
|
setAvailableCourseRuns: function() {
|
|
var allRuns = this.courseRuns.toJSON(),
|
|
courses = this.model.get('course_codes'),
|
|
selectedRuns,
|
|
availableRuns = allRuns;
|
|
|
|
if (courses.length) {
|
|
selectedRuns = _.pluck(courses, 'run_modes');
|
|
selectedRuns = _.flatten(selectedRuns);
|
|
}
|
|
|
|
availableRuns = _.reject(allRuns, function(run) {
|
|
var selectedCourseRun = _.findWhere(selectedRuns, {
|
|
course_key: run.id,
|
|
start_date: run.start
|
|
});
|
|
|
|
return !_.isUndefined(selectedCourseRun);
|
|
});
|
|
|
|
this.courseRuns.set(availableRuns);
|
|
},
|
|
|
|
validateMarketingSlug: function() {
|
|
var isValid = false,
|
|
$input = {},
|
|
$message = {};
|
|
|
|
if (this.model.get('marketing_slug').length > 0) {
|
|
isValid = true;
|
|
} else {
|
|
$input = this.$el.find('#program-marketing-slug');
|
|
$message = $input.siblings('.field-message');
|
|
|
|
// Update DOM
|
|
$input.addClass('has-error');
|
|
$message.addClass('has-error');
|
|
$message.find('.field-message-content')
|
|
.text(gettext('Marketing Slug is required.'));
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
});
|
|
}
|
|
);
|