Transcript organization credentials UI - EDUCATOR-1126
This commit is contained in:
@@ -31,6 +31,8 @@ from edxval.api import (
|
||||
get_transcript_preferences,
|
||||
create_or_update_transcript_preferences,
|
||||
remove_transcript_preferences,
|
||||
get_transcript_credentials_state_for_org,
|
||||
update_transcript_credentials_state_for_org,
|
||||
)
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from openedx.core.djangoapps.video_config.models import VideoTranscriptEnabledFlag
|
||||
@@ -44,7 +46,13 @@ 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',
|
||||
'transcript_credentials_handler'
|
||||
]
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -380,6 +388,32 @@ def transcript_preferences_handler(request, course_key_string):
|
||||
return JsonResponse()
|
||||
|
||||
|
||||
@expect_json
|
||||
@login_required
|
||||
@require_POST
|
||||
def transcript_credentials_handler(request, course_key_string):
|
||||
"""
|
||||
JSON view handler to post the transcript organization credentials.
|
||||
|
||||
Arguments:
|
||||
request: WSGI request object
|
||||
course_key_string: string for course key
|
||||
|
||||
Returns: An empty success response or 404 if transcript feature is not enabled
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_key_string)
|
||||
if not VideoTranscriptEnabledFlag.feature_enabled(course_key):
|
||||
return HttpResponseNotFound()
|
||||
|
||||
org = course_key.org
|
||||
provider = request.json.get('provider')
|
||||
|
||||
# TODO: Send organization credentials to edx-pipeline end point.
|
||||
credentials = update_transcript_credentials_state_for_org(org, provider, exists=True)
|
||||
|
||||
return JsonResponse()
|
||||
|
||||
|
||||
@login_required
|
||||
@require_GET
|
||||
def video_encodings_download(request, course_key_string):
|
||||
@@ -589,7 +623,8 @@ def videos_index_html(course):
|
||||
},
|
||||
'is_video_transcript_enabled': is_video_transcript_enabled,
|
||||
'video_transcript_settings': None,
|
||||
'active_transcript_preferences': None
|
||||
'active_transcript_preferences': None,
|
||||
'transcript_credentials': None
|
||||
}
|
||||
|
||||
if is_video_transcript_enabled:
|
||||
@@ -598,9 +633,15 @@ 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)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ define([
|
||||
videoSupportedFileFormats,
|
||||
videoUploadMaxFileSizeInGB,
|
||||
activeTranscriptPreferences,
|
||||
transcriptOrganizationCredentials,
|
||||
videoTranscriptSettings,
|
||||
isVideoTranscriptEnabled,
|
||||
videoImageSettings
|
||||
@@ -27,6 +28,7 @@ define([
|
||||
videoUploadMaxFileSizeInGB: videoUploadMaxFileSizeInGB,
|
||||
videoImageSettings: videoImageSettings,
|
||||
activeTranscriptPreferences: activeTranscriptPreferences,
|
||||
transcriptOrganizationCredentials: transcriptOrganizationCredentials,
|
||||
videoTranscriptSettings: videoTranscriptSettings,
|
||||
isVideoTranscriptEnabled: isVideoTranscriptEnabled,
|
||||
onFileUploadDone: function(activeVideos) {
|
||||
|
||||
@@ -43,7 +43,7 @@ define(
|
||||
activeTranscriptPreferences: {},
|
||||
videoTranscriptSettings: {
|
||||
transcript_preferences_handler_url: '',
|
||||
transcription_plans: {}
|
||||
transcription_plans: null
|
||||
},
|
||||
isVideoTranscriptEnabled: isVideoTranscriptEnabled
|
||||
});
|
||||
|
||||
@@ -8,10 +8,19 @@ define(
|
||||
courseVideoSettingsView,
|
||||
renderCourseVideoSettingsView,
|
||||
destroyCourseVideoSettingsView,
|
||||
verifyTranscriptPreferences,
|
||||
verifyTranscriptPreferencesView,
|
||||
verifyOrganizationCredentialsView,
|
||||
verifyOrganizationCredentialField,
|
||||
verifyMessage,
|
||||
verifyPreferanceErrorState,
|
||||
selectPreference,
|
||||
chooseProvider,
|
||||
verifyProviderList,
|
||||
verifyProviderSelectedView,
|
||||
resetProvider,
|
||||
changeProvider,
|
||||
transcriptPreferencesUrl = '/transcript_preferences/course-v1:edX+DemoX+Demo_Course',
|
||||
transcriptCredentialsHandlerUrl = '/transcript_credentials/course-v1:edX+DemoX+Demo_Course',
|
||||
activeTranscriptPreferences = {
|
||||
provider: 'Cielo24',
|
||||
cielo24_fidelity: 'PROFESSIONAL',
|
||||
@@ -21,6 +30,10 @@ define(
|
||||
preferred_languages: ['fr', 'en'],
|
||||
modified: '2017-08-27T12:28:17.421260Z'
|
||||
},
|
||||
transcriptOrganizationCredentials = {
|
||||
Cielo24: true,
|
||||
'3PlayMedia': true
|
||||
},
|
||||
transcriptionPlans = {
|
||||
'3PlayMedia': {
|
||||
languages: {
|
||||
@@ -72,15 +85,37 @@ define(
|
||||
},
|
||||
display_name: 'Cielo24'
|
||||
}
|
||||
},
|
||||
providers = {
|
||||
none: {
|
||||
key: 'none',
|
||||
value: '',
|
||||
displayName: 'N/A'
|
||||
},
|
||||
Cielo24: {
|
||||
key: 'Cielo24',
|
||||
value: 'Cielo24',
|
||||
displayName: 'Cielo24'
|
||||
},
|
||||
'3PlayMedia': {
|
||||
key: '3PlayMedia',
|
||||
value: '3PlayMedia',
|
||||
displayName: '3Play Media'
|
||||
}
|
||||
};
|
||||
|
||||
renderCourseVideoSettingsView = function(activeTranscriptPreferencesData, transcriptionPlansData) {
|
||||
renderCourseVideoSettingsView = function(activeTranscriptPreferencesData, transcriptionPlansData, transcriptOrganizationCredentialsData) { // eslint-disable-line max-len
|
||||
// First destroy old referance to the view if present.
|
||||
destroyCourseVideoSettingsView();
|
||||
|
||||
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;
|
||||
};
|
||||
@@ -108,10 +143,99 @@ define(
|
||||
$preference.change();
|
||||
};
|
||||
|
||||
chooseProvider = function(selectedProvider) {
|
||||
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(
|
||||
'<div class="course-video-settings-message">' +
|
||||
'<span class="icon fa ' + icon + '" aria-hidden="true"></span>' +
|
||||
'<span>' + message + '</span>' +
|
||||
'</div>'
|
||||
);
|
||||
};
|
||||
|
||||
verifyProviderList = function(selectedProvider) {
|
||||
var $transcriptProvidersListEl = $courseVideoSettingsEl.find('.transcript-provider-wrapper .transcript-provider-group'); // eslint-disable-line max-len
|
||||
// Check N/A 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();
|
||||
};
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
$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, {});
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures(
|
||||
'<div class="video-transcript-settings-wrapper"></div>' +
|
||||
@@ -148,17 +272,10 @@ 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(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('');
|
||||
renderCourseVideoSettingsView();
|
||||
// Checking turnaround is sufficient to check preferences are are shown or not.
|
||||
expect($courseVideoSettingsEl.find('.transcript-turnaround-wrapper')).not.toExist();
|
||||
});
|
||||
|
||||
it('populates transcription plans correctly', function() {
|
||||
@@ -169,39 +286,17 @@ define(
|
||||
|
||||
it('populates active preferances correctly', function() {
|
||||
// First check preferance are selected correctly in HTML.
|
||||
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
|
||||
);
|
||||
|
||||
// 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.selectedSourceLanguage,
|
||||
activeTranscriptPreferences.video_source_language
|
||||
);
|
||||
expect(courseVideoSettingsView.selectedLanguages, activeTranscriptPreferences.preferred_languages);
|
||||
verifyTranscriptPreferences();
|
||||
});
|
||||
|
||||
it('shows video source language directly in case of 3Play provider', function() {
|
||||
var sourceLanguages,
|
||||
selectedProvider = '3PlayMedia';
|
||||
|
||||
// Select CIELIO24 provider
|
||||
chooseProvider(selectedProvider);
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials);
|
||||
|
||||
// Select provider
|
||||
changeProvider(selectedProvider);
|
||||
expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider);
|
||||
|
||||
// Verify source langauges menu is shown.
|
||||
@@ -219,10 +314,10 @@ define(
|
||||
selectedProvider = 'Cielo24',
|
||||
selectedFidelity = 'PROFESSIONAL';
|
||||
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans);
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials);
|
||||
|
||||
// Select CIELIO24 provider
|
||||
chooseProvider(selectedProvider);
|
||||
// Select provider
|
||||
changeProvider(selectedProvider);
|
||||
expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider);
|
||||
|
||||
// Verify source language is not shown.
|
||||
@@ -254,8 +349,10 @@ define(
|
||||
selectedProvider = 'Cielo24',
|
||||
selectedFidelity = 'PROFESSIONAL';
|
||||
|
||||
// Select CIELIO24 provider
|
||||
chooseProvider(selectedProvider);
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials);
|
||||
|
||||
// Select provider
|
||||
changeProvider(selectedProvider);
|
||||
expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider);
|
||||
|
||||
// Select fidelity
|
||||
@@ -283,8 +380,10 @@ define(
|
||||
selectedProvider = 'Cielo24',
|
||||
selectedFidelity = 'MECHANICAL';
|
||||
|
||||
// Select CIELIO24 provider
|
||||
chooseProvider(selectedProvider);
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans, transcriptOrganizationCredentials);
|
||||
|
||||
// Select provider
|
||||
changeProvider(selectedProvider);
|
||||
expect(courseVideoSettingsView.selectedProvider).toEqual(selectedProvider);
|
||||
|
||||
// Select fidelity
|
||||
@@ -332,37 +431,16 @@ define(
|
||||
});
|
||||
|
||||
// Verify that success message is shown.
|
||||
expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.success').html()).toEqual(
|
||||
'<div class="course-video-settings-message">' +
|
||||
'<span class="icon fa fa-check-circle" aria-hidden="true"></span>' +
|
||||
'<span>Settings updated</span>' +
|
||||
'</div>'
|
||||
);
|
||||
verifyMessage('success', 'Settings updated');
|
||||
});
|
||||
|
||||
it('removes transcript settings on update settings button click when no provider is selected', function() {
|
||||
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, {});
|
||||
// Reset to N/A provider
|
||||
resetProvider();
|
||||
verifyProviderList(providers.none);
|
||||
|
||||
// Verify that success message is shown.
|
||||
expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.success').html()).toEqual(
|
||||
'<div class="course-video-settings-message">' +
|
||||
'<span class="icon fa fa-check-circle" aria-hidden="true"></span>' +
|
||||
'<span>Settings updated</span>' +
|
||||
'</div>'
|
||||
);
|
||||
verifyMessage('success', 'Settings updated');
|
||||
});
|
||||
|
||||
it('shows error message if server sends error', function() {
|
||||
@@ -390,12 +468,7 @@ define(
|
||||
});
|
||||
|
||||
// Verify that error message is shown.
|
||||
expect($courseVideoSettingsEl.find('.course-video-settings-message-wrapper.error').html()).toEqual(
|
||||
'<div class="course-video-settings-message">' +
|
||||
'<span class="icon fa fa-info-circle" aria-hidden="true"></span>' +
|
||||
'<span>Error message</span>' +
|
||||
'</div>'
|
||||
);
|
||||
verifyMessage('error', 'Error message');
|
||||
});
|
||||
|
||||
it('implies preferences are required if not selected when saving preferances', function() {
|
||||
@@ -423,8 +496,274 @@ 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 N/A provider is saved', function() {
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans);
|
||||
|
||||
// Check N/A 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 N/A provider is checked', function() { // eslint-disable-line max-len
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans);
|
||||
|
||||
// Check N/A 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 api secret input field if selected provider is 3Play Media', function() {
|
||||
// Set selected provider to 3Play Media
|
||||
changeProvider('3PlayMedia');
|
||||
|
||||
// Click change button to render organization credentials view.
|
||||
$courseVideoSettingsEl.find('.action-change-provider').click();
|
||||
|
||||
// Verify 3play api secret and api key are present.
|
||||
verifyOrganizationCredentialField('api-secret', 'API Secret');
|
||||
verifyOrganizationCredentialField('api-key', 'API Key');
|
||||
});
|
||||
|
||||
it('does not show api secret input field if selected provider is not 3Play Media', function() {
|
||||
verifyProviderSelectedView();
|
||||
// Click change button to render organization credentials view.
|
||||
$courseVideoSettingsEl.find('.action-change-provider').click();
|
||||
|
||||
// Verify 3Play Media api secret is not present.
|
||||
expect(
|
||||
$courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-secret')
|
||||
).not.toExist();
|
||||
|
||||
// Verify api key is present.
|
||||
verifyOrganizationCredentialField('api-key', 'API Key');
|
||||
});
|
||||
|
||||
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(
|
||||
'<span>By entering the set of credntials below, ' +
|
||||
'you will be overwriting your organization\'s credentials.</span>'
|
||||
);
|
||||
});
|
||||
|
||||
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(
|
||||
'<span>Please enter your organization\'s account information. ' +
|
||||
'Remember that all courses in your organization will use this account.</span>'
|
||||
);
|
||||
});
|
||||
|
||||
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 organization credentials on clicking save credentials button', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
verifyProviderSelectedView();
|
||||
// Click change button to render organization credentials view.
|
||||
$courseVideoSettingsEl.find('.action-change-provider').click();
|
||||
|
||||
// Set organization credentials so as to pass validations.
|
||||
$courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-key').val('testkey');
|
||||
|
||||
// Click save organization credentials button to save credentials.
|
||||
$courseVideoSettingsEl.find('.action-update-org-credentials').click();
|
||||
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
transcriptCredentialsHandlerUrl,
|
||||
JSON.stringify({
|
||||
provider: activeTranscriptPreferences.provider,
|
||||
global: false
|
||||
})
|
||||
);
|
||||
|
||||
// Send empty response.
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
// Verify that success message is shown.
|
||||
verifyMessage(
|
||||
'success',
|
||||
transcriptionPlans[courseVideoSettingsView.selectedProvider].display_name + ' credentials saved'
|
||||
);
|
||||
});
|
||||
|
||||
it('shows selected provider view afer organization credentials saved', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
renderCourseVideoSettingsView(null, transcriptionPlans);
|
||||
|
||||
// Verify selected provider view is not shown.
|
||||
expect(
|
||||
$courseVideoSettingsEl.find('.transcript-provider-wrapper .selected-transcript-provider')
|
||||
).not.toExist();
|
||||
|
||||
// Verify provider list view is shown.
|
||||
verifyProviderList(providers.none);
|
||||
|
||||
// Check Cielo24 provider
|
||||
changeProvider('Cielo24');
|
||||
verifyProviderList(providers.Cielo24);
|
||||
|
||||
// Set organization credentials so as to pass validations.
|
||||
$courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-key').val('testkey');
|
||||
|
||||
// Click save organization credentials button to save credentials.
|
||||
$courseVideoSettingsEl.find('.action-update-org-credentials').click();
|
||||
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
transcriptCredentialsHandlerUrl,
|
||||
JSON.stringify({
|
||||
provider: activeTranscriptPreferences.provider,
|
||||
global: false
|
||||
})
|
||||
);
|
||||
|
||||
// Send empty response.
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
// Verify that success message is shown.
|
||||
verifyMessage(
|
||||
'success',
|
||||
transcriptionPlans[courseVideoSettingsView.selectedProvider].display_name + ' credentials saved'
|
||||
);
|
||||
|
||||
// Shows selected provider view after credentials are saved.
|
||||
verifyProviderSelectedView();
|
||||
|
||||
// Verify provider list view is not shown.
|
||||
expect(
|
||||
$courseVideoSettingsEl.find('.transcript-provider-wrapper .transcript-provider-group')
|
||||
).not.toExist();
|
||||
});
|
||||
|
||||
it('shows error message on saving organization credentials if server sends error', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
verifyProviderSelectedView();
|
||||
// Click change button to render organization credentials view.
|
||||
$courseVideoSettingsEl.find('.action-change-provider').click();
|
||||
|
||||
// Set organization credentials so as to pass validations.
|
||||
$courseVideoSettingsEl.find('.' + courseVideoSettingsView.selectedProvider + '-api-key').val('testkey');
|
||||
|
||||
// Click save organization credentials button to save credentials.
|
||||
$courseVideoSettingsEl.find('.action-update-org-credentials').click();
|
||||
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
transcriptCredentialsHandlerUrl,
|
||||
JSON.stringify({
|
||||
provider: activeTranscriptPreferences.provider,
|
||||
global: false
|
||||
})
|
||||
);
|
||||
|
||||
// Send error response.
|
||||
AjaxHelpers.respondWithError(requests, 400, {
|
||||
error: 'Error message'
|
||||
});
|
||||
|
||||
// Verify that error message is shown.
|
||||
verifyMessage('error', 'Error message');
|
||||
});
|
||||
|
||||
// TODO: Add more tests like clicking on add language, remove and their scenarios and some other tests
|
||||
// like N/A selected, specific provider selected tests, specific preferance selected tests etc.
|
||||
// for specific preferance selected tests etc. - See EDUCATOR-1478
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -42,6 +42,7 @@ 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;
|
||||
@@ -85,6 +86,7 @@ define([
|
||||
if (this.isVideoTranscriptEnabled) {
|
||||
this.courseVideoSettingsView = new CourseVideoSettingsView({
|
||||
activeTranscriptPreferences: this.activeTranscriptPreferences,
|
||||
transcriptOrganizationCredentials: this.transcriptOrganizationCredentials,
|
||||
videoTranscriptSettings: this.videoTranscriptSettings
|
||||
});
|
||||
this.courseVideoSettingsView.render();
|
||||
|
||||
@@ -3,11 +3,20 @@
|
||||
*/
|
||||
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-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'
|
||||
],
|
||||
function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSettingsTemplate) {
|
||||
function($, Backbone, _, gettext, moment, ViewUtils, HtmlUtils, StringUtils, TranscriptSettingsTemplate,
|
||||
TranscriptPreferencesTemplate, TranscriptProviderEmptyStateTemplate, TranscriptProviderSelectedStateTemplate,
|
||||
OrganizationCredentialsTemplate, UpdateSettingsFooterTemplate, OrganizationCredentialsFooterTemplate) {
|
||||
'use strict';
|
||||
|
||||
var CourseVideoSettingsView,
|
||||
@@ -24,6 +33,8 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
'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-close-course-video-settings': 'closeCourseVideoSettings'
|
||||
},
|
||||
@@ -31,9 +42,17 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
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 = [];
|
||||
},
|
||||
@@ -49,7 +68,7 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
|
||||
// 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();
|
||||
}
|
||||
@@ -158,9 +177,33 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
},
|
||||
|
||||
providerSelected: function(event) {
|
||||
var $courseVideoSettingsContentEl = this.$el.find('.course-video-settings-content'),
|
||||
dateModified = this.activeTranscriptionPlan ?
|
||||
moment.utc(this.activeTranscriptionPlan.modified).format('ll') : '';
|
||||
|
||||
this.resetPlanData();
|
||||
this.selectedProvider = event.target.value;
|
||||
this.renderPreferences();
|
||||
|
||||
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();
|
||||
}
|
||||
},
|
||||
|
||||
languageSelected: function(event) {
|
||||
@@ -187,43 +230,56 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
$(event.target.parentElement).parent().remove();
|
||||
|
||||
// Remove language from selected languages.
|
||||
this.selectedLanguages = _.without(this.selectedLanguages, selectedLanguage);
|
||||
this.selectedLanguages = this.activeLanguages = _.without(this.selectedLanguages, selectedLanguage);
|
||||
|
||||
// Populate menu again to reflect latest changes.
|
||||
this.populateLanguageMenu();
|
||||
},
|
||||
|
||||
renderProviders: function() {
|
||||
var self = this,
|
||||
providerPlan = self.availableTranscriptionPlans,
|
||||
$providerEl = self.$el.find('.transcript-provider-group');
|
||||
renderProviders: function(state) {
|
||||
var $transcriptProviderWrapperEl = this.$el.find('.transcript-provider-wrapper');
|
||||
if (!state) {
|
||||
state = this.selectedProvider ? 'selected' : 'empty'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
if (providerPlan) {
|
||||
// If no transcription plans are sentm return.
|
||||
if (!this.availableTranscriptionPlans) {
|
||||
return;
|
||||
}
|
||||
if (state === 'empty') {
|
||||
HtmlUtils.setHtml(
|
||||
$providerEl,
|
||||
HtmlUtils.interpolateHtml(
|
||||
HtmlUtils.HTML('<input type="radio" id="transcript-provider-none" name="transcript-provider" value="" {checked}/><label for="transcript-provider-none">{text}</label>'), // 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('<input type="radio" id="transcript-provider-{value}" name="transcript-provider" value="{value}" {checked}/><label for="transcript-provider-{value}">{text}'), // eslint-disable-line max-len
|
||||
$transcriptProviderWrapperEl,
|
||||
this.transcriptProviderEmptyStateTemplate({
|
||||
providers: [
|
||||
{
|
||||
text: providerObject.display_name,
|
||||
value: key,
|
||||
checked: checked
|
||||
key: 'none',
|
||||
value: '',
|
||||
name: gettext('N/A'),
|
||||
checked: this.selectedProvider === '' ? 'checked' : ''
|
||||
},
|
||||
{
|
||||
key: CIELO24,
|
||||
value: CIELO24,
|
||||
name: this.availableTranscriptionPlans[CIELO24].display_name,
|
||||
checked: this.selectedProvider === CIELO24 ? 'checked' : ''
|
||||
},
|
||||
{
|
||||
key: THREE_PLAY_MEDIA,
|
||||
value: THREE_PLAY_MEDIA,
|
||||
name: this.availableTranscriptionPlans[THREE_PLAY_MEDIA].display_name,
|
||||
checked: this.selectedProvider === THREE_PLAY_MEDIA ? 'checked' : ''
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
]
|
||||
})
|
||||
);
|
||||
} else {
|
||||
HtmlUtils.setHtml(
|
||||
$transcriptProviderWrapperEl,
|
||||
this.transcriptProviderSelectedStateTemplate({
|
||||
selectedProvider: this.availableTranscriptionPlans[this.selectedProvider].display_name
|
||||
})
|
||||
);
|
||||
this.renderTranscriptPreferences();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -284,6 +340,10 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
|
||||
renderTargetLanguages: function() {
|
||||
var self = this,
|
||||
// Merge active and selected languages, this handles the case when active languages are present and
|
||||
// user also has selected some languages but not saved, user changes organization credentials,
|
||||
// both active and selected languages should be rendered.
|
||||
selectedLanguages = _.union(self.activeLanguages, self.selectedLanguages),
|
||||
$languagesPreferenceContainer = self.$el.find('.transcript-languages-wrapper'),
|
||||
$languagesContainer = self.$el.find('.languages-container');
|
||||
|
||||
@@ -292,9 +352,9 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
|
||||
$languagesContainer.empty();
|
||||
|
||||
// Show language container if source language is selected .
|
||||
// Show language container if source language is selected.
|
||||
if (self.selectedVideoSourceLanguage) {
|
||||
_.each(self.activeLanguages, function(language) {
|
||||
_.each(selectedLanguages, function(language) {
|
||||
// Only add if not in the list already.
|
||||
if (_.indexOf(self.selectedLanguages, language) === -1) {
|
||||
self.selectedLanguages.push(language);
|
||||
@@ -386,14 +446,6 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
}
|
||||
},
|
||||
|
||||
renderPreferences: function() {
|
||||
this.renderProviders();
|
||||
this.renderTurnaround();
|
||||
this.renderFidelity();
|
||||
this.renderSourceLanguages();
|
||||
this.renderTargetLanguages();
|
||||
},
|
||||
|
||||
addLanguage: function(language) {
|
||||
var $languagesContainer = this.$el.find('.languages-container');
|
||||
HtmlUtils.append(
|
||||
@@ -419,8 +471,9 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
);
|
||||
},
|
||||
|
||||
updateSuccessResponseStatus: function(data) {
|
||||
updateSuccessResponseStatus: function(data, successMessage) {
|
||||
var dateModified = data ? moment.utc(data.modified).format('ll') : '';
|
||||
successMessage = successMessage ? successMessage : gettext('Settings updated'); // eslint-disable-line no-param-reassign, no-unneeded-ternary, max-len
|
||||
|
||||
// Update last modified date
|
||||
if (dateModified) {
|
||||
@@ -436,7 +489,10 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
);
|
||||
}
|
||||
|
||||
this.renderResponseStatus(gettext('Settings updated'), 'success');
|
||||
// Now re-render providers state.
|
||||
this.renderProviders();
|
||||
|
||||
this.renderResponseStatus(successMessage, 'success');
|
||||
// Sync ActiveUploadListView with latest active plan.
|
||||
this.activeTranscriptionPlan = data;
|
||||
Backbone.trigger('coursevideosettings:syncActiveTranscriptPreferences', this.activeTranscriptionPlan);
|
||||
@@ -548,6 +604,37 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
return isValid;
|
||||
},
|
||||
|
||||
validateOrganizationCredentials: function() {
|
||||
var $OrganizationApiSecretWrapperEl,
|
||||
isValid = true,
|
||||
$OrganizationApiKeyWrapperEl = this.$el.find('.' + this.selectedProvider + '-api-key-wrapper');
|
||||
|
||||
|
||||
// Explicit None selected case.
|
||||
if (this.selectedProvider === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($OrganizationApiKeyWrapperEl.find('input').val() === '') {
|
||||
isValid = false;
|
||||
this.addErrorState($OrganizationApiKeyWrapperEl);
|
||||
} else {
|
||||
this.clearPreferenceErrorState($OrganizationApiKeyWrapperEl);
|
||||
}
|
||||
|
||||
if (this.selectedProvider === THREE_PLAY_MEDIA) {
|
||||
$OrganizationApiSecretWrapperEl = this.$el.find('.' + this.selectedProvider + '-api-secret-wrapper');
|
||||
if ($OrganizationApiSecretWrapperEl.find('input').val() === '') {
|
||||
isValid = false;
|
||||
this.addErrorState($OrganizationApiSecretWrapperEl);
|
||||
} else {
|
||||
this.clearPreferenceErrorState($OrganizationApiSecretWrapperEl);
|
||||
}
|
||||
}
|
||||
|
||||
return isValid;
|
||||
},
|
||||
|
||||
saveTranscriptPreferences: function() {
|
||||
var self = this,
|
||||
responseTranscriptPreferences;
|
||||
@@ -585,6 +672,42 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
}
|
||||
},
|
||||
|
||||
saveOrganizationCredentials: function() {
|
||||
var self = this;
|
||||
// First clear response status if present already
|
||||
this.clearResponseStatus();
|
||||
|
||||
// TODO: Send actual organization credentials.
|
||||
|
||||
$.postJSON(self.transcriptCredentialsHandlerUrl, {
|
||||
provider: self.selectedProvider,
|
||||
global: false // Do not trigger global AJAX error handler
|
||||
}, function() {
|
||||
self.$el.find('.organization-credentials-wrapper').hide();
|
||||
|
||||
// Update org credentials for selected provider
|
||||
self.transcriptOrganizationCredentials[self.selectedProvider] = true;
|
||||
|
||||
self.updateSuccessResponseStatus(
|
||||
self.activeTranscriptionPlan,
|
||||
gettext('{selectedProvider} credentials saved').replace(
|
||||
'{selectedProvider}',
|
||||
self.availableTranscriptionPlans[self.selectedProvider].display_name
|
||||
)
|
||||
);
|
||||
}).fail(function(jqXHR) {
|
||||
if (jqXHR.responseText) {
|
||||
self.updateFailResponseStatus(jqXHR.responseText);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateOrganizationCredentials: function() {
|
||||
if (this.validateOrganizationCredentials()) {
|
||||
this.saveOrganizationCredentials();
|
||||
}
|
||||
},
|
||||
|
||||
updateCourseVideoSettings: function() {
|
||||
var $messageWrapperEl = this.$el.find('.course-video-settings-message-wrapper');
|
||||
if (this.validateCourseVideoSettings()) {
|
||||
@@ -594,17 +717,74 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
}
|
||||
},
|
||||
|
||||
renderOrganizationCredentials: function() {
|
||||
var $courseVideoSettingsContentEl = this.$el.find('.course-video-settings-content');
|
||||
|
||||
// Render empty state providers view.
|
||||
this.renderProviders('empty');
|
||||
|
||||
HtmlUtils.setHtml(
|
||||
$courseVideoSettingsContentEl,
|
||||
this.organizationCredentialsTemplate({
|
||||
selectedProvider: {
|
||||
key: this.selectedProvider,
|
||||
name: this.availableTranscriptionPlans[this.selectedProvider].display_name
|
||||
},
|
||||
organizationCredentialsExists: this.transcriptOrganizationCredentials[this.selectedProvider],
|
||||
CIELO24: CIELO24,
|
||||
THREE_PLAY_MEDIA: THREE_PLAY_MEDIA
|
||||
})
|
||||
);
|
||||
// Render footer
|
||||
HtmlUtils.setHtml(
|
||||
this.$el.find('.course-video-settings-footer'),
|
||||
this.organizationCredentialsFooterTemplate({})
|
||||
);
|
||||
},
|
||||
|
||||
renderTranscriptPreferences: function() {
|
||||
var $courseVideoSettingsContentEl = this.$el.find('.course-video-settings-content'),
|
||||
dateModified = this.activeTranscriptionPlan ?
|
||||
moment.utc(this.activeTranscriptionPlan.modified).format('ll') : '';
|
||||
|
||||
HtmlUtils.setHtml(
|
||||
$courseVideoSettingsContentEl,
|
||||
this.transcriptPreferencesTemplate({
|
||||
selectedProvider: this.selectedProvider,
|
||||
THREE_PLAY_MEDIA: THREE_PLAY_MEDIA
|
||||
})
|
||||
);
|
||||
|
||||
// Render transcript preferences.
|
||||
this.renderTurnaround();
|
||||
this.renderFidelity();
|
||||
this.renderSourceLanguages();
|
||||
this.renderTargetLanguages();
|
||||
|
||||
// Render footer
|
||||
HtmlUtils.setHtml(
|
||||
this.$el.find('.course-video-settings-footer'),
|
||||
this.updateSettingsFooterTemplate({
|
||||
dateModified: dateModified
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var dateModified = this.activeTranscriptionPlan ?
|
||||
moment.utc(this.activeTranscriptionPlan.modified).format('ll') : '';
|
||||
|
||||
HtmlUtils.setHtml(this.$el, this.template({}));
|
||||
|
||||
// Render footer
|
||||
HtmlUtils.setHtml(
|
||||
this.$el,
|
||||
this.template({
|
||||
this.$el.find('.course-video-settings-footer'),
|
||||
this.updateSettingsFooterTemplate({
|
||||
dateModified: dateModified
|
||||
})
|
||||
);
|
||||
|
||||
this.renderPreferences();
|
||||
this.renderProviders();
|
||||
|
||||
this.registerCloseClickHandler();
|
||||
this.setFixedCourseVideoSettingsPane();
|
||||
@@ -640,7 +820,7 @@ function($, Backbone, _, gettext, moment, HtmlUtils, StringUtils, TranscriptSett
|
||||
},
|
||||
|
||||
closeCourseVideoSettings: function() {
|
||||
// TODO: Slide out when closing settings pane. We may need to hide the view instead of destroying it.
|
||||
// TODO: Slide out when closing settings pane. See EDUCATOR-1477
|
||||
|
||||
// Trigger destroy transcript event.
|
||||
Backbone.trigger('coursevideosettings:destroyCourseVideoSettingsView');
|
||||
|
||||
@@ -83,6 +83,18 @@
|
||||
border: solid 1px $state-danger-border;
|
||||
}
|
||||
|
||||
.organization-credentials-content {
|
||||
margin-top: ($baseline*1.6);
|
||||
.org-credentials-wrapper input {
|
||||
width: 75%;
|
||||
margin: ($baseline*0.8) 0;
|
||||
}
|
||||
.action-update-org-credentials {
|
||||
margin-top: ($baseline*1.6);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.transcript-preferance-wrapper {
|
||||
margin-top: ($baseline*1.6);
|
||||
.icon.fa-info-circle {
|
||||
@@ -99,6 +111,7 @@
|
||||
|
||||
.error-info {
|
||||
@include font-size(16);
|
||||
@include margin-left($baseline/2);
|
||||
}
|
||||
|
||||
.transcript-preferance-label {
|
||||
@@ -108,10 +121,15 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.transcript-provider-group, .transcript-turnaround, .transcript-fidelity, .video-source-language {
|
||||
.transcript-provider-group, .transcript-turnaround, .transcript-fidelity, .video-source-language, .selected-transcript-provider {
|
||||
margin-top: ($baseline*0.8);
|
||||
}
|
||||
|
||||
.selected-transcript-provider {
|
||||
.action-change-provider {
|
||||
@include margin-left($baseline/2);
|
||||
}
|
||||
}
|
||||
|
||||
.transcript-provider-group {
|
||||
input[type=radio] {
|
||||
@@ -128,6 +146,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.transcript-languages-wrapper .transcript-preferance-label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.transcript-languages-container .languages-container {
|
||||
margin-top: ($baseline*0.8);
|
||||
.transcript-language-container {
|
||||
@@ -148,6 +170,9 @@
|
||||
.action-add-language {
|
||||
@include margin-left($baseline/4);
|
||||
}
|
||||
.error-info {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.transcript-language-menu, .video-source-language {
|
||||
@@ -155,6 +180,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.transcription-account-details {
|
||||
margin-top: ($baseline*0.8);
|
||||
span {
|
||||
@include font-size(15);
|
||||
}
|
||||
}
|
||||
|
||||
.transcription-account-details.warning {
|
||||
background-color: $state-warning-bg;
|
||||
padding: ($baseline/2);
|
||||
}
|
||||
|
||||
.action-update-org-credentials {
|
||||
margin-top: ($baseline*1.6);
|
||||
}
|
||||
|
||||
.course-video-settings-footer {
|
||||
margin-top: ($baseline*1.6);
|
||||
.last-updated-text {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<button class='button action-update-org-credentials' aria-describedby='update-org-credentials-button-text'>
|
||||
<%- gettext('Update Organization Credentials') %>
|
||||
<span id='update-org-credentials-button-text' class='sr'><%-gettext('Press update organization credentials to update organization credentials') %></span>
|
||||
</button>
|
||||
@@ -0,0 +1,9 @@
|
||||
<button class="button action-update-course-video-settings" aria-describedby='update-button-text'>
|
||||
<%- gettext('Update Settings') %>
|
||||
<span id='update-button-text' class='sr'><%-gettext('Press update settings to update course video settings') %></span>
|
||||
</button>
|
||||
<span class='last-updated-text'>
|
||||
<%if (dateModified) { %>
|
||||
<%- gettext('Last updated')%> <%- dateModified %>
|
||||
<% } %>
|
||||
</span>
|
||||
@@ -11,49 +11,8 @@
|
||||
<div class='course-video-settings-wrapper'>
|
||||
<div class='course-video-settings-message-wrapper'></div>
|
||||
<span class="course-video-settings-title"><%- gettext('Course Video Settings') %></span>
|
||||
<div class='transcript-preferance-wrapper transcript-provider-wrapper'>
|
||||
<label class='transcript-preferance-label' for='transcript-provider'><%- gettext('Transcript Provider') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<div class='transcript-provider-group' id='transcript-provider'></div>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-turnaround-wrapper'>
|
||||
<label class='transcript-preferance-label' for='transcript-turnaround'><%- gettext('Transcript Turnaround') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='transcript-turnaround' class='transcript-turnaround'></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-fidelity-wrapper'>
|
||||
<label class='transcript-preferance-label' for='transcript-fidelity'><%- gettext('Transcript Fidelity') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='transcript-fidelity' class='transcript-fidelity'></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper video-source-language-wrapper'>
|
||||
<label class='transcript-preferance-label' for='video-source-language'><%- gettext('Video Source Language') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='video-source-language' class='video-source-language' aria-labelledby="video-source-language-none"></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-languages-wrapper'>
|
||||
<span class='transcript-preferance-label'><%- gettext('Transcript Languages') %><span class='error-icon' aria-hidden="true"></span></span>
|
||||
<div class='transcript-languages-container'>
|
||||
<div class='languages-container'></div>
|
||||
<div class="transcript-language-menu-container">
|
||||
<select class="transcript-language-menu" id="transcript-language" aria-labelledby="transcript-language-none"></select>
|
||||
<div class="add-language-action">
|
||||
<button class="button-link action-add-language"><%- gettext('Add') %><span class="sr"><%- gettext('Press Add to language') %></span></button>
|
||||
<span class="error-info" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='course-video-settings-footer'>
|
||||
<button class="button button action-update-course-video-settings" aria-describedby='update-button-text'>
|
||||
<%- gettext('Update Settings') %>
|
||||
<span id='update-button-text' class='sr'><%-gettext('Press update settings to update course video settings') %></span>
|
||||
</button>
|
||||
<span class='last-updated-text'>
|
||||
<%if (dateModified) { %>
|
||||
<%- gettext('Last updated')%> <%- dateModified %>
|
||||
<% } %>
|
||||
</span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-provider-wrapper'></div>
|
||||
<div class='course-video-settings-content'></div>
|
||||
<div class='course-video-settings-footer'></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<div class='course-video-transcript-preferances-wrapper'>
|
||||
<div class='transcript-preferance-wrapper transcript-turnaround-wrapper'>
|
||||
<label class='transcript-preferance-label' for='transcript-turnaround'><%- gettext('Transcript Turnaround') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='transcript-turnaround' class='transcript-turnaround'></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-fidelity-wrapper'>
|
||||
<label class='transcript-preferance-label' for='transcript-fidelity'><%- gettext('Transcript Fidelity') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='transcript-fidelity' class='transcript-fidelity'></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper video-source-language-wrapper'>
|
||||
<label class='transcript-preferance-label' for='video-source-language'><%- gettext('Video Source Language') %><span class='error-icon' aria-hidden="true"></span></label>
|
||||
<select id='video-source-language' class='video-source-language' aria-labelledby="video-source-language-none"></select>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
<div class='transcript-preferance-wrapper transcript-languages-wrapper'>
|
||||
<span class='transcript-preferance-label'><%- gettext('Transcript Languages') %></span>
|
||||
<span class='error-icon' aria-hidden="true"></span>
|
||||
<div class='transcript-languages-container'>
|
||||
<div class='languages-container'></div>
|
||||
<div class="transcript-language-menu-container">
|
||||
<select class="transcript-language-menu" id="transcript-language" aria-labelledby="transcript-language-none"></select>
|
||||
<div class="add-language-action">
|
||||
<button class="button-link action-add-language"><%- gettext('Add') %><span class="sr"><%- gettext('Press Add to language') %></span></button>
|
||||
</div>
|
||||
<span class="error-info" aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
<label class='transcript-preferance-label' for='transcript-provider'><%- gettext('Transcript Provider') %></label>
|
||||
<div class="transcript-provider-group" id="transcript-provider">
|
||||
<% for (var i = 0; i < providers.length; i++) { %>
|
||||
<input type='radio' id='transcript-provider-<%- providers[i].key %>' name='transcript-provider' value='<%- providers[i].value %>' <%- providers[i].checked %>>
|
||||
<label for='transcript-provider-<%- providers[i].key %>'><%- providers[i].name %></label>
|
||||
<% } %>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
<label class='transcript-preferance-label' for='transcript-provider'><%- gettext('Transcript Provider') %></label>
|
||||
<div class='selected-transcript-provider'>
|
||||
<span class='title'><%- selectedProvider %></span>
|
||||
<button class='button-link action-change-provider' aria-describedby='change-provider-button-text'>
|
||||
<%- gettext('Change') %>
|
||||
<span id='change-provider-button-text' class='sr'><%-gettext('Press change to change selected transcript provider.') %></span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,43 @@
|
||||
<div class='organization-credentials-wrapper'>
|
||||
<div class='organization-credentials-content'>
|
||||
<label class='transcript-preferance-label selected-provider-account'><%- selectedProvider.name %> <%- gettext('Account') %></label>
|
||||
<% if (organizationCredentialsExists) { %>
|
||||
<div class='transcription-account-details warning'><span><%- gettext("By entering the set of credntials below, you will be overwriting your organization's credentials.") %></span></div>
|
||||
<% } else { %>
|
||||
<div class='transcription-account-details'><span><%- gettext("Please enter your organization's account information. Remember that all courses in your organization will use this account.") %></span></div>
|
||||
<% } %>
|
||||
<div class='transcript-preferance-wrapper org-credentials-wrapper <%- selectedProvider.key %>-api-key-wrapper'>
|
||||
<label class='transcript-preferance-label' for='<%- selectedProvider.key %>-api-key'>
|
||||
<span class='title'><%- gettext('API Key') %></span>
|
||||
<span class='error-icon' aria-hidden="true"></span>
|
||||
</label>
|
||||
<div>
|
||||
<input type='text' class='<%- selectedProvider.key %>-api-key'>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<% if (selectedProvider.key === THREE_PLAY_MEDIA) { %>
|
||||
<div class='transcript-preferance-wrapper org-credentials-wrapper <%- selectedProvider.key %>-api-secret-wrapper'>
|
||||
<label class='transcript-preferance-label' for='<%- selectedProvider.key %>-api-secret'>
|
||||
<span class='title'><%- gettext('API Secret') %></span>
|
||||
<span class='error-icon' aria-hidden="true"></span>
|
||||
</label>
|
||||
<div>
|
||||
<input type='text' class='<%- selectedProvider.key %>-api-secret'>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class='transcript-preferance-wrapper org-credentials-wrapper <%- selectedProvider.key %>-username-wrapper'>
|
||||
<label class='transcript-preferance-label' for='<%- selectedProvider.key %>-username'>
|
||||
<span class='title'><%- gettext('Username') %></span>
|
||||
<span class='error-icon' aria-hidden="true"></span>
|
||||
</label>
|
||||
<div>
|
||||
<input type='text' class='<%- selectedProvider.key %>-username'>
|
||||
<span class='error-info' aria-hidden="true"></span>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -39,6 +39,7 @@
|
||||
${video_supported_file_formats | n, dump_js_escaped_json},
|
||||
${video_upload_max_file_size | n, dump_js_escaped_json},
|
||||
${active_transcript_preferences | n, dump_js_escaped_json},
|
||||
${transcript_credentials | n, dump_js_escaped_json},
|
||||
${video_transcript_settings | n, dump_js_escaped_json},
|
||||
${is_video_transcript_enabled | n, dump_js_escaped_json},
|
||||
${video_image_settings | n, dump_js_escaped_json}
|
||||
|
||||
@@ -141,6 +141,8 @@ urlpatterns = [
|
||||
contentstore.views.video_images_handler, name='video_images_handler'),
|
||||
url(r'^transcript_preferences/{}$'.format(settings.COURSE_KEY_PATTERN),
|
||||
contentstore.views.transcript_preferences_handler, name='transcript_preferences_handler'),
|
||||
url(r'^transcript_credentials/{}$'.format(settings.COURSE_KEY_PATTERN),
|
||||
contentstore.views.transcript_credentials_handler, name='transcript_credentials_handler'),
|
||||
url(r'^video_encodings_download/{}$'.format(settings.COURSE_KEY_PATTERN),
|
||||
contentstore.views.video_encodings_download, name='video_encodings_download'),
|
||||
url(r'^group_configurations/{}$'.format(settings.COURSE_KEY_PATTERN),
|
||||
|
||||
Reference in New Issue
Block a user