diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/files/ContentRenderer.vue b/contentcuration/contentcuration/frontend/channelEdit/views/files/ContentRenderer.vue index 27a96905e2..133a942e0a 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/files/ContentRenderer.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/views/files/ContentRenderer.vue @@ -112,7 +112,7 @@ ); }, isVideo() { - return this.file.file_format === 'mp4'; + return this.file.file_format === 'mp4' || this.file.file_format === 'webm'; }, isAudio() { return this.file.file_format === 'mp3'; diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/filePreview.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/filePreview.spec.js index fc608060b1..f7a31666d9 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/filePreview.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/filePreview.spec.js @@ -39,6 +39,7 @@ describe('filePreview', () => { expect(wrapper.vm.isPreviewable).toBe(previewable); } test('mp4', true); + test('webm', true); test('pdf', true); test('mp3', true); test('epub', true); @@ -55,5 +56,10 @@ describe('filePreview', () => { wrapper.setData({ fullscreen: true }); wrapper.find('[data-test="closefullscreen"]').trigger('click'); expect(wrapper.vm.fullscreen).toBe(false); + + let wrapperWebm = makeWrapper({ file_format: 'webm' }); + wrapperWebm.setData({ fullscreen: true }); + wrapperWebm.find('[data-test="closefullscreen"]').trigger('click'); + expect(wrapperWebm.vm.fullscreen).toBe(false); }); }); diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/thumbnailGenerator.spec.js b/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/thumbnailGenerator.spec.js index e40a8c11ff..6a9d0eef3b 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/thumbnailGenerator.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/views/files/__tests__/thumbnailGenerator.spec.js @@ -23,6 +23,11 @@ describe('thumbnailGenerator', () => { videoWrapper.vm.generate(); expect(generateVideoThumbnail).toHaveBeenCalled(); + let videoWrapperWebm = makeWrapper('test.webm'); + videoWrapperWebm.setMethods({ fileExists, generateVideoThumbnail }); + videoWrapperWebm.vm.generate(); + expect(generateVideoThumbnail).toHaveBeenCalled(); + let generateAudioThumbnail = jest.fn(); let audioWrapper = makeWrapper('test.mp3'); audioWrapper.setMethods({ generateAudioThumbnail }); diff --git a/contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue b/contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue index d920ac4621..a52d06a749 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue @@ -63,7 +63,7 @@ return this.width / ASPECT_RATIO; }, isVideo() { - return this.filePath.endsWith('mp4'); + return this.filePath.endsWith('mp4') || this.filePath.endsWith('webm'); }, isAudio() { return this.filePath.endsWith('mp3'); diff --git a/contentcuration/contentcuration/frontend/shared/leUtils/FormatPresets.js b/contentcuration/contentcuration/frontend/shared/leUtils/FormatPresets.js index 7524b7368f..76da1e6f7a 100644 --- a/contentcuration/contentcuration/frontend/shared/leUtils/FormatPresets.js +++ b/contentcuration/contentcuration/frontend/shared/leUtils/FormatPresets.js @@ -125,7 +125,7 @@ const FormatPresetsMap = new Map([ order: 4, kind_id: 'exercise', allowed_formats: ['svg', 'json', 'graphie'], - associated_mimetypes: ['application/json', '.graphie', 'image/svg'], + associated_mimetypes: ['.graphie', 'image/svg', 'application/json'], }, ], [ @@ -141,7 +141,7 @@ const FormatPresetsMap = new Map([ order: 3, kind_id: 'exercise', allowed_formats: ['png', 'jpg', 'jpeg', 'gif', 'svg'], - associated_mimetypes: ['image/jpeg', 'image/svg', 'image/gif', 'image/png'], + associated_mimetypes: ['image/jpeg', 'image/png', 'image/gif', 'image/svg'], }, ], [ @@ -204,8 +204,8 @@ const FormatPresetsMap = new Map([ display: true, order: 1, kind_id: 'video', - allowed_formats: ['mp4'], - associated_mimetypes: ['video/mp4'], + allowed_formats: ['mp4', 'webm'], + associated_mimetypes: ['video/webm', 'video/mp4'], }, ], [ @@ -268,8 +268,8 @@ const FormatPresetsMap = new Map([ display: true, order: 2, kind_id: 'video', - allowed_formats: ['mp4'], - associated_mimetypes: ['video/mp4'], + allowed_formats: ['mp4', 'webm'], + associated_mimetypes: ['video/webm', 'video/mp4'], }, ], [ @@ -348,8 +348,8 @@ const FormatPresetsMap = new Map([ display: false, order: 3, kind_id: 'video', - allowed_formats: ['mp4'], - associated_mimetypes: ['video/mp4'], + allowed_formats: ['mp4', 'webm'], + associated_mimetypes: ['video/webm', 'video/mp4'], }, ], [ diff --git a/contentcuration/contentcuration/frontend/shared/leUtils/Languages.js b/contentcuration/contentcuration/frontend/shared/leUtils/Languages.js index e853a12192..b45b4f9594 100644 --- a/contentcuration/contentcuration/frontend/shared/leUtils/Languages.js +++ b/contentcuration/contentcuration/frontend/shared/leUtils/Languages.js @@ -154,6 +154,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'brh', + { + id: 'brh', + lang_code: 'brh', + lang_subcode: null, + readable_name: 'Brahui', + native_name: 'Brahui', + lang_direction: 'ltr', + }, + ], [ 'en-GB', { @@ -176,6 +187,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'bxk', + { + id: 'bxk', + lang_code: 'bxk', + lang_subcode: null, + readable_name: 'Bukusu', + native_name: 'Bukusu', + lang_direction: 'ltr', + }, + ], [ 'ca', { @@ -231,6 +253,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'thl', + { + id: 'thl', + lang_code: 'thl', + lang_subcode: null, + readable_name: 'Dangaura Tharu', + native_name: 'Dangaura Tharu', + lang_direction: 'ltr', + }, + ], [ 'da', { @@ -275,6 +308,28 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'dty', + { + id: 'dty', + lang_code: 'dty', + lang_subcode: null, + readable_name: 'Dotyali', + native_name: 'Dotyali', + lang_direction: 'ltr', + }, + ], + [ + 'taj', + { + id: 'taj', + lang_code: 'taj', + lang_subcode: null, + readable_name: 'Eastern Tamang', + native_name: 'Eastern Tamang', + lang_direction: 'ltr', + }, + ], [ 'efi', { @@ -297,6 +352,28 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'guz', + { + id: 'guz', + lang_code: 'guz', + lang_subcode: null, + readable_name: 'Gusii', + native_name: 'Ekegusii', + lang_direction: 'ltr', + }, + ], + [ + 'enq', + { + id: 'enq', + lang_code: 'enq', + lang_subcode: null, + readable_name: 'Enga', + native_name: 'Enga', + lang_direction: 'ltr', + }, + ], [ 'en', { @@ -649,6 +726,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'kak', + { + id: 'kak', + lang_code: 'kak', + lang_subcode: null, + readable_name: 'Kalanguya', + native_name: 'Kalanguya', + lang_direction: 'ltr', + }, + ], [ 'kr', { @@ -693,6 +781,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'kam', + { + id: 'kam', + lang_code: 'kam', + lang_subcode: null, + readable_name: 'Kamba (Kenya)', + native_name: 'Kikamba', + lang_direction: 'ltr', + }, + ], [ 'sw', { @@ -759,6 +858,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'bma', + { + id: 'bma', + lang_code: 'bma', + lang_subcode: null, + readable_name: 'Lame', + native_name: 'Lame', + lang_direction: 'ltr', + }, + ], [ 'li', { @@ -957,6 +1067,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'pbu', + { + id: 'pbu', + lang_code: 'pbu', + lang_subcode: null, + readable_name: 'Northern Pashto', + native_name: 'Northern Pashto', + lang_direction: 'ltr', + }, + ], [ 'oc', { @@ -1144,6 +1265,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'srr', + { + id: 'srr', + lang_code: 'srr', + lang_subcode: null, + readable_name: 'Serer', + native_name: 'Seereer', + lang_direction: 'ltr', + }, + ], [ 'nso', { @@ -1254,6 +1386,28 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'bcc', + { + id: 'bcc', + lang_code: 'bcc', + lang_subcode: null, + readable_name: 'Southern Balochi', + native_name: 'Southern Balochi', + lang_direction: 'ltr', + }, + ], + [ + 'pbt', + { + id: 'pbt', + lang_code: 'pbt', + lang_subcode: null, + readable_name: 'Southern Pashto', + native_name: 'Southern Pashto', + lang_direction: 'ltr', + }, + ], [ 'sv-SE', { @@ -1299,6 +1453,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'tpi', + { + id: 'tpi', + lang_code: 'tpi', + lang_subcode: null, + readable_name: 'Tok Pisin', + native_name: 'Tok Pisin', + lang_direction: 'ltr', + }, + ], [ 've', { @@ -1453,6 +1618,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'yao', + { + id: 'yao', + lang_code: 'yao', + lang_subcode: null, + readable_name: 'Yao', + native_name: 'Yao', + lang_direction: 'ltr', + }, + ], [ 'yo', { @@ -1607,6 +1783,17 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'tum', + { + id: 'tum', + lang_code: 'tum', + lang_subcode: null, + readable_name: 'Tumbuka', + native_name: 'chiTumbuka', + lang_direction: 'ltr', + }, + ], [ 'co', { @@ -2309,6 +2496,17 @@ const LanguagesMap = new Map([ lang_direction: 'rtl', }, ], + [ + 'awa', + { + id: 'awa', + lang_code: 'awa', + lang_subcode: null, + readable_name: 'Awadhi', + native_name: '\u0905\u0935\u0927\u0940', + lang_direction: 'ltr', + }, + ], [ 'ks', { @@ -2321,6 +2519,29 @@ const LanguagesMap = new Map([ lang_direction: 'ltr', }, ], + [ + 'mai', + { + id: 'mai', + lang_code: 'mai', + lang_subcode: null, + readable_name: 'Maithili', + native_name: '\u0925\u093f\u0932\u0940, \u09ae\u09c8\u09a5\u09bf\u09b2\u09c0', + lang_direction: 'ltr', + }, + ], + [ + 'new', + { + id: 'new', + lang_code: 'new', + lang_subcode: null, + readable_name: 'Newari', + native_name: + '\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, \u0928\u0947\u0935\u093e\u0903 \u092d\u093e\u092f\u094d', + lang_direction: 'ltr', + }, + ], [ 'ne', { @@ -2798,19 +3019,26 @@ export const LanguagesNames = { ID: 'id', SU: 'su', BI: 'bi', + BRH: 'brh', EN_GB: 'en-GB', BUG: 'bug', + BXK: 'bxk', CA: 'ca', CEB: 'ceb', CH: 'ch', CHO: 'cho', CY: 'cy', + THL: 'thl', DA: 'da', SE: 'se', DE: 'de', NV: 'nv', + DTY: 'dty', + TAJ: 'taj', EFI: 'efi', NA: 'na', + GUZ: 'guz', + ENQ: 'enq', EN: 'en', ES: 'es', ES_AR: 'es-AR', @@ -2843,16 +3071,19 @@ export const LanguagesNames = { IT: 'it', IK: 'ik', MH: 'mh', + KAK: 'kak', KR: 'kr', KW: 'kw', KG: 'kg', KON: 'kon', + KAM: 'kam', SW: 'sw', SWA: 'swa', HT: 'ht', KJ: 'kj', KU: 'ku', LKT: 'lkt', + BMA: 'bma', LI: 'li', LN: 'ln', LIN: 'lin', @@ -2871,6 +3102,7 @@ export const LanguagesNames = { NO: 'no', NB: 'nb', NN: 'nn', + PBU: 'pbu', OC: 'oc', LWG: 'lwg', IE: 'ie', @@ -2888,6 +3120,7 @@ export const LanguagesNames = { NYN: 'nyn', ZA: 'za', SCO: 'sco', + SRR: 'srr', NSO: 'nso', ST: 'st', SOT: 'sot', @@ -2898,10 +3131,13 @@ export const LanguagesNames = { SID: 'sid', SOM: 'som', SO: 'so', + BCC: 'bcc', + PBT: 'pbt', SV_SE: 'sv-SE', SV_FI: 'sv-FI', BE_TARA: 'be-tara', VI: 'vi', + TPI: 'tpi', VE: 've', TW: 'tw', TK: 'tk', @@ -2916,6 +3152,7 @@ export const LanguagesNames = { WO: 'wo', WOL: 'wol', TS: 'ts', + YAO: 'yao', YO: 'yo', YOR: 'yor', AE: 'ae', @@ -2930,6 +3167,7 @@ export const LanguagesNames = { NY: 'ny', SN: 'sn', SNA: 'sna', + TUM: 'tum', CO: 'co', ET: 'et', EU: 'eu', @@ -2993,7 +3231,10 @@ export const LanguagesNames = { FA: 'fa', PS: 'ps', DV: 'dv', + AWA: 'awa', KS: 'ks', + MAI: 'mai', + NEW: 'new', NE: 'ne', NE_NP: 'ne-NP', PI: 'pi', diff --git a/contentcuration/contentcuration/frontend/shared/mixins.js b/contentcuration/contentcuration/frontend/shared/mixins.js index 8d497fe2ba..f7d4575e3a 100644 --- a/contentcuration/contentcuration/frontend/shared/mixins.js +++ b/contentcuration/contentcuration/frontend/shared/mixins.js @@ -111,6 +111,7 @@ export const constantStrings = createTranslator('ConstantStrings', { true_false: 'True/False', unknown_question: 'Unknown question type', mp4: 'MP4 video', + webm: 'WEBM video', vtt: 'VTT caption', mp3: 'MP3 audio', pdf: 'PDF document', diff --git a/contentcuration/contentcuration/frontend/shared/views/files/__tests__/uploader.spec.js b/contentcuration/contentcuration/frontend/shared/views/files/__tests__/uploader.spec.js index c076b59f4c..542a691d3e 100644 --- a/contentcuration/contentcuration/frontend/shared/views/files/__tests__/uploader.spec.js +++ b/contentcuration/contentcuration/frontend/shared/views/files/__tests__/uploader.spec.js @@ -78,9 +78,10 @@ describe('uploader', () => { let testFiles = [ { name: 'file.wut', size: 10 }, { name: 'file.mp4', size: 10 }, + { name: 'file.webm', size: 10 }, ]; let returned = wrapper.vm.validateFiles(testFiles); - expect(returned).toHaveLength(1); + expect(returned).toHaveLength(2); expect(returned[0].name).toBe('file.mp4'); expect(wrapper.vm.unsupportedFiles).toHaveLength(1); expect(wrapper.vm.unsupportedFiles[0].name).toBe('file.wut'); diff --git a/contentcuration/contentcuration/migrations/0126_auto_20210219_2314.py b/contentcuration/contentcuration/migrations/0126_auto_20210219_2314.py new file mode 100644 index 0000000000..82ee59c7c3 --- /dev/null +++ b/contentcuration/contentcuration/migrations/0126_auto_20210219_2314.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2021-02-19 23:14 +from __future__ import unicode_literals + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contentcuration', '0125_user_feature_flags_default'), + ] + + operations = [ + migrations.AlterField( + model_name='fileformat', + name='extension', + field=models.CharField(choices=[('mp4', 'MP4 Video'), ('webm', 'WEBM Video'), ('vtt', 'VTT Subtitle'), ('mp3', 'MP3 Audio'), ('pdf', 'PDF Document'), ('jpg', 'JPG Image'), ('jpeg', 'JPEG Image'), ('png', 'PNG Image'), ('gif', 'GIF Image'), ('json', 'JSON'), ('svg', 'SVG Image'), ('perseus', 'Perseus Exercise'), ('graphie', 'Graphie Exercise'), ('zip', 'HTML5 Zip'), ('h5p', 'H5P'), ('epub', 'ePub Document')], max_length=40, primary_key=True, serialize=False), + ), + ] diff --git a/contentcuration/contentcuration/migrations/0127_auto_20210504_1744.py b/contentcuration/contentcuration/migrations/0127_auto_20210504_1744.py new file mode 100644 index 0000000000..ffd63ab8b0 --- /dev/null +++ b/contentcuration/contentcuration/migrations/0127_auto_20210504_1744.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2021-05-04 17:44 +from __future__ import unicode_literals + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contentcuration', '0126_auto_20210219_2314'), + ] + + operations = [ + migrations.AlterField( + model_name='formatpreset', + name='id', + field=models.CharField(choices=[('high_res_video', 'High Resolution'), ('low_res_video', 'Low Resolution'), ('video_thumbnail', 'Thumbnail'), ('video_subtitle', 'Subtitle'), ('video_dependency', 'Video (dependency)'), ('audio', 'Audio'), ('audio_thumbnail', 'Thumbnail'), ('audio_dependency', 'audio (dependency)'), ('document', 'Document'), ('epub', 'ePub Document'), ('document_thumbnail', 'Thumbnail'), ('exercise', 'Exercise'), ('exercise_thumbnail', 'Thumbnail'), ('exercise_image', 'Exercise Image'), ('exercise_graphie', 'Exercise Graphie'), ('channel_thumbnail', 'Channel Thumbnail'), ('topic_thumbnail', 'Thumbnail'), ('html5_zip', 'HTML5 Zip'), ('html5_dependency', 'HTML5 Dependency (Zip format)'), ('html5_thumbnail', 'HTML5 Thumbnail'), ('h5p', 'H5P Zip'), ('h5p_thumbnail', 'H5P Thumbnail'), ('slideshow_image', 'Slideshow Image'), ('slideshow_thumbnail', 'Slideshow Thumbnail'), ('slideshow_manifest', 'Slideshow Manifest')], max_length=150, primary_key=True, serialize=False), + ), + ] diff --git a/contentcuration/contentcuration/tests/test_createchannel.py b/contentcuration/contentcuration/tests/test_createchannel.py index b6602779c4..bf24a7f2b5 100644 --- a/contentcuration/contentcuration/tests/test_createchannel.py +++ b/contentcuration/contentcuration/tests/test_createchannel.py @@ -1,11 +1,10 @@ from __future__ import absolute_import -import base64 import json - -import requests from builtins import range from builtins import str + +import requests from django.core.urlresolvers import reverse_lazy from .base import BaseTestCase @@ -64,8 +63,9 @@ def setUp(self): self.license = cc.License.objects.all()[0] self.fileinfo_audio = create_studio_file("abc", preset='audio', ext='mp3') self.fileinfo_video = create_studio_file("def", preset='high_res_video', ext='mp4') - self.fileinfo_document = create_studio_file("ghi", preset='document', ext='pdf') - self.fileinfo_exercise = create_studio_file("jkl", preset='exercise', ext='perseus') + self.fileinfo_video_webm = create_studio_file("ghi", preset='high_res_video', ext='webm') + self.fileinfo_document = create_studio_file("jkl", preset='document', ext='pdf') + self.fileinfo_exercise = create_studio_file("mno", preset='exercise', ext='perseus') def create_channel(self): create_channel_url = str(reverse_lazy('api_create_channel')) diff --git a/contentcuration/kolibri_content/migrations/0010_auto_20210202_0604.py b/contentcuration/kolibri_content/migrations/0010_auto_20210202_0604.py new file mode 100644 index 0000000000..7800d2c5e9 --- /dev/null +++ b/contentcuration/kolibri_content/migrations/0010_auto_20210202_0604.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2021-02-02 06:04 +from __future__ import unicode_literals + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + ('content', '0009_contentnode_options'), + ] + + operations = [ + migrations.AlterField( + model_name='file', + name='extension', + field=models.CharField(blank=True, choices=[('mp4', 'MP4 Video'), ('webm', 'WEBM Video'), ('vtt', 'VTT Subtitle'), ('mp3', 'MP3 Audio'), ('pdf', 'PDF Document'), ('jpg', 'JPG Image'), ('jpeg', 'JPEG Image'), ('png', 'PNG Image'), ('gif', 'GIF Image'), ('json', 'JSON'), ('svg', 'SVG Image'), ('perseus', 'Perseus Exercise'), ('graphie', 'Graphie Exercise'), ('zip', 'HTML5 Zip'), ('h5p', 'H5P'), ('epub', 'ePub Document')], max_length=40), + ), + migrations.AlterField( + model_name='localfile', + name='extension', + field=models.CharField(blank=True, choices=[('mp4', 'MP4 Video'), ('webm', 'WEBM Video'), ('vtt', 'VTT Subtitle'), ('mp3', 'MP3 Audio'), ('pdf', 'PDF Document'), ('jpg', 'JPG Image'), ('jpeg', 'JPEG Image'), ('png', 'PNG Image'), ('gif', 'GIF Image'), ('json', 'JSON'), ('svg', 'SVG Image'), ('perseus', 'Perseus Exercise'), ('graphie', 'Graphie Exercise'), ('zip', 'HTML5 Zip'), ('h5p', 'H5P'), ('epub', 'ePub Document')], max_length=40), + ), + ] diff --git a/contentcuration/kolibri_content/migrations/0011_auto_20210504_1744.py b/contentcuration/kolibri_content/migrations/0011_auto_20210504_1744.py new file mode 100644 index 0000000000..feddf0b1e4 --- /dev/null +++ b/contentcuration/kolibri_content/migrations/0011_auto_20210504_1744.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2021-05-04 17:44 +from __future__ import unicode_literals + +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + + dependencies = [ + ('content', '0010_auto_20210202_0604'), + ] + + operations = [ + migrations.AlterField( + model_name='file', + name='preset', + field=models.CharField(blank=True, choices=[('high_res_video', 'High Resolution'), ('low_res_video', 'Low Resolution'), ('video_thumbnail', 'Thumbnail'), ('video_subtitle', 'Subtitle'), ('video_dependency', 'Video (dependency)'), ('audio', 'Audio'), ('audio_thumbnail', 'Thumbnail'), ('audio_dependency', 'audio (dependency)'), ('document', 'Document'), ('epub', 'ePub Document'), ('document_thumbnail', 'Thumbnail'), ('exercise', 'Exercise'), ('exercise_thumbnail', 'Thumbnail'), ('exercise_image', 'Exercise Image'), ('exercise_graphie', 'Exercise Graphie'), ('channel_thumbnail', 'Channel Thumbnail'), ('topic_thumbnail', 'Thumbnail'), ('html5_zip', 'HTML5 Zip'), ('html5_dependency', 'HTML5 Dependency (Zip format)'), ('html5_thumbnail', 'HTML5 Thumbnail'), ('h5p', 'H5P Zip'), ('h5p_thumbnail', 'H5P Thumbnail'), ('slideshow_image', 'Slideshow Image'), ('slideshow_thumbnail', 'Slideshow Thumbnail'), ('slideshow_manifest', 'Slideshow Manifest')], max_length=150), + ), + ] diff --git a/contentcuration/locale/ar/LC_MESSAGES/contentcuration-messages.json b/contentcuration/locale/ar/LC_MESSAGES/contentcuration-messages.json index 09c2562a77..30d90a43ba 100644 --- a/contentcuration/locale/ar/LC_MESSAGES/contentcuration-messages.json +++ b/contentcuration/locale/ar/LC_MESSAGES/contentcuration-messages.json @@ -466,6 +466,7 @@ "ConstantStrings.m_of_n_description": "يجب على المتعلم أن يجيب على M سؤالاً M بشكل صحيح من آخر N سؤال تمت الإجابة عليها. على سبيل المثال، '3 من أصل 5' يعني أنه يجب على المتعلمين الإجابة على 3 أسئلة بشكل صحيح من الإجابات الخمس الأخيرة.", "ConstantStrings.mp3": "ملف صوتي MP3", "ConstantStrings.mp4": "فيديو MP4", + "ConstantStrings.webm": "فيديو WEBM", "ConstantStrings.multiple_selection": "خيارات متعددة", "ConstantStrings.nthCopy": "نسخ {n, number, integer} من {title}", "ConstantStrings.num_correct_in_a_row_10": "١٠ على التوالي", diff --git a/contentcuration/locale/es_ES/LC_MESSAGES/contentcuration-messages.json b/contentcuration/locale/es_ES/LC_MESSAGES/contentcuration-messages.json index de399b6254..46f0c26085 100644 --- a/contentcuration/locale/es_ES/LC_MESSAGES/contentcuration-messages.json +++ b/contentcuration/locale/es_ES/LC_MESSAGES/contentcuration-messages.json @@ -466,6 +466,7 @@ "ConstantStrings.m_of_n_description": "Estudiantes tienen que responder correctamente a M preguntas de las últimas N. Por ejemplo, '3 de 5' significa que los estudiantes necesitan responder correctamente a 3 preguntas de las últimas 5.", "ConstantStrings.mp3": "Audio MP3", "ConstantStrings.mp4": "Video MP4", + "ConstantStrings.webm": "Video WEBM", "ConstantStrings.multiple_selection": "Selección múltiple", "ConstantStrings.nthCopy": "Copia {n, number, integer} de {title}", "ConstantStrings.num_correct_in_a_row_10": "10 consecutivas", diff --git a/contentcuration/locale/fr_FR/LC_MESSAGES/contentcuration-messages.json b/contentcuration/locale/fr_FR/LC_MESSAGES/contentcuration-messages.json index 878eef56ee..6e1a577fea 100644 --- a/contentcuration/locale/fr_FR/LC_MESSAGES/contentcuration-messages.json +++ b/contentcuration/locale/fr_FR/LC_MESSAGES/contentcuration-messages.json @@ -466,6 +466,7 @@ "ConstantStrings.m_of_n_description": "Sur les N dernières questions répondues, l'apprenant doit répondre correctement à M questions. Par exemple, \"3 sur 5\" signifie que l'apprenant doit répondre correctement à 3 questions sur les 5 dernières répondues.", "ConstantStrings.mp3": "Audio MP3", "ConstantStrings.mp4": "Vidéo MP4", + "ConstantStrings.webm": "Vidéo WEBM", "ConstantStrings.multiple_selection": "Choix multiple", "ConstantStrings.nthCopy": "Copier {n, number, integer} du {titre}", "ConstantStrings.num_correct_in_a_row_10": "10 d'affilée", diff --git a/contentcuration/locale/hi_IN/LC_MESSAGES/contentcuration-messages.json b/contentcuration/locale/hi_IN/LC_MESSAGES/contentcuration-messages.json index 59ab7ba0d1..e54c7242b6 100644 --- a/contentcuration/locale/hi_IN/LC_MESSAGES/contentcuration-messages.json +++ b/contentcuration/locale/hi_IN/LC_MESSAGES/contentcuration-messages.json @@ -466,6 +466,7 @@ "ConstantStrings.m_of_n_description": "Learner must answer M questions correctly from the last N answered questions. For example, ‘3 of 5’ means learners must answer 3 questions correctly out of the 5 most recently answered.", "ConstantStrings.mp3": "MP3 audio", "ConstantStrings.mp4": "MP4 video", + "ConstantStrings.webm": "WEBM video", "ConstantStrings.multiple_selection": "Multiple choice", "ConstantStrings.nthCopy": "Copy {n, number, integer} of {title}", "ConstantStrings.num_correct_in_a_row_10": "10 in a row", diff --git a/contentcuration/locale/pt_BR/LC_MESSAGES/contentcuration-messages.json b/contentcuration/locale/pt_BR/LC_MESSAGES/contentcuration-messages.json index 589efc0df4..45b2a8bfee 100644 --- a/contentcuration/locale/pt_BR/LC_MESSAGES/contentcuration-messages.json +++ b/contentcuration/locale/pt_BR/LC_MESSAGES/contentcuration-messages.json @@ -466,6 +466,7 @@ "ConstantStrings.m_of_n_description": "Learner must answer M questions correctly from the last N answered questions. For example, ‘3 of 5’ means learners must answer 3 questions correctly out of the 5 most recently answered.", "ConstantStrings.mp3": "MP3 audio", "ConstantStrings.mp4": "MP4 video", + "ConstantStrings.webm": "WEBM video", "ConstantStrings.multiple_selection": "Multiple choice", "ConstantStrings.nthCopy": "Copy {n, number, integer} of {title}", "ConstantStrings.num_correct_in_a_row_10": "10 in a row", diff --git a/requirements-docs.txt b/requirements-docs.txt index f1957a4cbc..221ebc84f4 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -4,92 +4,35 @@ # # pip-compile requirements-docs.in # -alabaster==0.7.12 - # via sphinx -argh==0.26.2 - # via sphinx-autobuild -babel==2.8.0 - # via - # sphinx - # sphinx-intl -certifi==2019.11.28 - # via - # -c requirements.txt - # requests -chardet==3.0.4 - # via - # -c requirements.txt - # requests -click==7.1.2 - # via sphinx-intl -docutils==0.15.2 - # via - # -c requirements.txt - # sphinx -idna==2.8 - # via - # -c requirements.txt - # requests -imagesize==1.2.0 - # via sphinx -jinja2==2.11.3 - # via sphinx -livereload==2.6.3 - # via sphinx-autobuild -markupsafe==1.1.1 - # via jinja2 -pathtools==0.1.2 - # via - # sphinx-autobuild - # watchdog -port_for==0.3.1 - # via sphinx-autobuild -pygments==2.7.4 - # via sphinx -pytz==2019.3 - # via - # -c requirements.txt - # babel -pyyaml==5.4 - # via sphinx-autobuild -requests==2.22.0 - # via - # -c requirements.txt - # sphinx -six==1.14.0 - # via - # -c requirements.txt - # livereload - # sphinx -snowballstemmer==2.0.0 - # via sphinx -sphinx-autobuild==0.7.1 - # via -r requirements-docs.in -sphinx-intl==2.0.1 - # via -r requirements-docs.in -sphinx-rtd-theme==0.5.0 - # via -r requirements-docs.in -sphinx==1.6.4 - # via - # -r requirements-docs.in - # sphinx-intl - # sphinx-rtd-theme -sphinxcontrib-serializinghtml==1.1.4 - # via sphinxcontrib-websupport -sphinxcontrib-websupport==1.2.4 - # via - # -r requirements-docs.in - # sphinx -tornado==6.0.4 - # via - # livereload - # sphinx-autobuild -urllib3==1.25.8 - # via - # -c requirements.txt - # requests -watchdog==0.10.3 - # via sphinx-autobuild +alabaster==0.7.12 # via sphinx +argh==0.26.2 # via sphinx-autobuild +babel==2.8.0 # via sphinx, sphinx-intl +certifi==2019.11.28 # via -c requirements.txt, requests +chardet==3.0.4 # via -c requirements.txt, requests +click==7.1.2 # via sphinx-intl +docutils==0.15.2 # via -c requirements.txt, sphinx +idna==2.8 # via -c requirements.txt, requests +imagesize==1.2.0 # via sphinx +jinja2==2.11.3 # via sphinx +livereload==2.6.3 # via sphinx-autobuild +markupsafe==1.1.1 # via jinja2 +pathtools==0.1.2 # via sphinx-autobuild, watchdog +port_for==0.3.1 # via sphinx-autobuild +pygments==2.7.4 # via sphinx +pytz==2019.3 # via -c requirements.txt, babel +pyyaml==5.4 # via sphinx-autobuild +requests==2.22.0 # via -c requirements.txt, sphinx +six==1.14.0 # via -c requirements.txt, livereload, sphinx +snowballstemmer==2.0.0 # via sphinx +sphinx-autobuild==0.7.1 # via -r requirements-docs.in +sphinx-intl==2.0.1 # via -r requirements-docs.in +sphinx-rtd-theme==0.5.0 # via -r requirements-docs.in +sphinx==1.6.4 # via -r requirements-docs.in, sphinx-intl, sphinx-rtd-theme +sphinxcontrib-serializinghtml==1.1.4 # via sphinxcontrib-websupport +sphinxcontrib-websupport==1.2.4 # via -r requirements-docs.in, sphinx +tornado==6.0.4 # via livereload, sphinx-autobuild +urllib3==1.25.8 # via -c requirements.txt, requests +watchdog==0.10.3 # via sphinx-autobuild # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements.in b/requirements.in index 2852faab46..35072c6a50 100644 --- a/requirements.in +++ b/requirements.in @@ -6,7 +6,7 @@ djangorestframework==3.9.1 psycopg2-binary==2.7.4 django-js-reverse==0.9.1 django-registration==2.1.2 -le-utils>=0.1.19 +le-utils>=0.1.29 gunicorn==19.6.0 django-postmark==0.1.6 jsonfield==2.0.2 diff --git a/requirements.txt b/requirements.txt index 87de66200a..c0cf8aeab4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,260 +4,93 @@ # # pip-compile requirements.in # -amqp==2.5.2 - # via kombu -attrs==19.3.0 - # via - # -r requirements.in - # jsonschema -backoff==1.10.0 - # via -r requirements.in -backports-abc==0.5 - # via -r requirements.in -billiard==3.5.0.5 - # via celery -boto3==1.12.1 - # via django-s3-storage -botocore==1.15.1 - # via - # boto3 - # s3transfer -cachetools==4.0.0 - # via google-auth -celery==4.1.1 - # via -r requirements.in -certifi==2019.11.28 - # via - # minio - # requests - # sentry-sdk -chardet==3.0.4 - # via requests -django-bulk-update==2.2.0 - # via -r requirements.in -django-cte==1.1.4 - # via -r requirements.in -django-db-readonly==0.5.0 - # via -r requirements.in -django-filter==1.0.4 - # via -r requirements.in -django-js-asset==1.2.2 - # via django-mptt -django-js-reverse==0.9.1 - # via -r requirements.in -django-mathfilters==1.0.0 - # via -r requirements.in -django-model-utils==3.2.0 - # via -r requirements.in -django-mptt==0.9.1 - # via -r requirements.in -django-postmark==0.1.6 - # via -r requirements.in -django-prometheus==2.0.0 - # via -r requirements.in -django-redis==4.11.0 - # via -r requirements.in -django-registration==2.1.2 - # via -r requirements.in -django-s3-storage==0.12.4 - # via -r requirements.in -django-webpack-loader==0.7.0 - # via -r requirements.in -django==1.11.29 - # via - # -r requirements.in - # django-bulk-update - # django-js-reverse - # django-model-utils - # django-mptt - # django-redis - # django-s3-storage - # jsonfield -djangorestframework==3.9.1 - # via -r requirements.in -docutils==0.15.2 - # via botocore -future==0.18.2 - # via -r requirements.in -google-api-core[grpc]==1.16.0 - # via - # google-cloud-core - # google-cloud-kms - # google-cloud-logging -google-api-python-client==1.7.11 - # via -r requirements.in -google-auth-httplib2==0.0.3 - # via google-api-python-client -google-auth-oauthlib==0.4.2 - # via gspread -google-auth==1.23.0 - # via - # google-api-core - # google-api-python-client - # google-auth-httplib2 - # google-auth-oauthlib - # google-cloud-storage - # gspread -google-cloud-core==1.3.0 - # via - # -r requirements.in - # google-cloud-logging - # google-cloud-storage -google-cloud-error-reporting==0.33.0 - # via -r requirements.in -google-cloud-kms==0.2.1 - # via -r requirements.in -google-cloud-logging==1.14.0 - # via google-cloud-error-reporting -google-cloud-storage==1.26.0 - # via -r requirements.in -google-resumable-media==0.5.0 - # via google-cloud-storage -googleapis-common-protos[grpc]==1.51.0 - # via - # google-api-core - # grpc-google-iam-v1 -grpc-google-iam-v1==0.11.4 - # via google-cloud-kms -grpcio==1.27.2 - # via - # google-api-core - # googleapis-common-protos - # grpc-google-iam-v1 -gspread==3.6.0 - # via -r requirements.in -gunicorn==19.6.0 - # via -r requirements.in -html5lib==1.1 - # via -r requirements.in -httplib2==0.18.0 - # via - # django-postmark - # google-api-python-client - # google-auth-httplib2 - # oauth2client -idna==2.8 - # via requests -importlib-metadata==1.7.0 - # via -r requirements.in -jmespath==0.9.4 - # via - # boto3 - # botocore -jsonfield==2.0.2 - # via -r requirements.in -jsonschema==3.2.0 - # via -r requirements.in -kombu==4.3.0 - # via - # -r requirements.in - # celery -le-utils==0.1.24 - # via -r requirements.in -minio==3.0.3 - # via -r requirements.in -newrelic==5.6.0.135 - # via -r requirements.in -oauth2client==4.1.3 - # via -r requirements.in -oauthlib==3.1.0 - # via requests-oauthlib -pathlib==1.0.1 - # via -r requirements.in -pillow==8.1.1 - # via -r requirements.in -progressbar2==3.38.0 - # via -r requirements.in -prometheus-client==0.7.1 - # via django-prometheus -protobuf==3.11.3 - # via - # google-api-core - # googleapis-common-protos -psycopg2-binary==2.7.4 - # via -r requirements.in -pyasn1-modules==0.2.8 - # via - # google-auth - # oauth2client -pyasn1==0.4.8 - # via - # oauth2client - # pyasn1-modules - # rsa -pycountry==17.5.14 - # via - # -r requirements.in - # le-utils -pyrsistent==0.17.3 - # via jsonschema -python-dateutil==2.8.1 - # via - # -r requirements.in - # botocore -python-postmark==0.5.0 - # via -r requirements.in -python-utils==2.4.0 - # via progressbar2 -pytz==2019.3 - # via - # celery - # django - # django-postmark - # google-api-core - # minio -raven==6.10.0 - # via -r requirements.in -redis==2.10.5 - # via - # -r requirements.in - # django-redis -requests-oauthlib==1.3.0 - # via google-auth-oauthlib -requests==2.22.0 - # via - # -r requirements.in - # google-api-core - # gspread - # requests-oauthlib -rsa==4.7 - # via - # google-auth - # oauth2client -s3transfer==0.3.3 - # via boto3 -sentry-sdk==0.14.1 - # via -r requirements.in -six==1.14.0 - # via - # google-api-core - # google-api-python-client - # google-auth - # google-resumable-media - # grpcio - # html5lib - # jsonschema - # oauth2client - # progressbar2 - # protobuf - # python-dateutil - # python-utils -uritemplate==3.0.1 - # via google-api-python-client -urllib3==1.25.8 - # via - # botocore - # minio - # requests - # sentry-sdk -vine==1.3.0 - # via amqp -webencodings==0.5.1 - # via html5lib -whitenoise==4.1.4 - # via -r requirements.in -zipp==3.4.1 - # via importlib-metadata +amqp==2.5.2 # via kombu +attrs==19.3.0 # via -r requirements.in, jsonschema +backoff==1.10.0 # via -r requirements.in +backports-abc==0.5 # via -r requirements.in +billiard==3.5.0.5 # via celery +boto3==1.12.1 # via django-s3-storage +botocore==1.15.1 # via boto3, s3transfer +cachetools==4.0.0 # via google-auth +celery==4.1.1 # via -r requirements.in +certifi==2019.11.28 # via minio, requests, sentry-sdk +chardet==3.0.4 # via requests +django-bulk-update==2.2.0 # via -r requirements.in +django-cte==1.1.4 # via -r requirements.in +django-db-readonly==0.5.0 # via -r requirements.in +django-filter==1.0.4 # via -r requirements.in +django-js-asset==1.2.2 # via django-mptt +django-js-reverse==0.9.1 # via -r requirements.in +django-mathfilters==1.0.0 # via -r requirements.in +django-model-utils==3.2.0 # via -r requirements.in +django-mptt==0.9.1 # via -r requirements.in +django-postmark==0.1.6 # via -r requirements.in +django-prometheus==2.0.0 # via -r requirements.in +django-redis==4.11.0 # via -r requirements.in +django-registration==2.1.2 # via -r requirements.in +django-s3-storage==0.12.4 # via -r requirements.in +django-webpack-loader==0.7.0 # via -r requirements.in +django==1.11.29 # via -r requirements.in, django-bulk-update, django-js-reverse, django-model-utils, django-mptt, django-redis, django-s3-storage, jsonfield +djangorestframework==3.9.1 # via -r requirements.in +docutils==0.15.2 # via botocore +future==0.18.2 # via -r requirements.in +google-api-core[grpc]==1.16.0 # via google-cloud-core, google-cloud-kms, google-cloud-logging +google-api-python-client==1.7.11 # via -r requirements.in +google-auth-httplib2==0.0.3 # via google-api-python-client +google-auth-oauthlib==0.4.2 # via gspread +google-auth==1.23.0 # via google-api-core, google-api-python-client, google-auth-httplib2, google-auth-oauthlib, google-cloud-storage, gspread +google-cloud-core==1.3.0 # via -r requirements.in, google-cloud-logging, google-cloud-storage +google-cloud-error-reporting==0.33.0 # via -r requirements.in +google-cloud-kms==0.2.1 # via -r requirements.in +google-cloud-logging==1.14.0 # via google-cloud-error-reporting +google-cloud-storage==1.26.0 # via -r requirements.in +google-resumable-media==0.5.0 # via google-cloud-storage +googleapis-common-protos[grpc]==1.51.0 # via google-api-core, grpc-google-iam-v1 +grpc-google-iam-v1==0.11.4 # via google-cloud-kms +grpcio==1.27.2 # via google-api-core, googleapis-common-protos, grpc-google-iam-v1 +gspread==3.6.0 # via -r requirements.in +gunicorn==19.6.0 # via -r requirements.in +html5lib==1.1 # via -r requirements.in +httplib2==0.18.0 # via django-postmark, google-api-python-client, google-auth-httplib2, oauth2client +idna==2.8 # via requests +importlib-metadata==1.7.0 # via -r requirements.in, jsonschema +jmespath==0.9.4 # via boto3, botocore +jsonfield==2.0.2 # via -r requirements.in +jsonschema==3.2.0 # via -r requirements.in +kombu==4.3.0 # via -r requirements.in, celery +le-utils==0.1.29 # via -r requirements.in +minio==3.0.3 # via -r requirements.in +newrelic==5.6.0.135 # via -r requirements.in +oauth2client==4.1.3 # via -r requirements.in +oauthlib==3.1.0 # via requests-oauthlib +pathlib==1.0.1 # via -r requirements.in +pillow==8.1.1 # via -r requirements.in +progressbar2==3.38.0 # via -r requirements.in +prometheus-client==0.7.1 # via django-prometheus +protobuf==3.11.3 # via google-api-core, googleapis-common-protos +psycopg2-binary==2.7.4 # via -r requirements.in +pyasn1-modules==0.2.8 # via google-auth, oauth2client +pyasn1==0.4.8 # via oauth2client, pyasn1-modules, rsa +pycountry==17.5.14 # via -r requirements.in, le-utils +pyrsistent==0.17.3 # via jsonschema +python-dateutil==2.8.1 # via -r requirements.in, botocore +python-postmark==0.5.0 # via -r requirements.in +python-utils==2.4.0 # via progressbar2 +pytz==2019.3 # via celery, django, django-postmark, google-api-core, minio +raven==6.10.0 # via -r requirements.in +redis==2.10.5 # via -r requirements.in, django-redis +requests-oauthlib==1.3.0 # via google-auth-oauthlib +requests==2.22.0 # via -r requirements.in, google-api-core, gspread, requests-oauthlib +rsa==4.0 # via google-auth, oauth2client +s3transfer==0.3.3 # via boto3 +sentry-sdk==0.14.1 # via -r requirements.in +six==1.14.0 # via google-api-core, google-api-python-client, google-auth, google-resumable-media, grpcio, html5lib, jsonschema, oauth2client, progressbar2, protobuf, python-dateutil, python-utils +uritemplate==3.0.1 # via google-api-python-client +urllib3==1.25.8 # via botocore, minio, requests, sentry-sdk +vine==1.3.0 # via amqp +webencodings==0.5.1 # via html5lib +whitenoise==4.1.4 # via -r requirements.in +zipp==3.4.1 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools