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; } }); } );