diff --git a/cms/djangoapps/contentstore/views/videos.py b/cms/djangoapps/contentstore/views/videos.py index 03f288966c..315522e0c4 100644 --- a/cms/djangoapps/contentstore/views/videos.py +++ b/cms/djangoapps/contentstore/views/videos.py @@ -597,7 +597,7 @@ def get_all_transcript_languages(): all_languages_dict = dict(settings.ALL_LANGUAGES, **third_party_transcription_languages) # Return combined system settings and 3rd party transcript languages. all_languages = [] - for key, value in sorted(all_languages_dict.iteritems(), key=lambda (k, v): (v, k)): + for key, value in sorted(all_languages_dict.iteritems(), key=lambda (k, v): v): all_languages.append({ 'language_code': key, 'language_text': value diff --git a/cms/static/js/spec/views/video_transcripts_spec.js b/cms/static/js/spec/views/video_transcripts_spec.js index 36184e842e..4f76d91f37 100644 --- a/cms/static/js/spec/views/video_transcripts_spec.js +++ b/cms/static/js/spec/views/video_transcripts_spec.js @@ -34,11 +34,13 @@ define( TRANSCRIPT_DOWNLOAD_FILE_FORMAT = 'srt', TRANSCRIPT_DOWNLOAD_URL = 'abc.com/transcript_download/course_id', TRANSCRIPT_UPLOAD_URL = 'abc.com/transcript_upload/course_id', + TRANSCRIPT_DELETE_URL = 'abc.com/transcript_delete/course_id', videoSupportedFileFormats = ['.mov', '.mp4'], videoTranscriptSettings = { trancript_download_file_format: TRANSCRIPT_DOWNLOAD_FILE_FORMAT, transcript_download_handler_url: TRANSCRIPT_DOWNLOAD_URL, - transcript_upload_handler_url: TRANSCRIPT_UPLOAD_URL + transcript_upload_handler_url: TRANSCRIPT_UPLOAD_URL, + transcript_delete_handler_url: TRANSCRIPT_DELETE_URL }, videoListView; @@ -119,6 +121,7 @@ define( beforeEach(function() { setFixtures( '
' + + '
' + '
' ); TemplateHelpers.installTemplate('previous-video-upload-list'); @@ -127,7 +130,7 @@ define( it('renders as expected', function() { // Verify transcript container is present. - expect(videoListView.$el.find('.show-video-transcripts-container')).toExist(); + expect(videoListView.$el.find('.video-transcripts-header')).toExist(); // Veirfy transcript column header is present. expect(videoListView.$el.find('.js-table-head .video-head-col.transcripts-col')).toExist(); // Verify transcript data column is present. @@ -139,7 +142,7 @@ define( it('does not render transcripts view if feature is disabled', function() { renderView(transcripts, false); // Verify transcript container is not present. - expect(videoListView.$el.find('.show-video-transcripts-container')).not.toExist(); + expect(videoListView.$el.find('.video-transcripts-header')).not.toExist(); // Veirfy transcript column header is not present. expect(videoListView.$el.find('.js-table-head .video-head-col.transcripts-col')).not.toExist(); // Verify transcript data column is not present. @@ -150,7 +153,7 @@ define( it('does not show list of transcripts initially', function() { expect( - videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden') + videoTranscriptsView.$el.find('.video-transcripts-wrapper').hasClass('hidden') ).toEqual(true); expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual( 'Show transcripts (' + transcripts.length + ')' @@ -160,7 +163,7 @@ define( it('shows list of transcripts when clicked on show transcript button', function() { // Verify transcript container is hidden expect( - videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden') + videoTranscriptsView.$el.find('.video-transcripts-wrapper').hasClass('hidden') ).toEqual(true); // Verify initial button text @@ -171,7 +174,7 @@ define( // Verify transcript container is not hidden expect( - videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden') + videoTranscriptsView.$el.find('.video-transcripts-wrapper').hasClass('hidden') ).toEqual(false); // Verify button text is changed. @@ -191,7 +194,7 @@ define( // Verify transcript container is not hidden expect( - videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden') + videoTranscriptsView.$el.find('.video-transcripts-wrapper').hasClass('hidden') ).toEqual(false); videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click(); @@ -203,7 +206,7 @@ define( // Verify transcript container is hidden expect( - videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden') + videoTranscriptsView.$el.find('.video-transcripts-wrapper').hasClass('hidden') ).toEqual(true); }); @@ -221,12 +224,12 @@ define( var $transcriptEl; // Show transcripts videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click(); - expect(videoTranscriptsView.$el.find('.show-video-transcript-content').length).toEqual( + expect(videoTranscriptsView.$el.find('.video-transcript-content').length).toEqual( transcripts.length ); _.each(transcripts, function(languageCode) { - $transcriptEl = videoTranscriptsView.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len // Verify correct transcript title is set. expect($transcriptEl.find('.transcript-title').html()).toEqual( 'Video client title n_' + languageCode + '.' + TRANSCRIPT_DOWNLOAD_FILE_FORMAT @@ -240,7 +243,7 @@ define( var languageCode = 'en', newLanguageCode = 'ar', requests = AjaxHelpers.requests(this), - $transcriptEl = videoTranscriptsView.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len // Verify correct transcript title is set. expect($transcriptEl.find('.transcript-title').html()).toEqual( @@ -255,7 +258,7 @@ define( // Add transcript to upload queue and send POST request to upload transcript. $transcriptEl.find('.upload-transcript-input').fileupload('add', {files: [createFakeTranscriptFile()]}); - // Verify if POST request received for image upload + // Verify if POST request received for transcript upload AjaxHelpers.expectRequest( requests, 'POST', @@ -276,11 +279,97 @@ define( verifyTranscriptStateInfo($transcriptEl, newLanguageCode); }); + it('can delete transcript', function() { + var languageCode = 'en', + requests = AjaxHelpers.requests(this), + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + + // Verify correct transcript title is set. + expect($transcriptEl.find('.transcript-title').html()).toEqual( + 'Video client title n_' + languageCode + '.' + TRANSCRIPT_DOWNLOAD_FILE_FORMAT + ); + + $transcriptEl.find('.delete-transcript-button').click(); + + // Click remove button on prompt. + $('#page-prompt .action-primary').click(); + + // Verify if DELETE request received for transcript delete + AjaxHelpers.expectRequest( + requests, + 'DELETE', + TRANSCRIPT_DELETE_URL + '/' + edxVideoID + '/' + languageCode + ); + + // Send successful delete response + AjaxHelpers.respondWithJson(requests, {}); + + // Verify English transcript is not present. + expect(videoTranscriptsView.$el.find( + '.video-transcript-content[data-language-code="' + languageCode + '"]' + )).not.toExist(); + + // Verify transcripts view is rendered with transcript deleted for English. + expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual( + 'Show transcripts (2)' + ); + }); + + it('should show error message when deleting a transcript in case of server error', function() { + var languageCode = 'en', + requests = AjaxHelpers.requests(this), + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + + // Verify correct transcript title is set. + expect($transcriptEl.find('.transcript-title').html()).toEqual( + 'Video client title n_' + languageCode + '.' + TRANSCRIPT_DOWNLOAD_FILE_FORMAT + ); + + $transcriptEl.find('.delete-transcript-button').click(); + + // Verify prompt title and description. + + expect($('#page-prompt #prompt-warning-title').html().trim()).toEqual( + 'Are you sure you want to remove this transcript?' + ); + + expect($('#page-prompt #prompt-warning-description').html().trim()).toEqual( + 'If you remove this transcript, the transcript will not be available for any components that use this video.' // eslint-disable-line max-len + ); + + // Click remove button on prompt. + $('#page-prompt .action-primary').click(); + + // Verify if DELETE request received for transcript delete. + AjaxHelpers.expectRequest( + requests, + 'DELETE', + TRANSCRIPT_DELETE_URL + '/' + edxVideoID + '/' + languageCode + ); + + AjaxHelpers.respondWithError(requests, 500); + + // Verify prompt message is shown. + expect($('#page-notification #notification-error-title').html()).toEqual( + "Studio's having trouble saving your work" + ); + + // Verify English transcript container is not removed. + expect(videoTranscriptsView.$el.find( + '.video-transcript-content[data-language-code="' + languageCode + '"]' + )).toExist(); + + // Verify transcripts count is correct. + expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual( + 'Show transcripts (3)' + ); + }); + it('shows error state correctly', function() { var languageCode = 'en', requests = AjaxHelpers.requests(this), errorMessage = 'Transcript failed error message', - $transcriptEl = videoTranscriptsView.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len $transcriptEl.find('.upload-transcript-button').click(); @@ -306,7 +395,7 @@ define( it('should show error message in case of server error', function() { var languageCode = 'en', requests = AjaxHelpers.requests(this), - $transcriptEl = videoTranscriptsView.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len $transcriptEl.find('.upload-transcript-button').click(); @@ -332,7 +421,7 @@ define( var languageCode = 'en', transcriptFileName = 'unsupported-transcript-file-format.txt', errorMessage = 'This file type is not supported. Supported file type is ' + TRANSCRIPT_DOWNLOAD_FILE_FORMAT + '.', // eslint-disable-line max-len - $transcriptEl = videoTranscriptsView.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptEl = videoTranscriptsView.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len $transcriptEl.find('.upload-transcript-button').click(); diff --git a/cms/static/js/views/video_transcripts.js b/cms/static/js/views/video_transcripts.js index 1eca27f741..3081fb2df7 100644 --- a/cms/static/js/views/video_transcripts.js +++ b/cms/static/js/views/video_transcripts.js @@ -13,7 +13,7 @@ define( events: { 'click .toggle-show-transcripts-button': 'toggleShowTranscripts', 'click .upload-transcript-button': 'chooseFile', - 'click .delete-transcript-button': 'removeTranscript', + 'click .delete-transcript-button': 'deleteTranscript', 'click .more-details-action': 'showUploadFailureMessage' }, @@ -106,7 +106,7 @@ define( Toggles Show/Hide transcript button and transcripts container. */ toggleShowTranscripts: function() { - var $transcriptsWrapperEl = this.$el.find('.show-video-transcripts-wrapper'); + var $transcriptsWrapperEl = this.$el.find('.video-transcripts-wrapper'); if ($transcriptsWrapperEl.hasClass('hidden')) { this.showTranscripts(); @@ -119,13 +119,13 @@ define( showTranscripts: function() { // Show transcript wrapper - this.$el.find('.show-video-transcripts-wrapper').removeClass('hidden'); + this.$el.find('.video-transcripts-wrapper').removeClass('hidden'); // Update button text. HtmlUtils.setHtml( this.$el.find('.toggle-show-transcripts-button-text'), StringUtils.interpolate( - gettext('Show transcripts ({transcriptCount})'), + gettext('Hide transcripts ({transcriptCount})'), { transcriptCount: this.transcripts.length } @@ -138,15 +138,15 @@ define( hideTranscripts: function() { // Hide transcript wrapper - this.$el.find('.show-video-transcripts-wrapper').addClass('hidden'); + this.$el.find('.video-transcripts-wrapper').addClass('hidden'); // Update button text. HtmlUtils.setHtml( this.$el.find('.toggle-show-transcripts-button-text'), StringUtils.interpolate( - gettext('Hide transcripts ({transcriptCount})'), + gettext('Show transcripts ({transcriptCount})'), { - transcriptCount: _.size(this.transcripts) + transcriptCount: this.transcripts.length } ) ); @@ -171,7 +171,7 @@ define( }, chooseFile: function(event) { - var $transcriptContainer = $(event.target).parents('.show-video-transcript-content'), + var $transcriptContainer = $(event.target).parents('.video-transcript-content'), $transcriptUploadEl = $transcriptContainer.find('.upload-transcript-input'); $transcriptUploadEl.fileupload({ @@ -191,7 +191,7 @@ define( transcriptSelected: function(event, data) { var errorMessage, - $transcriptContainer = $(event.target).parents('.show-video-transcript-content'); + $transcriptContainer = $(event.target).parents('.video-transcript-content'); errorMessage = this.validateTranscriptUpload(data.files[0]); if (!errorMessage) { @@ -209,7 +209,7 @@ define( transcriptUploadSucceeded: function(event, data) { var languageCode = data.formData.language_code, newLanguageCode = data.formData.new_language_code, - $transcriptContainer = this.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptContainer = this.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len $transcriptContainer.attr('data-language-code', newLanguageCode); $transcriptContainer.find('.download-transcript-button').attr( @@ -238,7 +238,7 @@ define( transcriptUploadFailed: function(event, data) { var errorMessage, languageCode = data.formData.language_code, - $transcriptContainer = this.$el.find('.show-video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len + $transcriptContainer = this.$el.find('.video-transcript-content[data-language-code="' + languageCode + '"]'); // eslint-disable-line max-len try { errorMessage = JSON.parse(data.jqXHR.responseText).error; @@ -252,19 +252,19 @@ define( this.renderMessage($transcriptContainer, 'failed', errorMessage); }, - removeTranscript: function(event) { + deleteTranscript: function(event) { var self = this, - $transcriptEl = $(event.target).parents('.show-video-transcript-content'), + $transcriptEl = $(event.target).parents('.video-transcript-content'), languageCode = $transcriptEl.attr('data-language-code'), - transcriptDeleteUrl = this.getTranscriptDeleteUrl( - this.edxVideoID, + transcriptDeleteUrl = self.getTranscriptDeleteUrl( + self.edxVideoID, languageCode, - this.videoTranscriptSettings.transcript_delete_handler_url + self.videoTranscriptSettings.transcript_delete_handler_url ); ViewUtils.confirmThenRunOperation( - gettext('Are you sure you want to remove this transcript from the video?'), - gettext('Removing a transcript from this video will have impact on all the video components using this video.'), // eslint-disable-line max-len + gettext('Are you sure you want to remove this transcript?'), + gettext('If you remove this transcript, the transcript will not be available for any components that use this video.'), // eslint-disable-line max-len gettext('Remove'), function() { ViewUtils.runOperationShowingMessage( @@ -275,7 +275,7 @@ define( type: 'DELETE' }).done(function() { // Update transcripts. - self.transcripts = _.omit(self.transcripts, languageCode); + self.transcripts = _.without(self.transcripts, languageCode); // re-render transcripts. self.render(); }); @@ -346,7 +346,11 @@ define( }) ); - this.isCollapsed ? this.hideTranscripts() : this.showTranscripts(); + if (this.isCollapsed) { + this.hideTranscripts(); + } else { + this.showTranscripts(); + } return this; } }); diff --git a/cms/static/sass/views/_video-upload.scss b/cms/static/sass/views/_video-upload.scss index 88f6259929..ad02b56a60 100644 --- a/cms/static/sass/views/_video-upload.scss +++ b/cms/static/sass/views/_video-upload.scss @@ -25,7 +25,7 @@ cursor:pointer } - .show-video-transcripts-wrapper { + .video-transcripts-wrapper { display: block; .button-link { @@ -37,7 +37,7 @@ display: none; } - .show-video-transcript-content { + .video-transcript-content { margin-top: ($baseline/2); .transcript-upload-status-container { diff --git a/cms/templates/js/video-transcripts.underscore b/cms/templates/js/video-transcripts.underscore index 4d9a82cbbe..a5da745ebd 100644 --- a/cms/templates/js/video-transcripts.underscore +++ b/cms/templates/js/video-transcripts.underscore @@ -1,4 +1,4 @@ -
+
<% if (transcripts.length) { %>