chore: All selection and save flow added
This commit is contained in:
@@ -12,9 +12,9 @@ export const {
|
||||
} = appHooks;
|
||||
|
||||
export const hooks = {
|
||||
initialize: (dispatch) => {
|
||||
initialize: (dispatch, selectedVideoId) => {
|
||||
React.useEffect(() => {
|
||||
dispatch(thunkActions.video.loadVideoData());
|
||||
dispatch(thunkActions.video.loadVideoData(selectedVideoId));
|
||||
}, []);
|
||||
},
|
||||
returnToGallery: () => {
|
||||
@@ -29,10 +29,11 @@ const VideoEditorModal = ({
|
||||
isOpen,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
module.hooks.initialize(dispatch);
|
||||
const searchParams = new URLSearchParams(document.location.search);
|
||||
const showReturn = searchParams.get('return') !== null;
|
||||
const selectedVideoId = searchParams.get('selectedVideoId');
|
||||
const showReturn = selectedVideoId != null;
|
||||
const onReturn = module.hooks.returnToGallery();
|
||||
module.hooks.initialize(dispatch, selectedVideoId);
|
||||
return (
|
||||
<VideoSettingsModal {...{
|
||||
close,
|
||||
|
||||
@@ -129,8 +129,7 @@ export const videoListProps = ({ searchSortProps, videos }) => {
|
||||
selectBtnProps: {
|
||||
onClick: () => {
|
||||
if (highlighted) {
|
||||
// TODO save the metadata of the video on the block to fill it into the cideo editor
|
||||
navigateTo(`/course/${learningContextId}/editor/video/${blockId}?return=true`);
|
||||
navigateTo(`/course/${learningContextId}/editor/video/${blockId}?selectedVideoId=${highlighted}`);
|
||||
} else {
|
||||
setShowSelectVideoError(true);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
/* eslint-disable import/no-cycle */
|
||||
import { actions, selectors } from '..';
|
||||
import { removeItemOnce } from '../../../utils';
|
||||
import { formatDuration, removeItemOnce } from '../../../utils';
|
||||
import * as requests from './requests';
|
||||
import * as module from './video';
|
||||
import { valueFromDuration } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks';
|
||||
import { parseYoutubeId } from '../../services/cms/api';
|
||||
|
||||
export const loadVideoData = () => (dispatch, getState) => {
|
||||
export const loadVideoData = (selectedVideoId) => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const blockValueData = state.app.blockValue.data;
|
||||
const rawVideoData = blockValueData.metadata ? blockValueData.metadata : {};
|
||||
const courseData = state.app.courseDetails.data ? state.app.courseDetails.data : {};
|
||||
if (Object.keys(rawVideoData).length === 0 && selectedVideoId !== null) {
|
||||
const rawVideos = Object.values(selectors.app.videos(state));
|
||||
const selectedVideo = rawVideos.find(video => video.edx_video_id === selectedVideoId);
|
||||
// TODO it's missing laod the transcripts
|
||||
rawVideoData = {
|
||||
edx_video_id: selectedVideo.edx_video_id,
|
||||
thumbnail: selectedVideo.course_video_image_url,
|
||||
end_time: formatDuration(selectedVideo.duration),
|
||||
duration: selectedVideo.duration,
|
||||
};
|
||||
}
|
||||
const studioView = state.app.studioView?.data?.html;
|
||||
const {
|
||||
videoId,
|
||||
@@ -45,7 +56,7 @@ export const loadVideoData = () => (dispatch, getState) => {
|
||||
duration: { // TODO duration is not always sent so they should be calculated.
|
||||
startTime: valueFromDuration(rawVideoData.start_time || '00:00:00'),
|
||||
stopTime: valueFromDuration(rawVideoData.end_time || '00:00:00'),
|
||||
total: 0, // TODO can we get total duration? if not, probably dropping from widget
|
||||
total: rawVideoData.duration || 0, // TODO can we get total duration? if not, probably dropping from widget
|
||||
},
|
||||
handout: rawVideoData.handout,
|
||||
licenseType,
|
||||
|
||||
@@ -12,6 +12,7 @@ jest.mock('..', () => ({
|
||||
selectors: {
|
||||
app: {
|
||||
courseDetails: (state) => ({ courseDetails: state }),
|
||||
videos: (state) => ({ videos: state.app.videos }),
|
||||
},
|
||||
video: {
|
||||
videoId: (state) => ({ videoId: state }),
|
||||
@@ -34,6 +35,7 @@ jest.mock('./requests', () => ({
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils', () => ({
|
||||
...jest.requireActual('../../../utils'),
|
||||
removeItemOnce: (args) => (args),
|
||||
}));
|
||||
|
||||
@@ -56,6 +58,7 @@ const mockVideoFeatures = {
|
||||
videoSharingEnabled: 'soMEbOolEAn',
|
||||
},
|
||||
};
|
||||
const mockSelectedVideoId = 'ThisIsAVideoId';
|
||||
|
||||
const testMetadata = {
|
||||
download_track: 'dOWNlOAdTraCK',
|
||||
@@ -80,6 +83,11 @@ const testState = {
|
||||
originalThumbnail: null,
|
||||
videoId: 'soMEvIDEo',
|
||||
};
|
||||
const testVideosState = {
|
||||
edx_video_id: mockSelectedVideoId,
|
||||
thumbnail: 'thumbnail',
|
||||
duration: 60,
|
||||
};
|
||||
const testUpload = { transcripts: ['la', 'en'] };
|
||||
const testReplaceUpload = {
|
||||
file: mockFile,
|
||||
@@ -130,25 +138,37 @@ describe('video thunkActions', () => {
|
||||
jest.spyOn(thunkActions, thunkActionsKeys.parseTranscripts).mockReturnValue(
|
||||
testMetadata.transcripts,
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
it('dispatches fetchVideoFeatures action', () => {
|
||||
thunkActions.loadVideoData()(dispatch, getState);
|
||||
[
|
||||
[dispatchedLoad],
|
||||
[dispatchedAction1],
|
||||
[dispatchedAction2],
|
||||
] = dispatch.mock.calls;
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
it('dispatches fetchVideoFeatures action', () => {
|
||||
expect(dispatchedLoad).not.toEqual(undefined);
|
||||
expect(dispatchedAction1.fetchVideoFeatures).not.toEqual(undefined);
|
||||
});
|
||||
it('dispatches checkTranscriptsForImport action', () => {
|
||||
thunkActions.loadVideoData()(dispatch, getState);
|
||||
[
|
||||
[dispatchedLoad],
|
||||
[dispatchedAction1],
|
||||
[dispatchedAction2],
|
||||
] = dispatch.mock.calls;
|
||||
expect(dispatchedLoad).not.toEqual(undefined);
|
||||
expect(dispatchedAction2.checkTranscriptsForImport).not.toEqual(undefined);
|
||||
});
|
||||
it('dispatches actions.video.load', () => {
|
||||
thunkActions.loadVideoData()(dispatch, getState);
|
||||
[
|
||||
[dispatchedLoad],
|
||||
[dispatchedAction1],
|
||||
[dispatchedAction2],
|
||||
] = dispatch.mock.calls;
|
||||
expect(dispatchedLoad.load).toEqual({
|
||||
videoSource: 'videOsOurce',
|
||||
videoId: 'videOiD',
|
||||
@@ -186,7 +206,62 @@ describe('video thunkActions', () => {
|
||||
thumbnail: testMetadata.thumbnail,
|
||||
});
|
||||
});
|
||||
it('dispatches actions.video.load with selectedVideoId', () => {
|
||||
getState = jest.fn(() => ({
|
||||
app: {
|
||||
blockId: 'soMEBloCk',
|
||||
studioEndpointUrl: 'soMEeNDPoiNT',
|
||||
blockValue: { data: { metadata: {} } },
|
||||
courseDetails: { data: { license: null } },
|
||||
studioView: { data: { html: 'sOMeHTml' } },
|
||||
videos: testVideosState,
|
||||
},
|
||||
}));
|
||||
thunkActions.loadVideoData(mockSelectedVideoId)(dispatch, getState);
|
||||
[
|
||||
[dispatchedLoad],
|
||||
[dispatchedAction1],
|
||||
[dispatchedAction2],
|
||||
] = dispatch.mock.calls;
|
||||
expect(dispatchedLoad.load).toEqual({
|
||||
videoSource: 'videOsOurce',
|
||||
videoId: 'videOiD',
|
||||
fallbackVideos: 'fALLbACKvIDeos',
|
||||
allowVideoDownloads: undefined,
|
||||
transcripts: testMetadata.transcripts,
|
||||
allowTranscriptDownloads: undefined,
|
||||
allowVideoSharing: undefined,
|
||||
showTranscriptByDefault: undefined,
|
||||
duration: {
|
||||
startTime: testMetadata.start_time,
|
||||
stopTime: testVideosState.duration * 1000,
|
||||
total: testVideosState.duration,
|
||||
},
|
||||
handout: undefined,
|
||||
licenseType: 'liCENSEtyPe',
|
||||
licenseDetails: {
|
||||
attribution: true,
|
||||
noncommercial: true,
|
||||
noDerivatives: true,
|
||||
shareAlike: false,
|
||||
},
|
||||
courseLicenseType: 'liCENSEtyPe',
|
||||
courseLicenseDetails: {
|
||||
attribution: true,
|
||||
noncommercial: true,
|
||||
noDerivatives: true,
|
||||
shareAlike: false,
|
||||
},
|
||||
thumbnail: undefined,
|
||||
});
|
||||
});
|
||||
it('dispatches actions.video.updateField on success', () => {
|
||||
thunkActions.loadVideoData()(dispatch, getState);
|
||||
[
|
||||
[dispatchedLoad],
|
||||
[dispatchedAction1],
|
||||
[dispatchedAction2],
|
||||
] = dispatch.mock.calls;
|
||||
dispatch.mockClear();
|
||||
dispatchedAction1.fetchVideoFeatures.onSuccess(mockVideoFeatures);
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.video.updateField({
|
||||
|
||||
Reference in New Issue
Block a user