diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.jsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.jsx index 071241b50..f3c5c8a3c 100644 --- a/src/editors/containers/VideoEditor/components/VideoEditorModal.jsx +++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.jsx @@ -12,9 +12,9 @@ export const { } = appHooks; export const hooks = { - initialize: (dispatch, selectedVideoId) => { + initialize: (dispatch, selectedVideoId, selectedVideoUrl) => { React.useEffect(() => { - dispatch(thunkActions.video.loadVideoData(selectedVideoId)); + dispatch(thunkActions.video.loadVideoData(selectedVideoId, selectedVideoUrl)); }, []); }, returnToGallery: () => { @@ -31,8 +31,9 @@ const VideoEditorModal = ({ const dispatch = useDispatch(); const searchParams = new URLSearchParams(document.location.search); const selectedVideoId = searchParams.get('selectedVideoId'); + const selectedVideoUrl = searchParams.get('selectedVideoUrl'); const onReturn = module.hooks.returnToGallery(); - module.hooks.initialize(dispatch, selectedVideoId); + module.hooks.initialize(dispatch, selectedVideoId, selectedVideoUrl); return ( { return (edxVideoId) => navigateTo(`/course/${learningContextId}/editor/video/${blockId}?selectedVideoId=${edxVideoId}`); }; +export const onUrlUploaded = () => { + const state = store.getState(); + const learningContextId = selectors.app.learningContextId(state); + const blockId = selectors.app.blockId(state); + return (videoUrl) => navigateTo(`/course/${learningContextId}/editor/video/${blockId}?selectedVideoUrl=${videoUrl}`); +}; + export default { uploadVideo, }; diff --git a/src/editors/containers/VideoUploadEditor/hooks.test.js b/src/editors/containers/VideoUploadEditor/hooks.test.js index 217c52c14..c1ef806df 100644 --- a/src/editors/containers/VideoUploadEditor/hooks.test.js +++ b/src/editors/containers/VideoUploadEditor/hooks.test.js @@ -40,7 +40,6 @@ describe('uploadVideo', () => { { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' }, ], }; - const spyConsoleLog = jest.spyOn(console, 'log'); const mockRequestResponse = { data: response }; requests.uploadVideo.mockImplementation(async ({ onSuccess }) => { await onSuccess(mockRequestResponse); @@ -66,7 +65,6 @@ describe('uploadVideo', () => { { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' }, ], }; - const spyConsoleError = jest.spyOn(console, 'error'); const mockRequestResponse = { data: response }; requests.uploadVideo.mockImplementation(async ({ onSuccess }) => { await onSuccess(mockRequestResponse); diff --git a/src/editors/containers/VideoUploadEditor/index.jsx b/src/editors/containers/VideoUploadEditor/index.jsx index 7d998193f..71b2ce68d 100644 --- a/src/editors/containers/VideoUploadEditor/index.jsx +++ b/src/editors/containers/VideoUploadEditor/index.jsx @@ -13,6 +13,7 @@ import * as editorHooks from '../EditorContainer/hooks'; export const VideoUploader = ({ onUpload, errorMessage }) => { const [, setUploadedFile] = useState(); const [textInputValue, setTextInputValue] = useState(''); + const onUrlUpdatedHook = hooks.onUrlUploaded(); const { getRootProps, getInputProps, isDragActive } = useDropzone({ accept: 'video/*', @@ -31,8 +32,7 @@ export const VideoUploader = ({ onUpload, errorMessage }) => { }; const handleSaveButtonClick = () => { - // do something with the textInputValue, e.g. save to state or send to server - console.log(`Saving input value: ${textInputValue}`); + onUrlUpdatedHook(textInputValue); }; if (errorMessage) { diff --git a/src/editors/data/redux/thunkActions/video.js b/src/editors/data/redux/thunkActions/video.js index 1caebe1af..41a273129 100644 --- a/src/editors/data/redux/thunkActions/video.js +++ b/src/editors/data/redux/thunkActions/video.js @@ -6,7 +6,7 @@ import * as module from './video'; import { valueFromDuration } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks'; import { parseYoutubeId } from '../../services/cms/api'; -export const loadVideoData = (selectedVideoId) => (dispatch, getState) => { +export const loadVideoData = (selectedVideoId, selectedVideoUrl) => (dispatch, getState) => { const state = getState(); const blockValueData = state.app.blockValue.data; let rawVideoData = blockValueData.metadata ? blockValueData.metadata : {}; @@ -32,8 +32,10 @@ export const loadVideoData = (selectedVideoId) => (dispatch, getState) => { youtubeId: rawVideoData.youtube_id_1_0, html5Sources: rawVideoData.html5_sources, }); - const [licenseType, licenseOptions] = module.parseLicense({ licenseData: studioView, level: 'block' }); + // Use the selected video url first + const videoSourceUrl = selectedVideoUrl != null ? selectedVideoUrl : videoUrl; + const [licenseType, licenseOptions] = module.parseLicense({ licenseData: studioView, level: 'block' }); const transcripts = rawVideoData.transcripts ? rawVideoData.transcripts : module.parseTranscripts({ transcriptsData: studioView }); @@ -46,7 +48,7 @@ export const loadVideoData = (selectedVideoId) => (dispatch, getState) => { blockSetting: rawVideoData.public_access, }); dispatch(actions.video.load({ - videoSource: videoUrl || '', + videoSource: videoSourceUrl || '', videoId, fallbackVideos, allowVideoDownloads: rawVideoData.download_video, @@ -85,7 +87,7 @@ export const loadVideoData = (selectedVideoId) => (dispatch, getState) => { videoSharingEnabledForAll: response.data.videoSharingEnabled, })), })); - const youTubeId = parseYoutubeId(videoUrl); + const youTubeId = parseYoutubeId(videoSourceUrl); if (youTubeId) { dispatch(requests.checkTranscriptsForImport({ videoId, diff --git a/src/editors/data/redux/thunkActions/video.test.js b/src/editors/data/redux/thunkActions/video.test.js index e6bd7a038..edb211f6c 100644 --- a/src/editors/data/redux/thunkActions/video.test.js +++ b/src/editors/data/redux/thunkActions/video.test.js @@ -59,6 +59,7 @@ const mockVideoFeatures = { }, }; const mockSelectedVideoId = 'ThisIsAVideoId'; +const mockSelectedVideoUrl = 'ThisIsAYoutubeUrl'; const testMetadata = { download_track: 'dOWNlOAdTraCK', @@ -219,7 +220,7 @@ describe('video thunkActions', () => { videos: testVideosState, }, })); - thunkActions.loadVideoData(mockSelectedVideoId)(dispatch, getState); + thunkActions.loadVideoData(mockSelectedVideoId, null)(dispatch, getState); [ [dispatchedLoad], [dispatchedAction1], @@ -263,6 +264,44 @@ describe('video thunkActions', () => { thumbnail: undefined, }); }); + it('dispatches actions.video.load with selectedVideoUrl', () => { + thunkActions.loadVideoData(null, mockSelectedVideoUrl)(dispatch, getState); + [ + [dispatchedLoad], + [dispatchedAction1], + [dispatchedAction2], + ] = dispatch.mock.calls; + expect(dispatchedLoad.load).toEqual({ + videoSource: mockSelectedVideoUrl, + videoId: 'videOiD', + fallbackVideos: 'fALLbACKvIDeos', + allowVideoDownloads: testMetadata.download_video, + transcripts: testMetadata.transcripts, + allowTranscriptDownloads: testMetadata.download_track, + showTranscriptByDefault: testMetadata.show_captions, + duration: { + startTime: testMetadata.start_time, + stopTime: testMetadata.end_time, + total: 0, + }, + handout: testMetadata.handout, + licenseType: 'liCENSEtyPe', + licenseDetails: { + attribution: true, + noncommercial: true, + noDerivatives: true, + shareAlike: false, + }, + courseLicenseType: 'liCENSEtyPe', + courseLicenseDetails: { + attribution: true, + noncommercial: true, + noDerivatives: true, + shareAlike: false, + }, + thumbnail: testMetadata.thumbnail, + }); + }); it('dispatches actions.video.updateField on success', () => { thunkActions.loadVideoData()(dispatch, getState); [