diff --git a/app/models/media_track.rb b/app/models/media_track.rb index b225a778556..1f60b1b3298 100644 --- a/app/models/media_track.rb +++ b/app/models/media_track.rb @@ -24,6 +24,8 @@ class MediaTrack < ActiveRecord::Base belongs_to :user belongs_to :media_object, touch: true belongs_to :attachment + belongs_to :master_content_tags, class_name: "MasterCourses::MasterContentTag", dependent: :destroy + before_validation :set_media_and_attachment before_save :convert_srt_to_wvtt before_create :mark_downstream_create_destroy diff --git a/lib/api/v1/master_courses.rb b/lib/api/v1/master_courses.rb index 7e3c7b02931..9092bde3c55 100644 --- a/lib/api/v1/master_courses.rb +++ b/lib/api/v1/master_courses.rb @@ -76,6 +76,7 @@ module Api::V1::MasterCourses html_url: url, locked: } + json[:locale] = asset.locale if asset.class_name == "MediaTrack" json[:exceptions] = exceptions[migration_id] || [] unless migration_id.nil? json end diff --git a/packages/canvas-media/src/closedCaptionLanguages.js b/packages/canvas-media/src/closedCaptionLanguages.js index 6e60dd9118a..a8135c4c78a 100644 --- a/packages/canvas-media/src/closedCaptionLanguages.js +++ b/packages/canvas-media/src/closedCaptionLanguages.js @@ -414,4 +414,12 @@ function sortedClosedCaptionLanguageList(userLocale) { return langlist } -export {sortedClosedCaptionLanguageList, closedCaptionLanguages as default} +function captionLanguageForLocale(locale) { + return closedCaptionLanguages.find(lang => lang.id === locale)?.label || locale +} + +export { + sortedClosedCaptionLanguageList, + captionLanguageForLocale, + closedCaptionLanguages as default, +} diff --git a/packages/canvas-media/src/index.js b/packages/canvas-media/src/index.js index f0044b15d6c..dbbd8171c91 100644 --- a/packages/canvas-media/src/index.js +++ b/packages/canvas-media/src/index.js @@ -26,7 +26,10 @@ import saveMediaRecording, { saveClosedCaptions, saveClosedCaptionsForAttachment, } from './saveMediaRecording' -import closedCaptionLanguages, {sortedClosedCaptionLanguageList} from './closedCaptionLanguages' +import closedCaptionLanguages, { + sortedClosedCaptionLanguageList, + captionLanguageForLocale, +} from './closedCaptionLanguages' import getTranslations from './getTranslations' import * as CONSTANTS from './shared/constants' @@ -45,6 +48,7 @@ export { saveClosedCaptionsForAttachment, closedCaptionLanguages, sortedClosedCaptionLanguageList, + captionLanguageForLocale, getTranslations, CONSTANTS, } diff --git a/spec/javascripts/jsx/blueprint_courses/components/UnsyncedChangesSpec.js b/spec/javascripts/jsx/blueprint_courses/components/UnsyncedChangesSpec.js index a1f2058609e..6602f54b7ce 100644 --- a/spec/javascripts/jsx/blueprint_courses/components/UnsyncedChangesSpec.js +++ b/spec/javascripts/jsx/blueprint_courses/components/UnsyncedChangesSpec.js @@ -49,6 +49,15 @@ const unsyncedChanges = [ html_url: '/4/pages/page-1', locked: false, }, + { + asset_id: '5', + asset_type: 'media_track', + asset_name: 'media.mp4', + change_type: 'created', + html_url: '/media_attachments/96/media_tracks', + locked: false, + locale: 'en', + }, ] const defaultProps = { @@ -100,9 +109,21 @@ test('renders the migration options component', () => { test('renders the changes properly', () => { const tree = mount(connect()) const changes = tree.find('tr[data-testid="bcs__unsynced-item"]') - equal(changes.length, 3) + equal(changes.length, 4) const locks = changes.find('IconBlueprintLockSolid') equal(locks.length, 1) const unlocks = changes.find('IconBlueprintSolid') - equal(unlocks.length, 2) + equal(unlocks.length, 3) +}) + +test('renders the media tracks properly', () => { + const tree = mount(connect()) + const changes = tree.find('tr[data-testid="bcs__unsynced-item"]') + equal(changes.length, 4) + const assetName = changes.findWhere( + node => node.name() === 'Text' && node.text() === 'media.mp4 (English)' + ) + equal(assetName.length, 1) + const assetType = changes.findWhere(node => node.name() === 'Text' && node.text() === 'Caption') + equal(assetType.length, 1) }) diff --git a/ui/features/blueprint_course_master/react/components/UnsyncedChange.js b/ui/features/blueprint_course_master/react/components/UnsyncedChange.js index 6b3b714a3c2..2f122533906 100644 --- a/ui/features/blueprint_course_master/react/components/UnsyncedChange.js +++ b/ui/features/blueprint_course_master/react/components/UnsyncedChange.js @@ -25,11 +25,13 @@ import {View} from '@instructure/ui-view' import {IconLock, IconUnlock} from '@canvas/blueprint-courses/react/components/BlueprintLocks' import propTypes from '@canvas/blueprint-courses/react/propTypes' import {itemTypeLabels, changeTypeLabels} from '@canvas/blueprint-courses/react/labels' +import {captionLanguageForLocale} from '@instructure/canvas-media' const UnsyncedChange = props => { - const {asset_type, asset_name, change_type, locked} = props.change + const {asset_type, asset_name, change_type, locked, locale} = props.change const changeLabel = changeTypeLabels[change_type] || change_type const typeLabel = itemTypeLabels[asset_type] || asset_type + const name = locale ? `${asset_name} (${captionLanguageForLocale(locale)})` : asset_name return ( @@ -40,7 +42,7 @@ const UnsyncedChange = props => { - {asset_name} + {name} diff --git a/ui/features/media_player_iframe_content/index.js b/ui/features/media_player_iframe_content/index.js index eb7dc76ade2..869e0ff55e8 100644 --- a/ui/features/media_player_iframe_content/index.js +++ b/ui/features/media_player_iframe_content/index.js @@ -23,7 +23,7 @@ import ReactDOM from 'react-dom' import {parse} from 'url' import ready from '@instructure/ready' import CanvasMediaPlayer from '@canvas/canvas-media-player' -import {closedCaptionLanguages} from '@instructure/canvas-media' +import {captionLanguageForLocale} from '@instructure/canvas-media' const isStandalone = () => { return !window.frameElement && window.location === window.top.location @@ -84,7 +84,7 @@ ready(() => { return { id: track.id, src: track.url, - label: closedCaptionLanguages.find(lang => lang.id === track.locale)?.label || track.locale, + label: captionLanguageForLocale(track.locale), type: track.kind, language: track.locale, } diff --git a/ui/shared/blueprint-courses/react/labels.js b/ui/shared/blueprint-courses/react/labels.js index f537012eced..ae3f0eb4e76 100644 --- a/ui/shared/blueprint-courses/react/labels.js +++ b/ui/shared/blueprint-courses/react/labels.js @@ -21,59 +21,62 @@ import {useScope as useI18nScope} from '@canvas/i18n' const I18n = useI18nScope('blueprint_settings_labels') const itemTypeLabels = { - get assignment() { - return I18n.t('Assignment') - }, - get assignment_group() { - return I18n.t('Assignment Group') - }, - get quiz() { - return I18n.t('Quiz') - }, - get discussion_topic() { - return I18n.t('Discussion') - }, - get wiki_page() { - return I18n.t('Page') - }, - get attachment() { - return I18n.t('File') - }, - get context_module() { - return I18n.t('Module') - }, get announcement() { return I18n.t('Announcement') }, get assessment_question_bank() { return I18n.t('Question Bank') }, + get assignment() { + return I18n.t('Assignment') + }, + get assignment_group() { + return I18n.t('Assignment Group') + }, + get attachment() { + return I18n.t('File') + }, get calendar_event() { return I18n.t('Event') }, + get context_external_tool() { + return I18n.t('External Tool') + }, + get context_module() { + return I18n.t('Module') + }, + get course_pace() { + return I18n.t('Course Pace') + }, + get discussion_topic() { + return I18n.t('Discussion') + }, + get folder() { + return I18n.t('Folder') + }, get learning_outcome() { return I18n.t('Outcome') }, get learning_outcome_group() { return I18n.t('Outcome Group') }, + get media_track() { + return I18n.t('Caption') + }, + get quiz() { + return I18n.t('Quiz') + }, get rubric() { return I18n.t('Rubric') }, - get context_external_tool() { - return I18n.t('External Tool') - }, - get folder() { - return I18n.t('Folder') - }, - get syllabus() { - return I18n.t('Syllabus') - }, get settings() { return I18n.t('Settings') }, - get course_pace() { - return I18n.t('Course Pace') + get syllabus() { + return I18n.t('Syllabus') + }, + get wiki_page() { + return I18n.t('Page') }, } @@ -81,6 +84,12 @@ const itemTypeLabelPlurals = { get assignment() { return I18n.t('Assignments') }, + get attachment() { + return I18n.t('Files') + }, + get course_pace() { + return I18n.t('Course Pace') + }, get quiz() { return I18n.t('Quizzes') }, @@ -90,12 +99,6 @@ const itemTypeLabelPlurals = { get wiki_page() { return I18n.t('Pages') }, - get attachment() { - return I18n.t('Files') - }, - get course_pace() { - return I18n.t('Course Pace') - }, } const changeTypeLabels = { @@ -114,24 +117,24 @@ const changeTypeLabels = { } const exceptionTypeLabels = { - get points() { - return I18n.t('Points changed exceptions:') + get availability_dates() { + return I18n.t('Availability Dates changed exceptions:') }, get content() { return I18n.t('Content changed exceptions:') }, + get deleted() { + return I18n.t('Deleted content exceptions:') + }, get due_dates() { return I18n.t('Due Dates changed exceptions:') }, - get availability_dates() { - return I18n.t('Availability Dates changed exceptions:') + get points() { + return I18n.t('Points changed exceptions:') }, get settings() { return I18n.t('Settings changed exceptions:') }, - get deleted() { - return I18n.t('Deleted content exceptions:') - }, } const lockTypeLabel = { @@ -144,21 +147,21 @@ const lockTypeLabel = { } const lockLabels = { + get availability_dates() { + return I18n.t('Availability Dates') + }, get content() { return I18n.t('Content') }, + get due_dates() { + return I18n.t('Due Dates') + }, get points() { return I18n.t('Points') }, get settings() { return I18n.t('Settings') }, - get due_dates() { - return I18n.t('Due Dates') - }, - get availability_dates() { - return I18n.t('Availability Dates') - }, } export {