(function(define) { 'use strict'; define(['jquery', 'underscore', 'backbone', 'gettext', 'js/groups/models/cohort', 'js/groups/models/verified_track_settings', 'js/groups/views/cohort_editor', 'js/groups/views/cohort_form', 'js/groups/views/course_cohort_settings_notification', 'js/groups/views/verified_track_settings_notification', 'edx-ui-toolkit/js/utils/html-utils', 'js/views/base_dashboard_view', 'js/views/file_uploader', 'js/models/notification', 'js/views/notification', 'string_utils'], function($, _, Backbone, gettext, CohortModel, VerifiedTrackSettingsModel, CohortEditorView, CohortFormView, CourseCohortSettingsNotificationView, VerifiedTrackSettingsNotificationView, HtmlUtils, BaseDashboardView) { var hiddenClass = 'hidden', disabledClass = 'is-disabled', enableCohortsSelector = '.cohorts-state'; var CohortsView = BaseDashboardView.extend({ events: { 'change .cohort-select': 'onCohortSelected', 'change .cohorts-state': 'onCohortsEnabledChanged', 'click .action-create': 'showAddCohortForm', 'click .cohort-management-add-form .action-save': 'saveAddCohortForm', 'click .cohort-management-add-form .action-cancel': 'cancelAddCohortForm', 'click .link-cross-reference': 'showSection', 'click .toggle-cohort-management-secondary': 'showCsvUpload', }, initialize: function(options) { var model = this.model; this.template = HtmlUtils.template($('#cohorts-tpl').text()); this.selectorTemplate = HtmlUtils.template($('#cohort-selector-tpl').text()); this.context = options.context; this.contentGroups = options.contentGroups; this.cohortSettings = options.cohortSettings; model.on('sync', this.onSync, this); // Update cohort counts when the user clicks back on the cohort management tab // (for example, after uploading a csv file of cohort assignments and then // checking results on data download tab). $(this.getSectionCss('cohort_management')).click(function() { model.fetch(); }); }, render: function() { HtmlUtils.setHtml(this.$el, this.template({ cohorts: this.model.models, cohortsEnabled: this.cohortSettings.get('is_cohorted') })); this.onSync(); // Don't create this view until the first render is called, as at that point the // various other models whose state is required to properly view the notification // will have completed their fetch operations. if (!this.verifiedTrackSettingsNotificationView) { var verifiedTrackSettingsModel = new VerifiedTrackSettingsModel(); verifiedTrackSettingsModel.url = this.context.verifiedTrackCohortingUrl; verifiedTrackSettingsModel.fetch({ success: _.bind(this.renderVerifiedTrackSettingsNotificationView, this) }); this.verifiedTrackSettingsNotificationView = new VerifiedTrackSettingsNotificationView({ model: verifiedTrackSettingsModel }); } return this; }, renderSelector: function(selectedCohort) { HtmlUtils.setHtml(this.$('.cohort-select'), this.selectorTemplate({ cohorts: this.model.models, selectedCohort: selectedCohort })); }, renderCourseCohortSettingsNotificationView: function() { var cohortStateMessageNotificationView = new CourseCohortSettingsNotificationView({ el: $('.cohort-state-message'), cohortEnabled: this.getCohortsEnabled() }); cohortStateMessageNotificationView.render(); }, renderVerifiedTrackSettingsNotificationView: function() { if (this.verifiedTrackSettingsNotificationView) { this.verifiedTrackSettingsNotificationView.validateSettings( this.getCohortsEnabled(), this.model.models, this.$(enableCohortsSelector) ); } }, onSync: function(model, response, options) { var selectedCohort = this.lastSelectedCohortId && this.model.get(this.lastSelectedCohortId), hasCohorts = this.model.length > 0, cohortNavElement = this.$('.cohort-management-nav'), additionalCohortControlElement = this.$('.wrapper-cohort-supplemental'), isModelUpdate; isModelUpdate = function() { // Distinguish whether this is a sync event for just one model, or if it is for // an entire collection. return options && options.patch && response.hasOwnProperty('user_partition_id'); }; this.hideAddCohortForm(); if (isModelUpdate()) { // Refresh the selector in case the model's name changed this.renderSelector(selectedCohort); } else if (hasCohorts) { cohortNavElement.removeClass(hiddenClass); additionalCohortControlElement.removeClass(hiddenClass); this.renderSelector(selectedCohort); if (selectedCohort) { this.showCohortEditor(selectedCohort); } } else { cohortNavElement.addClass(hiddenClass); additionalCohortControlElement.addClass(hiddenClass); this.showNotification({ type: 'warning', title: gettext('You currently have no cohorts configured'), actionText: gettext('Add Cohort'), actionClass: 'action-create', actionIconClass: 'fa-plus' }); } this.renderVerifiedTrackSettingsNotificationView(); }, getSelectedCohort: function() { var id = this.$('.cohort-select').val(); return id && this.model.get(parseInt(id)); }, onCohortSelected: function(event) { event.preventDefault(); var selectedCohort = this.getSelectedCohort(); this.lastSelectedCohortId = selectedCohort.get('id'); this.showCohortEditor(selectedCohort); }, onCohortsEnabledChanged: function(event) { event.preventDefault(); this.saveCohortSettings(); }, saveCohortSettings: function() { var self = this, cohortSettings, fieldData = {is_cohorted: this.getCohortsEnabled()}; cohortSettings = this.cohortSettings; cohortSettings.save( fieldData, {patch: true, wait: true} ).done(function() { self.render(); self.renderCourseCohortSettingsNotificationView(); self.pubSub.trigger('cohorts:state', fieldData); }).fail(function(result) { self.showNotification({ type: 'error', title: gettext("We've encountered an error. Refresh your browser and then try again.")}, self.$('.cohorts-state-section') ); }); }, getCohortsEnabled: function() { return this.$(enableCohortsSelector).prop('checked'); }, showCohortEditor: function(cohort) { this.removeNotification(); if (this.editor) { this.editor.setCohort(cohort); $('.cohort-management-group .group-header-title').focus(); } else { this.editor = new CohortEditorView({ el: this.$('.cohort-management-group'), model: cohort, cohorts: this.model, contentGroups: this.contentGroups, context: this.context }); this.editor.render(); $('.cohort-management-group .group-header-title').focus(); } }, showNotification: function(options, beforeElement) { var model = new NotificationModel(options); this.removeNotification(); this.notification = new NotificationView({ model: model }); if (!beforeElement) { beforeElement = this.$('.cohort-management-group'); } beforeElement.before(this.notification.$el); this.notification.render(); }, removeNotification: function() { if (this.notification) { this.notification.remove(); } if (this.cohortFormView) { this.cohortFormView.removeNotification(); } }, showAddCohortForm: function(event) { var newCohort; event.preventDefault(); this.removeNotification(); newCohort = new CohortModel(); newCohort.url = this.model.url; this.cohortFormView = new CohortFormView({ model: newCohort, contentGroups: this.contentGroups, context: this.context }); this.cohortFormView.render(); this.$('.cohort-management-add-form').append(this.cohortFormView.$el); this.cohortFormView.$('.cohort-name').focus(); this.setCohortEditorVisibility(false); }, hideAddCohortForm: function() { this.setCohortEditorVisibility(true); if (this.cohortFormView) { this.cohortFormView.remove(); this.cohortFormView = null; } }, setCohortEditorVisibility: function(showEditor) { if (showEditor) { this.$('.cohorts-state-section').removeClass(disabledClass).attr('aria-disabled', false); this.$('.cohort-management-group').removeClass(hiddenClass); this.$('.cohort-management-nav').removeClass(disabledClass).attr('aria-disabled', false); } else { this.$('.cohorts-state-section').addClass(disabledClass).attr('aria-disabled', true); this.$('.cohort-management-group').addClass(hiddenClass); this.$('.cohort-management-nav').addClass(disabledClass).attr('aria-disabled', true); } }, saveAddCohortForm: function(event) { var self = this, newCohort = this.cohortFormView.model; event.preventDefault(); this.removeNotification(); this.cohortFormView.saveForm() .done(function() { self.lastSelectedCohortId = newCohort.id; self.model.fetch().done(function() { self.showNotification({ type: 'confirmation', title: interpolate_text( gettext('The {cohortGroupName} cohort has been created. You can manually add students to this cohort below.'), {cohortGroupName: newCohort.get('name')} ) }); }); }); }, cancelAddCohortForm: function(event) { event.preventDefault(); this.removeNotification(); this.onSync(); }, showSection: function(event) { event.preventDefault(); var section = $(event.currentTarget).data('section'); $(this.getSectionCss(section)).click(); $(window).scrollTop(0); }, showCsvUpload: function(event) { event.preventDefault(); $(event.currentTarget).addClass(hiddenClass); var uploadElement = this.$('.csv-upload').removeClass(hiddenClass); if (!this.fileUploaderView) { this.fileUploaderView = new FileUploaderView({ el: uploadElement, title: gettext('Assign students to cohorts by uploading a CSV file.'), inputLabel: gettext('Choose a .csv file'), inputTip: gettext('Only properly formatted .csv files will be accepted.'), submitButtonText: gettext('Upload File and Assign Students'), extensions: '.csv', url: this.context.uploadCohortsCsvUrl, successNotification: function(file, event, data) { var message = interpolate_text(gettext( "Your file '{file}' has been uploaded. Allow a few minutes for processing." ), {file: file}); return new NotificationModel({ type: 'confirmation', title: message }); } }).render(); } }, getSectionCss: function(section) { return ".instructor-nav .nav-item [data-section='" + section + "']"; } }); return CohortsView; }); }).call(this, define || RequireJS.define);