From 9a35a5439eba336be3ac440d4f56c06ac53ff03d Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Tue, 7 Nov 2017 13:07:32 -0500 Subject: [PATCH] Revert "Transcript secure credentials" --- cms/djangoapps/contentstore/views/__init__.py | 1 - .../views/tests/test_transcript_settings.py | 171 ------ .../contentstore/views/transcript_settings.py | 110 ---- cms/djangoapps/contentstore/views/videos.py | 37 +- cms/envs/common.py | 3 - cms/static/js/factories/videos_index.js | 2 - .../views/active_video_upload_list_spec.js | 2 +- .../spec/views/course_video_settings_spec.js | 528 +++--------------- .../js/views/active_video_upload_list.js | 2 - cms/static/js/views/course_video_settings.js | 328 ++--------- cms/static/sass/views/_video-upload.scss | 43 +- ...s-update-org-credentials-footer.underscore | 8 - ...settings-update-settings-footer.underscore | 13 - .../js/course-video-settings.underscore | 47 +- ...se-video-transcript-preferences.underscore | 31 - ...video-transcript-provider-empty.underscore | 7 - ...eo-transcript-provider-selected.underscore | 8 - ...script-organization-credentials.underscore | 43 -- cms/templates/videos_index.html | 1 - cms/urls.py | 2 - lms/envs/common.py | 3 - .../djangoapps/video_pipeline/__init__.py | 0 .../core/djangoapps/video_pipeline/admin.py | 9 - openedx/core/djangoapps/video_pipeline/api.py | 51 -- .../video_pipeline/migrations/0001_initial.py | 31 - .../video_pipeline/migrations/__init__.py | 0 .../core/djangoapps/video_pipeline/models.py | 31 - .../video_pipeline/tests/__init__.py | 0 .../djangoapps/video_pipeline/tests/mixins.py | 23 - .../video_pipeline/tests/test_api.py | 99 ---- .../core/djangoapps/video_pipeline/utils.py | 19 - requirements/edx/base.txt | 2 +- 32 files changed, 197 insertions(+), 1458 deletions(-) delete mode 100644 cms/djangoapps/contentstore/views/tests/test_transcript_settings.py delete mode 100644 cms/djangoapps/contentstore/views/transcript_settings.py delete mode 100644 cms/templates/js/course-video-settings-update-org-credentials-footer.underscore delete mode 100644 cms/templates/js/course-video-settings-update-settings-footer.underscore delete mode 100644 cms/templates/js/course-video-transcript-preferences.underscore delete mode 100644 cms/templates/js/course-video-transcript-provider-empty.underscore delete mode 100644 cms/templates/js/course-video-transcript-provider-selected.underscore delete mode 100644 cms/templates/js/transcript-organization-credentials.underscore delete mode 100644 openedx/core/djangoapps/video_pipeline/__init__.py delete mode 100644 openedx/core/djangoapps/video_pipeline/admin.py delete mode 100644 openedx/core/djangoapps/video_pipeline/api.py delete mode 100644 openedx/core/djangoapps/video_pipeline/migrations/0001_initial.py delete mode 100644 openedx/core/djangoapps/video_pipeline/migrations/__init__.py delete mode 100644 openedx/core/djangoapps/video_pipeline/models.py delete mode 100644 openedx/core/djangoapps/video_pipeline/tests/__init__.py delete mode 100644 openedx/core/djangoapps/video_pipeline/tests/mixins.py delete mode 100644 openedx/core/djangoapps/video_pipeline/tests/test_api.py delete mode 100644 openedx/core/djangoapps/video_pipeline/utils.py diff --git a/cms/djangoapps/contentstore/views/__init__.py b/cms/djangoapps/contentstore/views/__init__.py index 0242ac5723..ae2b317657 100644 --- a/cms/djangoapps/contentstore/views/__init__.py +++ b/cms/djangoapps/contentstore/views/__init__.py @@ -19,7 +19,6 @@ from .export_git import * from .user import * from .tabs import * from .videos import * -from .transcript_settings import * from .transcripts_ajax import * try: from .dev import * diff --git a/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py b/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py deleted file mode 100644 index 32eb1a0edb..0000000000 --- a/cms/djangoapps/contentstore/views/tests/test_transcript_settings.py +++ /dev/null @@ -1,171 +0,0 @@ -import ddt -import json -from mock import Mock, patch - -from django.test.testcases import TestCase - -from contentstore.tests.utils import CourseTestCase -from contentstore.utils import reverse_course_url -from contentstore.views.transcript_settings import TranscriptionProviderErrorType, validate_transcript_credentials - - -@ddt.ddt -@patch( - 'openedx.core.djangoapps.video_config.models.VideoTranscriptEnabledFlag.feature_enabled', - Mock(return_value=True) -) -class TranscriptCredentialsTest(CourseTestCase): - """ - Tests for transcript credentials handler. - """ - VIEW_NAME = 'transcript_credentials_handler' - - def get_url_for_course_key(self, course_id): - return reverse_course_url(self.VIEW_NAME, course_id) - - def test_302_with_anonymous_user(self): - """ - Verify that redirection happens in case of unauthorized request. - """ - self.client.logout() - transcript_credentials_url = self.get_url_for_course_key(self.course.id) - response = self.client.post(transcript_credentials_url, content_type='application/json') - self.assertEqual(response.status_code, 302) - - def test_405_with_not_allowed_request_method(self): - """ - Verify that 405 is returned in case of not-allowed request methods. - Allowed request methods include POST. - """ - transcript_credentials_url = self.get_url_for_course_key(self.course.id) - response = self.client.get(transcript_credentials_url, content_type='application/json') - self.assertEqual(response.status_code, 405) - - def test_404_with_feature_disabled(self): - """ - Verify that 404 is returned if the corresponding feature is disabled. - """ - transcript_credentials_url = self.get_url_for_course_key(self.course.id) - with patch('openedx.core.djangoapps.video_config.models.VideoTranscriptEnabledFlag.feature_enabled') as feature: - feature.return_value = False - response = self.client.post(transcript_credentials_url, content_type='application/json') - self.assertEqual(response.status_code, 404) - - @ddt.data( - ( - { - 'provider': 'abc_provider', - 'api_key': '1234' - }, - ({}, None), - 400, - '{\n "error": "Invalid Provider abc_provider."\n}' - ), - ( - { - 'provider': '3PlayMedia', - 'api_key': '11111', - 'api_secret_key': '44444' - }, - ({'error_type': TranscriptionProviderErrorType.INVALID_CREDENTIALS}, False), - 400, - '{\n "error": "The information you entered is incorrect."\n}' - ), - ( - { - 'provider': 'Cielo24', - 'api_key': '12345', - 'username': 'test_user' - }, - ({}, True), - 200, - '' - ) - ) - @ddt.unpack - @patch('contentstore.views.transcript_settings.update_3rd_party_transcription_service_credentials') - def test_transcript_credentials_handler(self, request_payload, update_credentials_response, expected_status_code, - expected_response, mock_update_credentials): - """ - Tests that transcript credentials handler works as expected. - """ - mock_update_credentials.return_value = update_credentials_response - transcript_credentials_url = self.get_url_for_course_key(self.course.id) - response = self.client.post( - transcript_credentials_url, - data=json.dumps(request_payload), - content_type='application/json' - ) - self.assertEqual(response.status_code, expected_status_code) - self.assertEqual(response.content, expected_response) - - -@ddt.ddt -class TranscriptCredentialsValidationTest(TestCase): - """ - Tests for credentials validations. - """ - - @ddt.data( - ( - 'ABC', - { - 'username': 'test_user', - 'password': 'test_pass' - }, - 'Invalid Provider ABC.', - {} - ), - ( - 'Cielo24', - { - 'username': 'test_user' - }, - 'api_key must be specified.', - {} - ), - ( - 'Cielo24', - { - 'username': 'test_user', - 'api_key': 'test_api_key', - 'extra_param': 'extra_value' - }, - '', - { - 'username': 'test_user', - 'api_key': 'test_api_key' - } - ), - ( - '3PlayMedia', - { - 'username': 'test_user' - }, - 'api_key and api_secret_key must be specified.', - {} - ), - ( - '3PlayMedia', - { - 'api_key': 'test_key', - 'api_secret_key': 'test_secret', - 'extra_param': 'extra_value' - }, - '', - { - 'api_key': 'test_key', - 'api_secret_key': 'test_secret' - } - ), - - ) - @ddt.unpack - def test_invalid_credentials(self, provider, credentials, expected_error_message, expected_validated_credentials): - """ - Test validation with invalid transcript credentials. - """ - error_message, validated_credentials = validate_transcript_credentials(provider, **credentials) - # Assert the results. - self.assertEqual(error_message, expected_error_message) - self.assertDictEqual(validated_credentials, expected_validated_credentials) diff --git a/cms/djangoapps/contentstore/views/transcript_settings.py b/cms/djangoapps/contentstore/views/transcript_settings.py deleted file mode 100644 index 86374d469d..0000000000 --- a/cms/djangoapps/contentstore/views/transcript_settings.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -Views related to the transcript preferences feature -""" -from django.contrib.auth.decorators import login_required -from django.http import HttpResponseNotFound -from django.utils.translation import ugettext as _ -from django.views.decorators.http import require_POST -from edxval.api import ( - get_3rd_party_transcription_plans, - update_transcript_credentials_state_for_org, -) -from opaque_keys.edx.keys import CourseKey - -from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag -from openedx.core.djangoapps.video_pipeline.api import update_3rd_party_transcription_service_credentials -from util.json_request import JsonResponse, expect_json - -from contentstore.views.videos import TranscriptProvider - -__all__ = ['transcript_credentials_handler'] - - -class TranscriptionProviderErrorType: - """ - Transcription provider's error types enumeration. - """ - INVALID_CREDENTIALS = 1 - - -def validate_transcript_credentials(provider, **credentials): - """ - Validates transcript credentials. - - Validations: - Providers must be either 3PlayMedia or Cielo24. - In case of: - 3PlayMedia - 'api_key' and 'api_secret_key' are required. - Cielo24 - 'api_key' and 'username' are required. - - It ignores any extra/unrelated parameters passed in credentials and - only returns the validated ones. - """ - error_message, validated_credentials = '', {} - valid_providers = get_3rd_party_transcription_plans().keys() - if provider in valid_providers: - must_have_props = [] - if provider == TranscriptProvider.THREE_PLAY_MEDIA: - must_have_props = ['api_key', 'api_secret_key'] - elif provider == TranscriptProvider.CIELO24: - must_have_props = ['api_key', 'username'] - - missing = [must_have_prop for must_have_prop in must_have_props if must_have_prop not in credentials.keys()] - if missing: - error_message = u'{missing} must be specified.'.format(missing=' and '.join(missing)) - return error_message, validated_credentials - - validated_credentials.update({ - prop: credentials[prop] for prop in must_have_props - }) - else: - error_message = u'Invalid Provider {provider}.'.format(provider=provider) - - return error_message, validated_credentials - - -@expect_json -@login_required -@require_POST -def transcript_credentials_handler(request, course_key_string): - """ - JSON view handler to update the transcript organization credentials. - - Arguments: - request: WSGI request object - course_key_string: A course identifier to extract the org. - - Returns: - - A 200 response if credentials are valid and successfully updated in edx-video-pipeline. - - A 404 response if transcript feature is not enabled for this course. - - A 400 if credentials do not pass validations, hence not updated in edx-video-pipeline. - """ - course_key = CourseKey.from_string(course_key_string) - if not VideoTranscriptEnabledFlag.feature_enabled(course_key): - return HttpResponseNotFound() - - provider = request.json.pop('provider') - error_message, validated_credentials = validate_transcript_credentials(provider=provider, **request.json) - if error_message: - response = JsonResponse({'error': error_message}, status=400) - else: - # Send the validated credentials to edx-video-pipeline. - credentials_payload = dict(validated_credentials, org=course_key.org, provider=provider) - error_response, is_updated = update_3rd_party_transcription_service_credentials(**credentials_payload) - # Send appropriate response based on whether credentials were updated or not. - if is_updated: - # Cache credentials state in edx-val. - update_transcript_credentials_state_for_org(org=course_key.org, provider=provider, exists=is_updated) - response = JsonResponse(status=200) - else: - # Error response would contain error types and the following - # error type is received from edx-video-pipeline whenever we've - # got invalid credentials for a provider. Its kept this way because - # edx-video-pipeline doesn't support i18n translations yet. - error_type = error_response.get('error_type') - if error_type == TranscriptionProviderErrorType.INVALID_CREDENTIALS: - error_message = _('The information you entered is incorrect.') - - response = JsonResponse({'error': error_message}, status=400) - - return response diff --git a/cms/djangoapps/contentstore/views/videos.py b/cms/djangoapps/contentstore/views/videos.py index 7df8135f60..c7ef4be093 100644 --- a/cms/djangoapps/contentstore/views/videos.py +++ b/cms/djangoapps/contentstore/views/videos.py @@ -1,10 +1,11 @@ """ Views related to the video upload feature """ +from contextlib import closing + import csv import json import logging -from contextlib import closing from datetime import datetime, timedelta from uuid import uuid4 @@ -17,38 +18,33 @@ from django.core.files.images import get_image_dimensions from django.http import HttpResponse, HttpResponseNotFound from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_noop -from django.views.decorators.http import require_GET, require_http_methods, require_POST +from django.views.decorators.http import require_GET, require_POST, require_http_methods from edxval.api import ( SortDirection, VideoSortField, - create_or_update_transcript_preferences, create_video, - get_3rd_party_transcription_plans, - get_transcript_credentials_state_for_org, - get_transcript_preferences, get_videos_for_course, - remove_transcript_preferences, remove_video_for_course, + update_video_status, update_video_image, - update_video_status + get_3rd_party_transcription_plans, + get_transcript_preferences, + create_or_update_transcript_preferences, + remove_transcript_preferences, ) from opaque_keys.edx.keys import CourseKey +from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag +from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace from contentstore.models import VideoUploadConfig from contentstore.utils import reverse_course_url from edxmako.shortcuts import render_to_response -from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag -from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace from util.json_request import JsonResponse, expect_json from .course import get_course_and_check_access -__all__ = [ - 'videos_handler', - 'video_encodings_download', - 'video_images_handler', - 'transcript_preferences_handler', -] + +__all__ = ['videos_handler', 'video_encodings_download', 'video_images_handler', 'transcript_preferences_handler'] LOGGER = logging.getLogger(__name__) @@ -593,8 +589,7 @@ def videos_index_html(course): }, 'is_video_transcript_enabled': is_video_transcript_enabled, 'video_transcript_settings': None, - 'active_transcript_preferences': None, - 'transcript_credentials': None + 'active_transcript_preferences': None } if is_video_transcript_enabled: @@ -603,15 +598,9 @@ def videos_index_html(course): 'transcript_preferences_handler', unicode(course.id) ), - 'transcript_credentials_handler_url': reverse_course_url( - 'transcript_credentials_handler', - unicode(course.id) - ), 'transcription_plans': get_3rd_party_transcription_plans(), } context['active_transcript_preferences'] = get_transcript_preferences(unicode(course.id)) - # Cached state for transcript providers' credentials (org-specific) - context['transcript_credentials'] = get_transcript_credentials_state_for_org(course.id.org) return render_to_response('videos_index.html', context) diff --git a/cms/envs/common.py b/cms/envs/common.py index f1572e34d0..4797aa1af6 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -947,9 +947,6 @@ INSTALLED_APPS = [ # Video module configs (This will be moved to Video once it becomes an XBlock) 'openedx.core.djangoapps.video_config', - # edX Video Pipeline integration - 'openedx.core.djangoapps.video_pipeline', - # For CMS 'contentstore.apps.ContentstoreConfig', diff --git a/cms/static/js/factories/videos_index.js b/cms/static/js/factories/videos_index.js index 1ad46cada1..abbc23b952 100644 --- a/cms/static/js/factories/videos_index.js +++ b/cms/static/js/factories/videos_index.js @@ -15,7 +15,6 @@ define([ videoSupportedFileFormats, videoUploadMaxFileSizeInGB, activeTranscriptPreferences, - transcriptOrganizationCredentials, videoTranscriptSettings, isVideoTranscriptEnabled, videoImageSettings @@ -28,7 +27,6 @@ define([ videoUploadMaxFileSizeInGB: videoUploadMaxFileSizeInGB, videoImageSettings: videoImageSettings, activeTranscriptPreferences: activeTranscriptPreferences, - transcriptOrganizationCredentials: transcriptOrganizationCredentials, videoTranscriptSettings: videoTranscriptSettings, isVideoTranscriptEnabled: isVideoTranscriptEnabled, onFileUploadDone: function(activeVideos) { diff --git a/cms/static/js/spec/views/active_video_upload_list_spec.js b/cms/static/js/spec/views/active_video_upload_list_spec.js index 920100766f..80fe73b87a 100644 --- a/cms/static/js/spec/views/active_video_upload_list_spec.js +++ b/cms/static/js/spec/views/active_video_upload_list_spec.js @@ -43,7 +43,7 @@ define( activeTranscriptPreferences: {}, videoTranscriptSettings: { transcript_preferences_handler_url: '', - transcription_plans: null + transcription_plans: {} }, isVideoTranscriptEnabled: isVideoTranscriptEnabled }); diff --git a/cms/static/js/spec/views/course_video_settings_spec.js b/cms/static/js/spec/views/course_video_settings_spec.js index be7575ee33..6035e0b966 100644 --- a/cms/static/js/spec/views/course_video_settings_spec.js +++ b/cms/static/js/spec/views/course_video_settings_spec.js @@ -8,23 +8,10 @@ define( courseVideoSettingsView, renderCourseVideoSettingsView, destroyCourseVideoSettingsView, - verifyTranscriptPreferences, - verifyTranscriptPreferencesView, - verifyOrganizationCredentialsView, - verifyCredentialFieldsPresent, - verifyOrganizationCredentialField, - verifyMessage, verifyPreferanceErrorState, selectPreference, - verifyProviderList, - verifyProviderSelectedView, - verifyCredentialsSaved, - resetProvider, - changeProvider, - submitOrganizationCredentials, + chooseProvider, transcriptPreferencesUrl = '/transcript_preferences/course-v1:edX+DemoX+Demo_Course', - transcriptCredentialsHandlerUrl = '/transcript_credentials/course-v1:edX+DemoX+Demo_Course', - INTERNAL_SERVER_ERROR = 'An error has occurred. Wait a few minutes, and then try again.', activeTranscriptPreferences = { provider: 'Cielo24', cielo24_fidelity: 'PROFESSIONAL', @@ -34,10 +21,6 @@ define( preferred_languages: ['fr', 'en'], modified: '2017-08-27T12:28:17.421260Z' }, - transcriptOrganizationCredentials = { - Cielo24: true, - '3PlayMedia': true - }, transcriptionPlans = { '3PlayMedia': { languages: { @@ -89,37 +72,15 @@ define( }, display_name: 'Cielo24' } - }, - providers = { - none: { - key: 'none', - value: '', - displayName: 'None' - }, - Cielo24: { - key: 'Cielo24', - value: 'Cielo24', - displayName: 'Cielo24' - }, - '3PlayMedia': { - key: '3PlayMedia', - value: '3PlayMedia', - displayName: '3Play Media' - } }; - renderCourseVideoSettingsView = function(activeTranscriptPreferencesData, transcriptionPlansData, transcriptOrganizationCredentialsData) { // eslint-disable-line max-len - // First destroy old referance to the view if present. - destroyCourseVideoSettingsView(); - + renderCourseVideoSettingsView = function(activeTranscriptPreferencesData, transcriptionPlansData) { courseVideoSettingsView = new CourseVideoSettingsView({ activeTranscriptPreferences: activeTranscriptPreferencesData || null, videoTranscriptSettings: { transcript_preferences_handler_url: transcriptPreferencesUrl, - transcript_credentials_handler_url: transcriptCredentialsHandlerUrl, transcription_plans: transcriptionPlansData || null - }, - transcriptOrganizationCredentials: transcriptOrganizationCredentialsData || null + } }); $courseVideoSettingsEl = courseVideoSettingsView.render().$el; }; @@ -147,167 +108,10 @@ define( $preference.change(); }; - verifyMessage = function(state, message) { - var icon = state === 'error' ? 'fa-info-circle' : 'fa-check-circle'; - expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.' + state).html()).toEqual( - '
' + - '' + - '' + message + '' + - '
' - ); - }; - - verifyProviderList = function(selectedProvider) { - var $transcriptProvidersListEl = $courseVideoSettingsEl.find('.transcript-provider-wrapper .transcript-provider-group'); // eslint-disable-line max-len - // Check None provider is selected. - expect($transcriptProvidersListEl.find('input[type=radio]:checked').val()).toEqual(selectedProvider.value); // eslint-disable-line max-len - _.each(providers, function(provider, key) { - $transcriptProvidersListEl.find('label[for=transcript-provider-' + key + ']').val(provider.displayName); // eslint-disable-line max-len - }); - }; - - verifyTranscriptPreferences = function() { - expect($courseVideoSettingsEl.find('#transcript-turnaround').val()).toEqual( - activeTranscriptPreferences.cielo24_turnaround - ); - expect($courseVideoSettingsEl.find('#transcript-fidelity').val()).toEqual( - activeTranscriptPreferences.cielo24_fidelity - ); - expect($courseVideoSettingsEl.find('.transcript-language-container').length).toEqual( - activeTranscriptPreferences.preferred_languages.length - ); - // Now check values are assigned correctly. - expect(courseVideoSettingsView.selectedTurnaroundPlan, activeTranscriptPreferences.cielo24_turnaround); - expect(courseVideoSettingsView.selectedFidelityPlan, activeTranscriptPreferences.cielo24_fidelity); - expect(courseVideoSettingsView.selectedLanguages, activeTranscriptPreferences.preferred_languages); - }; - - verifyProviderSelectedView = function() { - // Verify provider - expect( - $courseVideoSettingsEl.find('.selected-transcript-provider .title').html() - ).toEqual(courseVideoSettingsView.selectedProvider); - - expect($courseVideoSettingsEl.find('.selected-transcript-provider .action-change-provider')).toExist(); - expect( - $courseVideoSettingsEl.find('.selected-transcript-provider .action-change-provider .sr').html() - ).toEqual('Press change to change selected transcript provider.'); - }; - - verifyTranscriptPreferencesView = function() { - expect($courseVideoSettingsEl.find('.course-video-transcript-preferances-wrapper')).toExist(); - }; - - verifyOrganizationCredentialsView = function() { - expect($courseVideoSettingsEl.find('.organization-credentials-content')).toExist(); - }; - - verifyCredentialFieldsPresent = function(fields) { - // Verify correct number of input fields are shown. - expect( - $courseVideoSettingsEl.find( - '.organization-credentials-wrapper .transcript-preferance-wrapper input' - ).length - ).toEqual(_.keys(fields).length - ); - - // Verify individual field has correct label and key. - _.each(fields, function(label, fieldName) { - verifyOrganizationCredentialField(fieldName, label); - }); - }; - - verifyOrganizationCredentialField = function(fieldName, label) { - var elementSelector = courseVideoSettingsView.selectedProvider + '-' + fieldName; - // Verify that correct label is shown. - expect( - $courseVideoSettingsEl.find('.' + elementSelector + '-wrapper label .title').html() - ).toEqual(label); - - // Verify that credential field is shown. - expect( - $courseVideoSettingsEl.find('.' + elementSelector + '-wrapper .' + elementSelector) - ).toExist(); - }; - - verifyCredentialsSaved = function() { - // Verify that success message is shown. - verifyMessage( - 'success', - transcriptionPlans[courseVideoSettingsView.selectedProvider].display_name + ' credentials saved' - ); - - // Also verify that transcript credential state is updated. - expect( - courseVideoSettingsView.transcriptOrganizationCredentials[courseVideoSettingsView.selectedProvider] - ).toBeTruthy(); - - // Verify that selected provider view after credentials are saved. - verifyProviderSelectedView(); - }; - - changeProvider = function(selectedProvider) { - // If Provider Selected view is show, first click on "Change Provider" button to - // show all list of providers. - if ($courseVideoSettingsEl.find('.selected-transcript-provider').length) { - $courseVideoSettingsEl.find('.selected-transcript-provider .action-change-provider').click(); - } + chooseProvider = function(selectedProvider) { $courseVideoSettingsEl.find('#transcript-provider-' + selectedProvider).click(); }; - resetProvider = function() { - var requests = AjaxHelpers.requests(this); - // Set no provider selected - changeProvider('none'); - $courseVideoSettingsEl.find('.action-update-course-video-settings').click(); - - AjaxHelpers.expectRequest( - requests, - 'DELETE', - transcriptPreferencesUrl - ); - - // Send successful empty content response. - AjaxHelpers.respondWithJson(requests, {}); - }; - - submitOrganizationCredentials = function(fieldValues, statusCode, errorMessage) { - var requests = AjaxHelpers.requests(this); - // Click change button to render organization credentials view. - $courseVideoSettingsEl.find('.action-change-provider').click(); - - // Provide organization credentials. - _.each(fieldValues, function(key) { - $courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-' + key).val(key); - }); - // Click save organization credentials button to save credentials. - $courseVideoSettingsEl.find('.action-update-org-credentials').click(); - - AjaxHelpers.expectRequest( - requests, - 'POST', - transcriptCredentialsHandlerUrl, - JSON.stringify( - _.extend( - {provider: courseVideoSettingsView.selectedProvider}, - fieldValues, - {global: false} - ) - ) - ); - - if (statusCode === 400) { - // Send bad request error response. - AjaxHelpers.respondWithError(requests, statusCode, {error: errorMessage}); - } else if (statusCode === 500) { - // Send internal server error response. - AjaxHelpers.respondWithError(requests, statusCode); - } else { - // Send empty response. - AjaxHelpers.respondWithJson(requests, {}); - } - }; - beforeEach(function() { setFixtures( '
' + @@ -344,10 +148,17 @@ define( }); it('does not populate transcription plans if transcription plans are not provided', function() { + // First detroy old referance to the view. + destroyCourseVideoSettingsView(); + // Create view with empty data. - renderCourseVideoSettingsView(); - // Checking turnaround is sufficient to check preferences are are shown or not. - expect($courseVideoSettingsEl.find('.transcript-turnaround-wrapper')).not.toExist(); + renderCourseVideoSettingsView(null, null); + + expect($courseVideoSettingsEl.find('.transcript-provider-group').html()).toEqual(''); + expect($courseVideoSettingsEl.find('.transcript-turnaround').html()).toEqual(''); + expect($courseVideoSettingsEl.find('.transcript-fidelity').html()).toEqual(''); + expect($courseVideoSettingsEl.find('.video-source-language').html()).toEqual(''); + expect($courseVideoSettingsEl.find('.transcript-language-menu').html()).toEqual(''); }); it('populates transcription plans correctly', function() { @@ -358,51 +169,39 @@ define( it('populates active preferances correctly', function() { // First check preferance are selected correctly in HTML. - verifyTranscriptPreferences(); - }); - - it('resets to active preferences when clicked on cancel', function() { - var selectedProvider = '3PlayMedia'; - - renderCourseVideoSettingsView( - activeTranscriptPreferences, - transcriptionPlans, - transcriptOrganizationCredentials + expect($courseVideoSettingsEl.find('.transcript-provider-group input:checked').val()).toEqual( + activeTranscriptPreferences.provider + ); + expect($courseVideoSettingsEl.find('.transcript-turnaround').val()).toEqual( + activeTranscriptPreferences.cielo24_turnaround + ); + expect($courseVideoSettingsEl.find('.transcript-fidelity').val()).toEqual( + activeTranscriptPreferences.cielo24_fidelity + ); + expect($courseVideoSettingsEl.find('.video-source-language').val()).toEqual( + activeTranscriptPreferences.video_source_language + ); + expect($courseVideoSettingsEl.find('.transcript-language-container').length).toEqual( + activeTranscriptPreferences.preferred_languages.length ); - // First check preferance are selected correctly in HTML. - verifyTranscriptPreferences(); - expect(courseVideoSettingsView.selectedProvider, providers.Cielo24); - - // Now change preferences. - // Select provider. - changeProvider(selectedProvider); - expect(courseVideoSettingsView.selectedProvider, selectedProvider); - - // Select turnaround. - selectPreference( - '.transcript-turnaround', - transcriptionPlans[selectedProvider].turnaround.default - ); + // Now check values are assigned correctly. + expect(courseVideoSettingsView.selectedProvider, activeTranscriptPreferences.provider); + expect(courseVideoSettingsView.selectedTurnaroundPlan, activeTranscriptPreferences.cielo24_turnaround); + expect(courseVideoSettingsView.selectedFidelityPlan, activeTranscriptPreferences.cielo24_fidelity); expect( - courseVideoSettingsView.selectedTurnaroundPlan, - transcriptionPlans[selectedProvider].turnaround.default + courseVideoSettingsView.selectedSourceLanguage, + activeTranscriptPreferences.video_source_language ); - - // Now click cancel button and verify active preferences are shown. - $courseVideoSettingsEl.find('.action-cancel-course-video-settings').click(); - verifyTranscriptPreferences(); - expect(courseVideoSettingsView.selectedProvider, providers.Cielo24); + expect(courseVideoSettingsView.selectedLanguages, activeTranscriptPreferences.preferred_languages); }); it('shows video source language directly in case of 3Play provider', function() { var sourceLanguages, selectedProvider = '3PlayMedia'; - renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials); - - // Select provider - changeProvider(selectedProvider); + // Select CIELIO24 provider + chooseProvider(selectedProvider); expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider); // Verify source langauges menu is shown. @@ -420,10 +219,10 @@ define( selectedProvider = 'Cielo24', selectedFidelity = 'PROFESSIONAL'; - renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials); + renderCourseVideoSettingsView(null, transcriptionPlans); - // Select provider - changeProvider(selectedProvider); + // Select CIELIO24 provider + chooseProvider(selectedProvider); expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider); // Verify source language is not shown. @@ -455,10 +254,8 @@ define( selectedProvider = 'Cielo24', selectedFidelity = 'PROFESSIONAL'; - renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials); - - // Select provider - changeProvider(selectedProvider); + // Select CIELIO24 provider + chooseProvider(selectedProvider); expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider); // Select fidelity @@ -486,10 +283,8 @@ define( selectedProvider = 'Cielo24', selectedFidelity = 'MECHANICAL'; - renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials); - - // Select provider - changeProvider(selectedProvider); + // Select CIELIO24 provider + chooseProvider(selectedProvider); expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider); // Select fidelity @@ -537,16 +332,37 @@ define( }); // Verify that success message is shown. - verifyMessage('success', 'Settings updated'); + expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.success').html()).toEqual( + '
' + + '' + + 'Settings updated' + + '
' + ); }); it('removes transcript settings on update settings button click when no provider is selected', function() { - // Reset to None provider - resetProvider(); - verifyProviderList(providers.none); + var requests = AjaxHelpers.requests(this); + + // Set no provider selected + courseVideoSettingsView.selectedProvider = null; + $courseVideoSettingsEl.find('.action-update-course-video-settings').click(); + + AjaxHelpers.expectRequest( + requests, + 'DELETE', + transcriptPreferencesUrl + ); + + // Send successful empty content response. + AjaxHelpers.respondWithJson(requests, {}); // Verify that success message is shown. - verifyMessage('success', 'Automatic transcripts are disabled.'); + expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.success').html()).toEqual( + '
' + + '' + + 'Settings updated' + + '
' + ); }); it('shows error message if server sends error', function() { @@ -574,7 +390,12 @@ define( }); // Verify that error message is shown. - verifyMessage('error', 'Error message'); + expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.error').html()).toEqual( + '
' + + '' + + 'Error message' + + '
' + ); }); it('implies preferences are required if not selected when saving preferances', function() { @@ -602,203 +423,8 @@ define( verifyPreferanceErrorState($courseVideoSettingsEl.find('.transcript-languages-wrapper'), false); }); - it('shows provider selected view if active provider is present', function() { - var $selectedProviderContainerEl = $courseVideoSettingsEl.find('.transcript-provider-wrapper .selected-transcript-provider'); // eslint-disable-line max-len - expect($selectedProviderContainerEl.find('span').html()).toEqual(courseVideoSettingsView.selectedProvider); // eslint-disable-line max-len - expect($selectedProviderContainerEl.find('button.action-change-provider')).toExist(); - // Verify provider list view is not shown. - expect($courseVideoSettingsEl.find('.transcript-provider-wrapper .transcript-provider-group')).not.toExist(); // eslint-disable-line max-len - }); - - it('does not show transcript preferences or organization credentials if None provider is saved', function() { // eslint-disable-line max-len - renderCourseVideoSettingsView(null, transcriptionPlans); - - // Check None provider - resetProvider(); - verifyProviderList(providers.none); - - // Verify selected provider view is not shown. - expect($courseVideoSettingsEl.find('.transcript-provider-wrapper .selected-transcript-provider')).not.toExist(); // eslint-disable-line max-len - }); - - it('does not show transcript preferences or organization credentials if None provider is checked', function() { // eslint-disable-line max-len - renderCourseVideoSettingsView(null, transcriptionPlans); - - // Check None provider - resetProvider(); - verifyProviderList(providers.none); - - // Verify selected provider view is not shown. - expect($courseVideoSettingsEl.find('.transcript-provider-wrapper .selected-transcript-provider')).not.toExist(); // eslint-disable-line max-len - // Verify transcript preferences are not shown. - expect($courseVideoSettingsEl.find('.course-video-transcript-preferances-wrapper')).not.toExist(); - // Verify org credentials are not shown. - expect($courseVideoSettingsEl.find('.organization-credentials-content')).not.toExist(); - }); - - it('shows organization credentials when organization credentials for selected provider are not present', function() { // eslint-disable-line max-len - renderCourseVideoSettingsView(null, transcriptionPlans); - - // Check Cielo24 provider - changeProvider(providers.Cielo24.key); - verifyProviderList(providers.Cielo24); - - // Verify organization credentials are shown. - verifyOrganizationCredentialsView(); - - // Verify transcript preferences are not shown. - expect($courseVideoSettingsEl.find('.course-video-transcript-preferances-wrapper')).not.toExist(); - }); - - it('shows transcript preferences when organization credentials for selected provider are present', function() { // eslint-disable-line max-len - renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials); - - // Check Cielo24 provider - changeProvider('Cielo24'); - verifyProviderList(providers.Cielo24); - - // Verify organization credentials are not shown. - expect($courseVideoSettingsEl.find('.organization-credentials-content')).not.toExist(); - - // Verify transcript preferences are shown. - verifyTranscriptPreferencesView(); - }); - - it('shows organization credentials view if clicked on change provider button', function() { - // Verify organization credentials view is not shown initially. - expect($courseVideoSettingsEl.find('.organization-credentials-content')).not.toExist(); - - verifyProviderSelectedView(); - // Click change button to render organization credentials view. - $courseVideoSettingsEl.find('.action-change-provider').click(); - - // Verify organization credentials is now shown. - verifyOrganizationCredentialsView(); - }); - - it('shows cielo specific organization credentials fields only', function() { - verifyProviderSelectedView(); - // Click change button to render organization credentials view. - $courseVideoSettingsEl.find('.action-change-provider').click(); - - // Verify api key is present. - verifyCredentialFieldsPresent({ - 'api-key': 'API Key', - username: 'Username' - }); - }); - - it('shows 3play specific organization credentials fields only', function() { - // Set selected provider to 3Play Media - changeProvider('3PlayMedia'); - - // Verify api key and api secret input fields are present. - verifyCredentialFieldsPresent({ - 'api-key': 'API Key', - 'api-secret': 'API Secret' - }); - }); - - it('shows warning message when changing organization credentials if present already', function() { - // Set selectedProvider organization credentials. - courseVideoSettingsView.transcriptOrganizationCredentials[courseVideoSettingsView.selectedProvider] = true; // eslint-disable-line max-len - - verifyProviderSelectedView(); - // Click change button to render organization credentials view. - $courseVideoSettingsEl.find('.action-change-provider').click(); - - // Verify credentials are shown - verifyOrganizationCredentialsView(); - // Verify warning message is shown. - expect($courseVideoSettingsEl.find('.transcription-account-details.warning')).toExist(); - // Verify message - expect($courseVideoSettingsEl.find('.transcription-account-details').html()).toEqual( - 'This action updates the ' + courseVideoSettingsView.selectedProvider + - ' information for your entire organization.' - ); - }); - - it('does not show warning message when changing organization credentials if not present already', function() { // eslint-disable-line max-len - verifyProviderSelectedView(); - // Click change button to render organization credentials view. - $courseVideoSettingsEl.find('.action-change-provider').click(); - - // Verify warning message is not shown. - expect($courseVideoSettingsEl.find('.transcription-account-details.warning')).not.toExist(); - // Initial detail message is shown instead. - expect($courseVideoSettingsEl.find('.transcription-account-details').html()).toEqual( - 'Enter the account information for your organization.' - ); - }); - - it('shows validation errors if no organization credentials are provided when saving credentials', function() { // eslint-disable-line max-len - // Set selected provider to 3Play Media - changeProvider('3PlayMedia'); - - // Click save organization credentials button to save credentials. - $courseVideoSettingsEl.find('.action-update-org-credentials').click(); - - verifyPreferanceErrorState( - $courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-key-wrapper'), - true - ); - - verifyPreferanceErrorState( - $courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-secret-wrapper'), - true - ); - }); - - it('saves cielo organization credentials on clicking save credentials button', function() { - verifyProviderSelectedView(); - submitOrganizationCredentials({ - api_key: 'api-key', - username: 'username' - }); - - verifyCredentialsSaved(); - }); - - it('saves 3Play organization credentials on clicking save credentials button', function() { - verifyProviderSelectedView(); - - // Set selected provider to 3Play Media - changeProvider('3PlayMedia'); - - submitOrganizationCredentials({ - api_key: 'api-key', - api_secret_key: 'api-secret' - }); - - verifyCredentialsSaved(); - }); - - it('shows error message on saving organization credentials if server sends bad request error', function() { - verifyProviderSelectedView(); - - submitOrganizationCredentials({ - api_key: 'api-key', - username: 'username' - }, 400, 'Error saving credentials.'); - - // Verify that bad request error message is shown. - verifyMessage('error', 'Error saving credentials.'); - }); - - it('shows error message on saving organization credentials if server sends error', function() { - verifyProviderSelectedView(); - - submitOrganizationCredentials({ - api_key: 'api-key', - username: 'username' - }, 500); - - // Verify that server error message is shown. - verifyMessage('error', INTERNAL_SERVER_ERROR); - }); - // TODO: Add more tests like clicking on add language, remove and their scenarios and some other tests - // for specific preferance selected tests etc. - See EDUCATOR-1478 + // like N/A selected, specific provider selected tests, specific preferance selected tests etc. }); } ); diff --git a/cms/static/js/views/active_video_upload_list.js b/cms/static/js/views/active_video_upload_list.js index 6b0d067927..88afe648dc 100644 --- a/cms/static/js/views/active_video_upload_list.js +++ b/cms/static/js/views/active_video_upload_list.js @@ -42,7 +42,6 @@ define([ this.concurrentUploadLimit = options.concurrentUploadLimit || 0; this.postUrl = options.postUrl; this.activeTranscriptPreferences = options.activeTranscriptPreferences; - this.transcriptOrganizationCredentials = options.transcriptOrganizationCredentials; this.videoTranscriptSettings = options.videoTranscriptSettings; this.isVideoTranscriptEnabled = options.isVideoTranscriptEnabled; this.videoSupportedFileFormats = options.videoSupportedFileFormats; @@ -86,7 +85,6 @@ define([ if (this.isVideoTranscriptEnabled) { this.courseVideoSettingsView = new CourseVideoSettingsView({ activeTranscriptPreferences: this.activeTranscriptPreferences, - transcriptOrganizationCredentials: this.transcriptOrganizationCredentials, videoTranscriptSettings: this.videoTranscriptSettings }); this.courseVideoSettingsView.render(); diff --git a/cms/static/js/views/course_video_settings.js b/cms/static/js/views/course_video_settings.js index 2126c92717..bbaa675af5 100644 --- a/cms/static/js/views/course_video_settings.js +++ b/cms/static/js/views/course_video_settings.js @@ -3,26 +3,16 @@ */ define([ 'jquery', 'backbone', 'underscore', 'gettext', 'moment', - 'common/js/components/utils/view_utils', 'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/string-utils', - 'text!templates/course-video-settings.underscore', - 'text!templates/course-video-transcript-preferences.underscore', - 'text!templates/course-video-transcript-provider-empty.underscore', - 'text!templates/course-video-transcript-provider-selected.underscore', - 'text!templates/transcript-organization-credentials.underscore', - 'text!templates/course-video-settings-update-settings-footer.underscore', - 'text!templates/course-video-settings-update-org-credentials-footer.underscore' + 'text!templates/course-video-settings.underscore' ], -function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, TranscriptSettingsTemplate, - TranscriptPreferencesTemplate, TranscriptProviderEmptyStateTemplate, TranscriptProviderSelectedStateTemplate, - OrganizationCredentialsTemplate, UpdateSettingsFooterTemplate, OrganizationCredentialsFooterTemplate) { +function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSettingsTemplate) { 'use strict'; var CourseVideoSettingsView, CIELO24 = 'Cielo24', - THREE_PLAY_MEDIA = '3PlayMedia', - INTERNAL_SERVER_ERROR_MESSAGE = gettext('An error has occurred. Wait a few minutes, and then try again.'); + THREE_PLAY_MEDIA = '3PlayMedia'; CourseVideoSettingsView = Backbone.View.extend({ el: 'div.video-transcript-settings-wrapper', @@ -34,27 +24,16 @@ function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, Tra 'change #video-source-language': 'videoSourceLanguageSelected', 'click .action-add-language': 'languageSelected', 'click .action-remove-language': 'languageRemoved', - 'click .action-change-provider': 'renderOrganizationCredentials', - 'click .action-update-org-credentials': 'updateOrganizationCredentials', 'click .action-update-course-video-settings': 'updateCourseVideoSettings', - 'click .action-cancel-course-video-settings': 'discardChanges', 'click .action-close-course-video-settings': 'closeCourseVideoSettings' }, initialize: function(options) { var videoTranscriptSettings = options.videoTranscriptSettings; this.activeTranscriptionPlan = options.activeTranscriptPreferences; - this.transcriptOrganizationCredentials = _.extend({}, options.transcriptOrganizationCredentials); this.availableTranscriptionPlans = videoTranscriptSettings.transcription_plans; this.transcriptHandlerUrl = videoTranscriptSettings.transcript_preferences_handler_url; - this.transcriptCredentialsHandlerUrl = videoTranscriptSettings.transcript_credentials_handler_url; this.template = HtmlUtils.template(TranscriptSettingsTemplate); - this.transcriptPreferencesTemplate = HtmlUtils.template(TranscriptPreferencesTemplate); - this.organizationCredentialsTemplate = HtmlUtils.template(OrganizationCredentialsTemplate); - this.organizationCredentialsFooterTemplate = HtmlUtils.template(OrganizationCredentialsFooterTemplate); - this.updateSettingsFooterTemplate = HtmlUtils.template(UpdateSettingsFooterTemplate); - this.transcriptProviderEmptyStateTemplate = HtmlUtils.template(TranscriptProviderEmptyStateTemplate); - this.transcriptProviderSelectedStateTemplate = HtmlUtils.template(TranscriptProviderSelectedStateTemplate); this.setActiveTranscriptPlanData(); this.selectedLanguages = []; }, @@ -70,7 +49,7 @@ function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, Tra // Click anywhere outside the course video settings pane would close the pane. $(document).click(function(event) { - // If the target of the click isn't the container nor a descendant of the contain + // if the target of the click isn't the container nor a descendant of the contain if (!self.$el.is(event.target) && self.$el.has(event.target).length === 0) { self.closeCourseVideoSettings(); } @@ -181,35 +160,7 @@ function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, Tra providerSelected: function(event) { this.resetPlanData(); this.selectedProvider = event.target.value; - // Re-render view - this.reRenderView(); - }, - - reRenderView: function() { - var $courseVideoSettingsContentEl = this.$el.find('.course-video-settings-content'), - dateModified = this.activeTranscriptionPlan ? - moment.utc(this.activeTranscriptionPlan.modified).format('ll') : ''; - - if (!this.selectedProvider) { - // Hide organization credentials and transcript preferences views - $courseVideoSettingsContentEl.hide(); - - // Render footer - HtmlUtils.setHtml( - this.$el.find('.course-video-settings-footer'), - this.updateSettingsFooterTemplate({ - dateModified: dateModified - }) - ); - return; - } - $courseVideoSettingsContentEl.show(); - // If org provider specific credentials are present - if (this.transcriptOrganizationCredentials[this.selectedProvider]) { - this.renderTranscriptPreferences(); - } else { - this.renderOrganizationCredentials(); - } + this.renderPreferences(); }, languageSelected: function(event) { @@ -236,56 +187,43 @@ function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, Tra $(event.target.parentElement).parent().remove(); // Remove language from selected languages. - this.selectedLanguages = this.activeLanguages = _.without(this.selectedLanguages, selectedLanguage); + this.selectedLanguages = _.without(this.selectedLanguages, selectedLanguage); // Populate menu again to reflect latest changes. this.populateLanguageMenu(); }, - renderProviders: function(state) { - var $transcriptProviderWrapperEl = this.$el.find('.transcript-provider-wrapper'); - if (!state) { - state = this.selectedProvider ? 'selected' : 'empty'; // eslint-disable-line no-param-reassign - } + renderProviders: function() { + var self = this, + providerPlan = self.availableTranscriptionPlans, + $providerEl = self.$el.find('.transcript-provider-group'); - // If no transcription plans are sentm return. - if (!this.availableTranscriptionPlans) { - return; - } - if (state === 'empty') { + if (providerPlan) { HtmlUtils.setHtml( - $transcriptProviderWrapperEl, - this.transcriptProviderEmptyStateTemplate({ - providers: [ + $providerEl, + HtmlUtils.interpolateHtml( + HtmlUtils.HTML(''), // eslint-disable-line max-len + { + text: gettext('N/A'), + checked: self.selectedProvider === '' ? 'checked' : '' + } + ) + ); + + _.each(providerPlan, function(providerObject, key) { + var checked = self.selectedProvider === key ? 'checked' : ''; + HtmlUtils.append( + $providerEl, + HtmlUtils.interpolateHtml( + HtmlUtils.HTML('