Show transcripts on video uploads page - EDUCATOR-1662
This commit is contained in:
@@ -15,7 +15,13 @@ import pytz
|
||||
from django.conf import settings
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
from django.test.utils import override_settings
|
||||
from edxval.api import create_profile, create_video, get_video_info, get_course_video_image_url
|
||||
from edxval.api import (
|
||||
create_profile,
|
||||
create_video,
|
||||
get_video_info,
|
||||
get_course_video_image_url,
|
||||
create_or_update_video_transcript
|
||||
)
|
||||
from mock import Mock, patch
|
||||
|
||||
from contentstore.models import VideoUploadConfig
|
||||
@@ -228,6 +234,78 @@ class VideosHandlerTestCase(VideoUploadTestMixin, CourseTestCase):
|
||||
convert_video_status(original_video)
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
(
|
||||
False,
|
||||
['edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'course_video_image_url'],
|
||||
[],
|
||||
{}
|
||||
),
|
||||
(
|
||||
True,
|
||||
['edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'course_video_image_url',
|
||||
'transcripts'],
|
||||
[
|
||||
{
|
||||
'video_id': 'test1',
|
||||
'language_code': 'en',
|
||||
'file_name': 'edx101.srt',
|
||||
'file_format': 'srt',
|
||||
'provider': 'Cielo24'
|
||||
}
|
||||
],
|
||||
{
|
||||
'en': 'English'
|
||||
}
|
||||
),
|
||||
(
|
||||
True,
|
||||
['edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'course_video_image_url',
|
||||
'transcripts'],
|
||||
[
|
||||
{
|
||||
'video_id': 'test1',
|
||||
'language_code': 'en',
|
||||
'file_name': 'edx101_en.srt',
|
||||
'file_format': 'srt',
|
||||
'provider': 'Cielo24'
|
||||
},
|
||||
{
|
||||
'video_id': 'test1',
|
||||
'language_code': 'es',
|
||||
'file_name': 'edx101_es.srt',
|
||||
'file_format': 'srt',
|
||||
'provider': 'Cielo24'
|
||||
}
|
||||
],
|
||||
{
|
||||
'en': 'English',
|
||||
'es': 'Spanish'
|
||||
}
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
@patch('openedx.core.djangoapps.video_config.models.VideoTranscriptEnabledFlag.feature_enabled')
|
||||
def test_get_json_transcripts(self, is_video_transcript_enabled, expected_video_keys, uploaded_transcripts,
|
||||
expected_transcripts, video_transcript_feature):
|
||||
"""
|
||||
Test that transcripts are attached based on video transcript feature enablement.
|
||||
"""
|
||||
video_transcript_feature.return_value = is_video_transcript_enabled
|
||||
|
||||
for transcript in uploaded_transcripts:
|
||||
create_or_update_video_transcript(**transcript)
|
||||
|
||||
response = self.client.get_json(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response_videos = json.loads(response.content)['videos']
|
||||
self.assertEqual(len(response_videos), len(self.previous_uploads))
|
||||
|
||||
for response_video in response_videos:
|
||||
self.assertEqual(set(response_video.keys()), set(expected_video_keys))
|
||||
if response_video['edx_video_id'] == self.previous_uploads[0]['edx_video_id']:
|
||||
self.assertDictEqual(response_video.get('transcripts', {}), expected_transcripts)
|
||||
|
||||
def test_get_html(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@@ -30,7 +30,8 @@ from edxval.api import (
|
||||
remove_transcript_preferences,
|
||||
remove_video_for_course,
|
||||
update_video_image,
|
||||
update_video_status
|
||||
update_video_status,
|
||||
get_available_transcript_languages
|
||||
)
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
@@ -72,6 +73,9 @@ VIDEO_UPLOAD_MAX_FILE_SIZE_GB = 5
|
||||
# maximum time for video to remain in upload state
|
||||
MAX_UPLOAD_HOURS = 24
|
||||
|
||||
# Transcript download format
|
||||
TRANSCRIPT_DOWNLOAD_FILE_FORMAT = 'srt'
|
||||
|
||||
|
||||
class TranscriptProvider(object):
|
||||
"""
|
||||
@@ -528,12 +532,20 @@ def _get_videos(course):
|
||||
"""
|
||||
Retrieves the list of videos from VAL corresponding to this course.
|
||||
"""
|
||||
is_video_transcript_enabled = VideoTranscriptEnabledFlag.feature_enabled(course.id)
|
||||
videos = list(get_videos_for_course(unicode(course.id), VideoSortField.created, SortDirection.desc))
|
||||
|
||||
# convert VAL's status to studio's Video Upload feature status.
|
||||
for video in videos:
|
||||
video["status"] = convert_video_status(video)
|
||||
|
||||
if is_video_transcript_enabled:
|
||||
all_languages = get_all_transcript_languages()
|
||||
video['transcripts'] = {
|
||||
lang_code: all_languages[lang_code]
|
||||
for lang_code in get_available_transcript_languages([video['edx_video_id']])
|
||||
}
|
||||
|
||||
return videos
|
||||
|
||||
|
||||
@@ -551,6 +563,9 @@ def _get_index_videos(course):
|
||||
course_id = unicode(course.id)
|
||||
attrs = ['edx_video_id', 'client_video_id', 'created', 'duration', 'status', 'courses']
|
||||
|
||||
if VideoTranscriptEnabledFlag.feature_enabled(course.id):
|
||||
attrs += ['transcripts']
|
||||
|
||||
def _get_values(video):
|
||||
"""
|
||||
Get data for predefined video attributes.
|
||||
@@ -570,6 +585,24 @@ def _get_index_videos(course):
|
||||
]
|
||||
|
||||
|
||||
def get_all_transcript_languages():
|
||||
"""
|
||||
Returns all possible languages for transcript.
|
||||
"""
|
||||
third_party_transcription_languages = {}
|
||||
transcription_plans = get_3rd_party_transcription_plans()
|
||||
cielo_fidelity = transcription_plans[TranscriptProvider.CIELO24]['fidelity']
|
||||
|
||||
# Get third party transcription languages.
|
||||
third_party_transcription_languages.update(transcription_plans[TranscriptProvider.THREE_PLAY_MEDIA]['languages'])
|
||||
third_party_transcription_languages.update(cielo_fidelity['MECHANICAL']['languages'])
|
||||
third_party_transcription_languages.update(cielo_fidelity['PREMIUM']['languages'])
|
||||
third_party_transcription_languages.update(cielo_fidelity['PROFESSIONAL']['languages'])
|
||||
|
||||
# Return combined system settings and 3rd party transcript languages.
|
||||
return dict(settings.ALL_LANGUAGES, **third_party_transcription_languages)
|
||||
|
||||
|
||||
def videos_index_html(course):
|
||||
"""
|
||||
Returns an HTML page to display previous video uploads and allow new ones
|
||||
@@ -596,7 +629,8 @@ def videos_index_html(course):
|
||||
'is_video_transcript_enabled': is_video_transcript_enabled,
|
||||
'video_transcript_settings': None,
|
||||
'active_transcript_preferences': None,
|
||||
'transcript_credentials': None
|
||||
'transcript_credentials': None,
|
||||
'transcript_available_languages': None
|
||||
}
|
||||
|
||||
if is_video_transcript_enabled:
|
||||
@@ -610,10 +644,12 @@ def videos_index_html(course):
|
||||
unicode(course.id)
|
||||
),
|
||||
'transcription_plans': get_3rd_party_transcription_plans(),
|
||||
'trancript_download_file_format': TRANSCRIPT_DOWNLOAD_FILE_FORMAT
|
||||
}
|
||||
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)
|
||||
context['transcript_available_languages'] = get_all_transcript_languages()
|
||||
|
||||
return render_to_response('videos_index.html', context)
|
||||
|
||||
|
||||
@@ -259,6 +259,7 @@
|
||||
'js/spec/views/previous_video_upload_spec',
|
||||
'js/spec/views/video_thumbnail_spec',
|
||||
'js/spec/views/course_video_settings_spec',
|
||||
'js/spec/views/video_transcripts_spec',
|
||||
'js/spec/views/previous_video_upload_list_spec',
|
||||
'js/spec/views/assets_spec',
|
||||
'js/spec/views/baseview_spec',
|
||||
|
||||
@@ -18,7 +18,8 @@ define([
|
||||
transcriptOrganizationCredentials,
|
||||
videoTranscriptSettings,
|
||||
isVideoTranscriptEnabled,
|
||||
videoImageSettings
|
||||
videoImageSettings,
|
||||
transcriptAvailableLanguages
|
||||
) {
|
||||
var activeView = new ActiveVideoUploadListView({
|
||||
postUrl: videoHandlerUrl,
|
||||
@@ -51,7 +52,11 @@ define([
|
||||
videoHandlerUrl: videoHandlerUrl,
|
||||
collection: updatedCollection,
|
||||
encodingsDownloadUrl: encodingsDownloadUrl,
|
||||
videoImageSettings: videoImageSettings
|
||||
videoImageSettings: videoImageSettings,
|
||||
videoTranscriptSettings: videoTranscriptSettings,
|
||||
transcriptAvailableLanguages: transcriptAvailableLanguages,
|
||||
videoSupportedFileFormats: videoSupportedFileFormats,
|
||||
isVideoTranscriptEnabled: isVideoTranscriptEnabled
|
||||
});
|
||||
$contentWrapper.find('.wrapper-assets').replaceWith(updatedView.render().$el);
|
||||
});
|
||||
@@ -63,7 +68,11 @@ define([
|
||||
videoHandlerUrl: videoHandlerUrl,
|
||||
collection: new Backbone.Collection(previousUploads),
|
||||
encodingsDownloadUrl: encodingsDownloadUrl,
|
||||
videoImageSettings: videoImageSettings
|
||||
videoImageSettings: videoImageSettings,
|
||||
videoTranscriptSettings: videoTranscriptSettings,
|
||||
transcriptAvailableLanguages: transcriptAvailableLanguages,
|
||||
videoSupportedFileFormats: videoSupportedFileFormats,
|
||||
isVideoTranscriptEnabled: isVideoTranscriptEnabled
|
||||
});
|
||||
$contentWrapper.append(activeView.render().$el);
|
||||
$contentWrapper.append(previousView.render().$el);
|
||||
|
||||
189
cms/static/js/spec/views/video_transcripts_spec.js
Normal file
189
cms/static/js/spec/views/video_transcripts_spec.js
Normal file
@@ -0,0 +1,189 @@
|
||||
define(
|
||||
['jquery', 'underscore', 'backbone', 'js/views/video_transcripts', 'js/views/previous_video_upload_list',
|
||||
'common/js/spec_helpers/template_helpers'],
|
||||
function($, _, Backbone, VideoTranscriptsView, PreviousVideoUploadListView, TemplateHelpers) {
|
||||
'use strict';
|
||||
describe('VideoTranscriptsView', function() {
|
||||
var videoTranscriptsView,
|
||||
renderView,
|
||||
verifyTranscriptActions,
|
||||
transcripts = {
|
||||
en: 'English',
|
||||
es: 'Spanish',
|
||||
ur: 'Urdu'
|
||||
},
|
||||
edxVideoID = 'test-edx-video-id',
|
||||
clientVideoID = 'Video client title name.mp4',
|
||||
transcriptAvailableLanguages = {
|
||||
en: 'English',
|
||||
es: 'Spanish',
|
||||
cn: 'Chinese',
|
||||
ar: 'Arabic',
|
||||
ur: 'Urdu'
|
||||
},
|
||||
TRANSCRIPT_DOWNLOAD_FILE_FORMAT = 'srt',
|
||||
videoSupportedFileFormats = ['.mov', '.mp4'],
|
||||
videoTranscriptSettings = {
|
||||
trancript_download_file_format: TRANSCRIPT_DOWNLOAD_FILE_FORMAT
|
||||
},
|
||||
videoListView;
|
||||
|
||||
verifyTranscriptActions = function($transcriptActionsEl, transcriptLanguage) {
|
||||
var downloadTranscriptActionEl = $transcriptActionsEl.find('.download-transcript-button'),
|
||||
uploadTranscriptActionEl = $transcriptActionsEl.find('.upload-transcript-button');
|
||||
|
||||
expect(downloadTranscriptActionEl.html().trim(), 'Download');
|
||||
expect(downloadTranscriptActionEl.attr('href'), '#');
|
||||
|
||||
expect(uploadTranscriptActionEl.html().trim(), 'Upload');
|
||||
expect(uploadTranscriptActionEl.data('edx-video-id'), edxVideoID);
|
||||
expect(uploadTranscriptActionEl.data('language-code'), transcriptLanguage);
|
||||
};
|
||||
|
||||
renderView = function(availableTranscripts, isVideoTranscriptEnabled) {
|
||||
var videoViewIndex = 0,
|
||||
isVideoTranscriptEnabled = isVideoTranscriptEnabled || _.isUndefined(isVideoTranscriptEnabled), // eslint-disable-line max-len, no-redeclare
|
||||
videoData = {
|
||||
client_video_id: clientVideoID,
|
||||
edx_video_id: edxVideoID,
|
||||
created: '2014-11-25T23:13:05',
|
||||
transcripts: availableTranscripts
|
||||
},
|
||||
videoCollection = new Backbone.Collection([new Backbone.Model(videoData)]);
|
||||
|
||||
videoListView = new PreviousVideoUploadListView({
|
||||
collection: videoCollection,
|
||||
videoImageSettings: {},
|
||||
videoTranscriptSettings: videoTranscriptSettings,
|
||||
transcriptAvailableLanguages: transcriptAvailableLanguages,
|
||||
videoSupportedFileFormats: videoSupportedFileFormats,
|
||||
isVideoTranscriptEnabled: isVideoTranscriptEnabled
|
||||
});
|
||||
videoListView.setElement($('.wrapper-assets'));
|
||||
videoListView.render();
|
||||
|
||||
videoTranscriptsView = videoListView.itemViews[videoViewIndex].videoTranscriptsView;
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<section class="wrapper-assets"></section>');
|
||||
TemplateHelpers.installTemplate('previous-video-upload-list');
|
||||
renderView(transcripts);
|
||||
});
|
||||
|
||||
it('renders as expected', function() {
|
||||
// Verify transcript container is present.
|
||||
expect(videoListView.$el.find('.show-video-transcripts-container')).toExist();
|
||||
// Veirfy transcript column header is present.
|
||||
expect(videoListView.$el.find('.js-table-head .video-head-col.transcripts-col')).toExist();
|
||||
// Verify transcript data column is present.
|
||||
expect(videoListView.$el.find('.js-table-body .transcripts-col')).toExist();
|
||||
// Verify view has initiallized.
|
||||
expect(_.isUndefined(videoTranscriptsView)).toEqual(false);
|
||||
});
|
||||
|
||||
it('does not render transcripts view if feature is disabled', function() {
|
||||
renderView(transcripts, false);
|
||||
// Verify transcript container is not present.
|
||||
expect(videoListView.$el.find('.show-video-transcripts-container')).not.toExist();
|
||||
// Veirfy transcript column header is not present.
|
||||
expect(videoListView.$el.find('.js-table-head .video-head-col.transcripts-col')).not.toExist();
|
||||
// Verify transcript data column is not present.
|
||||
expect(videoListView.$el.find('.js-table-body .transcripts-col')).not.toExist();
|
||||
// Verify view has not initiallized.
|
||||
expect(_.isUndefined(videoTranscriptsView)).toEqual(true);
|
||||
});
|
||||
|
||||
it('does not show list of transcripts initially', function() {
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden')
|
||||
).toEqual(true);
|
||||
expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual(
|
||||
'Show transcripts (' + _.size(transcripts) + ')'
|
||||
);
|
||||
});
|
||||
|
||||
it('shows list of transcripts when clicked on show transcript button', function() {
|
||||
// Verify transcript container is hidden
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden')
|
||||
).toEqual(true);
|
||||
|
||||
// Verify initial button text
|
||||
expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual(
|
||||
'Show transcripts (' + _.size(transcripts) + ')'
|
||||
);
|
||||
videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click();
|
||||
|
||||
// Verify transcript container is not hidden
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden')
|
||||
).toEqual(false);
|
||||
|
||||
// Verify button text is changed.
|
||||
expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual(
|
||||
'Hide transcripts (' + _.size(transcripts) + ')'
|
||||
);
|
||||
});
|
||||
|
||||
it('hides list of transcripts when clicked on hide transcripts button', function() {
|
||||
// Click to show transcripts first.
|
||||
videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click();
|
||||
|
||||
// Verify button text.
|
||||
expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual(
|
||||
'Hide transcripts (' + _.size(transcripts) + ')'
|
||||
);
|
||||
|
||||
// Verify transcript container is not hidden
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden')
|
||||
).toEqual(false);
|
||||
|
||||
videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click();
|
||||
|
||||
// Verify button text is changed.
|
||||
expect(videoTranscriptsView.$el.find('.toggle-show-transcripts-button-text').html().trim()).toEqual(
|
||||
'Show transcripts (' + _.size(transcripts) + ')'
|
||||
);
|
||||
|
||||
// Verify transcript container is hidden
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.show-video-transcripts-wrapper').hasClass('hidden')
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
it('renders appropriate text when no transcript is available', function() {
|
||||
// Render view with no transcripts
|
||||
renderView({});
|
||||
|
||||
// Verify appropriate text is shown
|
||||
expect(
|
||||
videoTranscriptsView.$el.find('.transcripts-empty-text').html()
|
||||
).toEqual('No transcript available yet.');
|
||||
});
|
||||
|
||||
it('renders correct transcript attributes', function() {
|
||||
var $transcriptEl;
|
||||
// Show transcripts
|
||||
videoTranscriptsView.$el.find('.toggle-show-transcripts-button').click();
|
||||
expect(videoTranscriptsView.$el.find('.show-video-transcript-content').length).toEqual(
|
||||
_.size(transcripts)
|
||||
);
|
||||
|
||||
_.each(transcripts, function(langaugeText, languageCode) {
|
||||
$transcriptEl = $(videoTranscriptsView.$el.find('#show-video-transcript-content-' + languageCode));
|
||||
// Verify correct transcript title is set.
|
||||
expect($transcriptEl.find('.transcript-title').html()).toEqual(
|
||||
'Video client title n_' + languageCode + '.' + TRANSCRIPT_DOWNLOAD_FILE_FORMAT
|
||||
);
|
||||
// Verify transcript language dropdown has correct value set.
|
||||
expect($transcriptEl.find('.transcript-language-menu').val(), languageCode);
|
||||
|
||||
// Verify transcript actions are rendered correctly.
|
||||
verifyTranscriptActions($transcriptEl.find('.transcript-actions'), languageCode);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,10 +1,10 @@
|
||||
define(
|
||||
['underscore', 'gettext', 'js/utils/date_utils', 'js/views/baseview', 'common/js/components/views/feedback_prompt',
|
||||
'common/js/components/views/feedback_notification', 'js/views/video_thumbnail',
|
||||
'common/js/components/views/feedback_notification', 'js/views/video_thumbnail', 'js/views/video_transcripts',
|
||||
'common/js/components/utils/view_utils', 'edx-ui-toolkit/js/utils/html-utils',
|
||||
'text!templates/previous-video-upload.underscore'],
|
||||
function(_, gettext, DateUtils, BaseView, PromptView, NotificationView, VideoThumbnailView, ViewUtils, HtmlUtils,
|
||||
previousVideoUploadTemplate) {
|
||||
function(_, gettext, DateUtils, BaseView, PromptView, NotificationView, VideoThumbnailView, VideoTranscriptsView,
|
||||
ViewUtils, HtmlUtils, previousVideoUploadTemplate) {
|
||||
'use strict';
|
||||
|
||||
var PreviousVideoUploadView = BaseView.extend({
|
||||
@@ -20,6 +20,7 @@ define(
|
||||
this.template = HtmlUtils.template(previousVideoUploadTemplate);
|
||||
this.videoHandlerUrl = options.videoHandlerUrl;
|
||||
this.videoImageUploadEnabled = options.videoImageSettings.video_image_upload_enabled;
|
||||
this.isVideoTranscriptEnabled = options.isVideoTranscriptEnabled;
|
||||
|
||||
if (this.videoImageUploadEnabled) {
|
||||
this.videoThumbnailView = new VideoThumbnailView({
|
||||
@@ -29,11 +30,22 @@ define(
|
||||
videoImageSettings: options.videoImageSettings
|
||||
});
|
||||
}
|
||||
if (this.isVideoTranscriptEnabled) {
|
||||
this.videoTranscriptsView = new VideoTranscriptsView({
|
||||
transcripts: this.model.get('transcripts'),
|
||||
edxVideoID: this.model.get('edx_video_id'),
|
||||
clientVideoID: this.model.get('client_video_id'),
|
||||
transcriptAvailableLanguages: options.transcriptAvailableLanguages,
|
||||
videoSupportedFileFormats: options.videoSupportedFileFormats,
|
||||
videoTranscriptSettings: options.videoTranscriptSettings
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var renderedAttributes = {
|
||||
videoImageUploadEnabled: this.videoImageUploadEnabled,
|
||||
isVideoTranscriptEnabled: this.isVideoTranscriptEnabled,
|
||||
created: DateUtils.renderDate(this.model.get('created')),
|
||||
status: this.model.get('status')
|
||||
};
|
||||
@@ -47,6 +59,9 @@ define(
|
||||
if (this.videoImageUploadEnabled) {
|
||||
this.videoThumbnailView.setElement(this.$('.thumbnail-col')).render();
|
||||
}
|
||||
if (this.isVideoTranscriptEnabled) {
|
||||
this.videoTranscriptsView.setElement(this.$('.transcripts-col')).render();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
define(
|
||||
['jquery', 'underscore', 'backbone', 'js/views/baseview', 'js/views/previous_video_upload'],
|
||||
function($, _, Backbone, BaseView, PreviousVideoUploadView) {
|
||||
['jquery', 'underscore', 'backbone', 'js/views/baseview', 'edx-ui-toolkit/js/utils/html-utils',
|
||||
'js/views/previous_video_upload', 'text!templates/previous-video-upload-list.underscore'],
|
||||
function($, _, Backbone, BaseView, HtmlUtils, PreviousVideoUploadView, previousVideoUploadListTemplate) {
|
||||
'use strict';
|
||||
var PreviousVideoUploadListView = BaseView.extend({
|
||||
tagName: 'section',
|
||||
className: 'wrapper-assets',
|
||||
|
||||
initialize: function(options) {
|
||||
this.template = this.loadTemplate('previous-video-upload-list');
|
||||
this.template = HtmlUtils.template(previousVideoUploadListTemplate);
|
||||
this.encodingsDownloadUrl = options.encodingsDownloadUrl;
|
||||
this.videoImageUploadEnabled = options.videoImageSettings.video_image_upload_enabled;
|
||||
this.isVideoTranscriptEnabled = options.isVideoTranscriptEnabled;
|
||||
this.itemViews = this.collection.map(function(model) {
|
||||
return new PreviousVideoUploadView({
|
||||
videoImageUploadURL: options.videoImageUploadURL,
|
||||
defaultVideoImageURL: options.defaultVideoImageURL,
|
||||
videoHandlerUrl: options.videoHandlerUrl,
|
||||
videoImageSettings: options.videoImageSettings,
|
||||
model: model
|
||||
model: model,
|
||||
transcriptAvailableLanguages: options.transcriptAvailableLanguages,
|
||||
videoSupportedFileFormats: options.videoSupportedFileFormats,
|
||||
videoTranscriptSettings: options.videoTranscriptSettings,
|
||||
isVideoTranscriptEnabled: options.isVideoTranscriptEnabled
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -24,10 +30,16 @@ define(
|
||||
render: function() {
|
||||
var $el = this.$el,
|
||||
$tabBody;
|
||||
$el.html(this.template({
|
||||
encodingsDownloadUrl: this.encodingsDownloadUrl,
|
||||
videoImageUploadEnabled: this.videoImageUploadEnabled
|
||||
}));
|
||||
|
||||
HtmlUtils.setHtml(
|
||||
this.$el,
|
||||
this.template({
|
||||
encodingsDownloadUrl: this.encodingsDownloadUrl,
|
||||
videoImageUploadEnabled: this.videoImageUploadEnabled,
|
||||
isVideoTranscriptEnabled: this.isVideoTranscriptEnabled
|
||||
})
|
||||
);
|
||||
|
||||
$tabBody = $el.find('.js-table-body');
|
||||
_.each(this.itemViews, function(view) {
|
||||
$tabBody.append(view.render().$el);
|
||||
|
||||
97
cms/static/js/views/video_transcripts.js
Normal file
97
cms/static/js/views/video_transcripts.js
Normal file
@@ -0,0 +1,97 @@
|
||||
define(
|
||||
['underscore', 'gettext', 'js/views/baseview', 'edx-ui-toolkit/js/utils/html-utils',
|
||||
'edx-ui-toolkit/js/utils/string-utils', 'text!templates/video-transcripts.underscore'],
|
||||
function(_, gettext, BaseView, HtmlUtils, StringUtils, videoTranscriptsTemplate) {
|
||||
'use strict';
|
||||
|
||||
var VideoTranscriptsView = BaseView.extend({
|
||||
tagName: 'div',
|
||||
|
||||
events: {
|
||||
'click .toggle-show-transcripts-button': 'toggleShowTranscripts'
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.transcripts = options.transcripts;
|
||||
this.edxVideoID = options.edxVideoID;
|
||||
this.clientVideoID = options.clientVideoID;
|
||||
this.transcriptAvailableLanguages = options.transcriptAvailableLanguages;
|
||||
this.videoSupportedFileFormats = options.videoSupportedFileFormats;
|
||||
this.videoTranscriptSettings = options.videoTranscriptSettings;
|
||||
this.template = HtmlUtils.template(videoTranscriptsTemplate);
|
||||
},
|
||||
|
||||
/*
|
||||
Sorts object by value and returns a sorted array.
|
||||
*/
|
||||
sortByValue: function(itemObject) {
|
||||
var sortedArray = [];
|
||||
_.each(itemObject, function(value, key) {
|
||||
// Push each JSON Object entry in array by [value, key]
|
||||
sortedArray.push([value, key]);
|
||||
});
|
||||
return sortedArray.sort();
|
||||
},
|
||||
|
||||
/*
|
||||
Returns transcript title.
|
||||
*/
|
||||
getTranscriptClientTitle: function() {
|
||||
var clientTitle = this.clientVideoID;
|
||||
// Remove video file extension for transcript title.
|
||||
_.each(this.videoSupportedFileFormats, function(videoFormat) {
|
||||
clientTitle.replace(videoFormat, '');
|
||||
});
|
||||
return clientTitle.substring(0, 20);
|
||||
},
|
||||
|
||||
/*
|
||||
Toggles Show/Hide transcript button and transcripts container.
|
||||
*/
|
||||
toggleShowTranscripts: function() {
|
||||
var $transcriptsWrapperEl = this.$el.find('.show-video-transcripts-wrapper');
|
||||
|
||||
// Toggle show transcript wrapper.
|
||||
$transcriptsWrapperEl.toggleClass('hidden');
|
||||
|
||||
// Toggle button text.
|
||||
HtmlUtils.setHtml(
|
||||
this.$el.find('.toggle-show-transcripts-button-text'),
|
||||
StringUtils.interpolate(
|
||||
gettext('{toggleShowTranscriptText} transcripts ({totalTranscripts})'),
|
||||
{
|
||||
toggleShowTranscriptText: $transcriptsWrapperEl.hasClass('hidden') ? gettext('Show') : gettext('Hide'), // eslint-disable-line max-len
|
||||
totalTranscripts: _.size(this.transcripts)
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// Toggle icon class.
|
||||
if ($transcriptsWrapperEl.hasClass('hidden')) {
|
||||
this.$el.find('.toggle-show-transcripts-icon').removeClass('fa-caret-down').addClass('fa-caret-right'); // eslint-disable-line max-len
|
||||
} else {
|
||||
this.$el.find('.toggle-show-transcripts-icon').removeClass('fa-caret-right').addClass('fa-caret-down'); // eslint-disable-line max-len
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Renders transcripts view.
|
||||
*/
|
||||
render: function() {
|
||||
HtmlUtils.setHtml(
|
||||
this.$el,
|
||||
this.template({
|
||||
transcripts: this.transcripts,
|
||||
transcriptAvailableLanguages: this.sortByValue(this.transcriptAvailableLanguages),
|
||||
edxVideoID: this.edxVideoID,
|
||||
transcriptClientTitle: this.getTranscriptClientTitle(),
|
||||
transcriptDownloadFileFormat: this.videoTranscriptSettings.trancript_download_file_format
|
||||
})
|
||||
);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return VideoTranscriptsView;
|
||||
}
|
||||
);
|
||||
@@ -17,6 +17,34 @@
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
.button-link {
|
||||
background:none;
|
||||
border:none;
|
||||
padding:0;
|
||||
color: $ui-link-color;
|
||||
cursor:pointer
|
||||
}
|
||||
|
||||
.show-video-transcripts-wrapper {
|
||||
display: block;
|
||||
|
||||
.button-link {
|
||||
color: $ui-link-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.show-video-transcripts-wrapper.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.show-video-transcript-content {
|
||||
margin-top: ($baseline/2);
|
||||
.transcript-language-menu {
|
||||
display: block;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.course-video-settings-container {
|
||||
position: absolute;
|
||||
overflow: scroll;
|
||||
@@ -30,14 +58,6 @@
|
||||
-moz-box-shadow: -3px 0px 3px 0px rgba(153,153,153,0.3);
|
||||
box-shadow: -3px 0px 3px 0px rgba(153,153,153,0.3);
|
||||
|
||||
.button-link {
|
||||
background:none;
|
||||
border:none;
|
||||
padding:0;
|
||||
color: $ui-link-color;
|
||||
cursor:pointer
|
||||
}
|
||||
|
||||
.action-close-wrapper {
|
||||
.action-close-course-video-settings {
|
||||
width: 100%;
|
||||
@@ -416,6 +436,10 @@
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.transcripts-col {
|
||||
width: 17%;
|
||||
}
|
||||
|
||||
.thumbnail-col, .video-id-col {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
<div class="video-head-col video-col name-col"><%- gettext("Name") %></div>
|
||||
<div class="video-head-col video-col date-col"><%- gettext("Date Added") %></div>
|
||||
<div class="video-head-col video-col video-id-col"><%- gettext("Video ID") %></div>
|
||||
<% if (isVideoTranscriptEnabled) { %>
|
||||
<div class="video-head-col video-col transcripts-col"><%- gettext("Transcripts") %></div>
|
||||
<% } %>
|
||||
<div class="video-head-col video-col status-col"><%- gettext("Status") %></div>
|
||||
<div class="video-head-col video-col actions-col"><%- gettext("Action") %></div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
<div class="video-col name-col"><%- client_video_id %></div>
|
||||
<div class="video-col date-col"><%- created %></div>
|
||||
<div class="video-col video-id-col"><%- edx_video_id %></div>
|
||||
<% if (isVideoTranscriptEnabled) { %>
|
||||
<div class="video-col transcripts-col"></div>
|
||||
<% } %>
|
||||
<div class="video-col status-col"><%- status %></div>
|
||||
<div class="video-col actions-col">
|
||||
<ul class="actions-list">
|
||||
|
||||
36
cms/templates/js/video-transcripts.underscore
Normal file
36
cms/templates/js/video-transcripts.underscore
Normal file
@@ -0,0 +1,36 @@
|
||||
<div class='show-video-transcripts-container'>
|
||||
<% if (_.size(transcripts)) { %>
|
||||
<button class="button-link toggle-show-transcripts-button">
|
||||
<strong>
|
||||
<span class="icon fa fa-caret-right toggle-show-transcripts-icon" aria-hidden="true"></span>
|
||||
<span class="toggle-show-transcripts-button-text">
|
||||
<%- StringUtils.interpolate(gettext('Show transcripts ({totalTranscripts})'), {totalTranscripts: _.size(transcripts)})%>
|
||||
</span>
|
||||
</strong>
|
||||
</button>
|
||||
<% } else { %>
|
||||
<span class='transcripts-empty-text'><%- gettext('No transcript available yet.') %></span>
|
||||
<% }%>
|
||||
<div class='show-video-transcripts-wrapper hidden'>
|
||||
<% _.each(transcripts, function(transcriptLanguageText, transcriptLanguageCode){ %>
|
||||
<div id='show-video-transcript-content-<%- transcriptLanguageCode %>' class='show-video-transcript-content'>
|
||||
<strong class='transcript-title'><%- StringUtils.interpolate(gettext('{transcriptClientTitle}_{transcriptLanguageCode}.{fileExtension}'), {transcriptClientTitle: transcriptClientTitle, transcriptLanguageCode: transcriptLanguageCode, fileExtension: transcriptDownloadFileFormat}) %></strong>
|
||||
<select id='transcript-language-<%- transcriptLanguageCode %>' class='transcript-language-menu'>
|
||||
<option value=''>Select Language</option>
|
||||
<% _.each(transcriptAvailableLanguages, function(availableLanguage){ %>
|
||||
<option value='<%- availableLanguage[1] %>' <%- transcriptLanguageCode === availableLanguage[1] ? 'selected': '' %>><%- availableLanguage[0] %></option>
|
||||
<% }) %>
|
||||
</select>
|
||||
<div class='transcript-actions'>
|
||||
<a class="button-link download-transcript-button" href="#" data-edx-video-id="<%- edxVideoID %>" data-language-code="<%- transcriptLanguageCode %>">
|
||||
<%- gettext('Download') %>
|
||||
</a>
|
||||
<span class='transcript-actions-separator'> | </span>
|
||||
<button class="button-link upload-transcript-button" data-edx-video-id="<%- edxVideoID %>" data-language-code="<%- transcriptLanguageCode %>">
|
||||
<%- gettext('Upload') %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<% }) %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,7 +42,8 @@
|
||||
${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}
|
||||
${video_image_settings | n, dump_js_escaped_json},
|
||||
${transcript_available_languages | n, dump_js_escaped_json}
|
||||
);
|
||||
});
|
||||
</%block>
|
||||
|
||||
Reference in New Issue
Block a user