diff --git a/src/editors/containers/EditorContainer/hooks.js b/src/editors/containers/EditorContainer/hooks.js index 77eae480a..7bb918f77 100644 --- a/src/editors/containers/EditorContainer/hooks.js +++ b/src/editors/containers/EditorContainer/hooks.js @@ -11,46 +11,13 @@ export const { saveBlock, } = appHooks; -export const setAssetToStaticUrl = (images, getContent) => { - /* For assets to remain usable across course instances, we convert their url to be course-agnostic. - * For example, /assets/course//filename gets converted to /static/filename. This is - * important for rerunning courses and importing/exporting course as the /static/ part of the url - * allows the asset to be mapped to the new course run. - */ - let content = getContent(); - const imageUrls = []; - const imgsArray = Object.values(images); - imgsArray.forEach(image => { - imageUrls.push({ portableUrl: image.portableUrl, displayName: image.displayName }); - }); - const imageSrcs = typeof content === 'string' ? content.split('src="') : []; - imageSrcs.forEach(src => { - if (src.startsWith('/asset') && imageUrls.length > 0) { - const nameFromEditorSrc = src.substring(src.lastIndexOf('@') + 1, src.indexOf('"')); - const nameFromStudioSrc = nameFromEditorSrc.substring(nameFromEditorSrc.indexOf('/') + 1); - let portableUrl; - imageUrls.forEach((url) => { - if (url.displayName === nameFromEditorSrc || url.displayName === nameFromStudioSrc) { - portableUrl = url.portableUrl; - } - }); - if (portableUrl) { - const currentSrc = src.substring(0, src.indexOf('"')); - const updatedContent = content.replace(currentSrc, portableUrl); - content = updatedContent; - } - } - }); - return content; -}; - export const handleSaveClicked = ({ dispatch, getContent, validateEntry }) => { const destination = useSelector(selectors.app.returnUrl); const analytics = useSelector(selectors.app.analytics); - const images = useSelector(selectors.app.images); + return () => saveBlock({ analytics, - content: setAssetToStaticUrl(images, getContent), + content: getContent({ dispatch }), destination, dispatch, validateEntry, diff --git a/src/editors/containers/EditorContainer/hooks.test.jsx b/src/editors/containers/EditorContainer/hooks.test.jsx index a9f027017..098302fba 100644 --- a/src/editors/containers/EditorContainer/hooks.test.jsx +++ b/src/editors/containers/EditorContainer/hooks.test.jsx @@ -26,20 +26,6 @@ jest.mock('../../hooks', () => ({ const dispatch = jest.fn(); describe('EditorContainer hooks', () => { - describe('non-state hooks', () => { - describe('replaceStaticwithAsset', () => { - it('returns content with updated img links', () => { - const getContent = jest.fn(() => ' '); - const images = [ - { portableUrl: '/static/soMEImagEURl', displayName: 'soMEImagEURl' }, - { portableUrl: '/static/soMEImagEURl1', displayName: 'soMEImagEURl1' }, - ]; - const content = hooks.setAssetToStaticUrl(images, getContent); - expect(getContent).toHaveBeenCalled(); - expect(content).toEqual(' '); - }); - }); - }); describe('forwarded hooks', () => { it('forwards navigateCallback from app hooks', () => { expect(hooks.navigateCallback).toEqual(appHooks.navigateCallback); diff --git a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap index 9ce88eff3..d6c214ed8 100644 --- a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap @@ -10,6 +10,11 @@ exports[`TextEditor snapshots ImageUploadModal is not rendered 1`] = ` "value": "something", }, }, + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "isRaw": false, }, } @@ -79,6 +84,11 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` "value": "something", }, }, + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "isRaw": false, }, } @@ -169,6 +179,11 @@ exports[`TextEditor snapshots loaded, raw editor 1`] = ` "value": "something", }, }, + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "isRaw": true, }, } @@ -250,6 +265,11 @@ exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = ` "value": "something", }, }, + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "isRaw": false, }, } @@ -324,6 +344,11 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = ` "value": "something", }, }, + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "isRaw": false, }, } diff --git a/src/editors/containers/TextEditor/hooks.js b/src/editors/containers/TextEditor/hooks.js index c322f2ff8..0ef8ff009 100644 --- a/src/editors/containers/TextEditor/hooks.js +++ b/src/editors/containers/TextEditor/hooks.js @@ -173,11 +173,44 @@ export const prepareEditorRef = () => { return { editorRef, refReady, setEditorRef }; }; -export const getContent = ({ editorRef, isRaw }) => () => { - if (isRaw && editorRef && editorRef.current) { - return editorRef.current.state.doc.toString(); - } - return editorRef.current?.getContent(); +export const setAssetToStaticUrl = ({ editorValue, images }) => { + /* For assets to remain usable across course instances, we convert their url to be course-agnostic. + * For example, /assets/course//filename gets converted to /static/filename. This is + * important for rerunning courses and importing/exporting course as the /static/ part of the url + * allows the asset to be mapped to the new course run. + */ + let content = editorValue; + const imageUrls = []; + const imgsArray = Object.values(images); + imgsArray.forEach(image => { + imageUrls.push({ portableUrl: image.portableUrl, displayName: image.displayName }); + }); + const imageSrcs = typeof content === 'string' ? content.split('src="') : []; + imageSrcs.forEach(src => { + if (src.startsWith('/asset') && imageUrls.length > 0) { + const nameFromEditorSrc = src.substring(src.lastIndexOf('@') + 1, src.indexOf('"')); + const nameFromStudioSrc = nameFromEditorSrc.substring(nameFromEditorSrc.indexOf('/') + 1); + let portableUrl; + imageUrls.forEach((url) => { + if (url.displayName === nameFromEditorSrc || url.displayName === nameFromStudioSrc) { + portableUrl = url.portableUrl; + } + }); + if (portableUrl) { + const currentSrc = src.substring(0, src.indexOf('"')); + const updatedContent = content.replace(currentSrc, portableUrl); + content = updatedContent; + } + } + }); + return content; +}; + +export const getContent = ({ editorRef, isRaw, images }) => () => { + const content = (isRaw && editorRef && editorRef.current + ? editorRef.current.state.doc.toString() + : editorRef.current?.getContent()); + return setAssetToStaticUrl({ editorValue: content, images }); }; export const fetchImageUrls = (images) => { diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx index 269ebca14..72fc11a92 100644 --- a/src/editors/containers/TextEditor/hooks.test.jsx +++ b/src/editors/containers/TextEditor/hooks.test.jsx @@ -96,6 +96,18 @@ describe('TextEditor hooks', () => { }); }); + describe('setAssetToStaticUrl', () => { + it('returns content with updated img links', () => { + const editorValue = ' '; + const images = [ + { portableUrl: '/static/soMEImagEURl', displayName: 'soMEImagEURl' }, + { portableUrl: '/static/soMEImagEURl1', displayName: 'soMEImagEURl1' }, + ]; + const content = module.setAssetToStaticUrl({ editorValue, images }); + expect(content).toEqual(' '); + }); + }); + describe('checkRelativeUrl', () => { test('it calls editor.on', () => { const editor = { on: jest.fn() }; @@ -249,9 +261,10 @@ describe('TextEditor hooks', () => { }, }, }; + const images = {}; test('returns correct ontent based on isRaw', () => { - expect(module.getContent({ editorRef, isRaw: false })()).toEqual(visualContent); - expect(module.getContent({ editorRef, isRaw: true })()).toEqual(rawContent); + expect(module.getContent({ editorRef, isRaw: false, images })()).toEqual(visualContent); + expect(module.getContent({ editorRef, isRaw: true, images })()).toEqual(rawContent); }); }); diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx index 6063c7d74..9cb09a444 100644 --- a/src/editors/containers/TextEditor/index.jsx +++ b/src/editors/containers/TextEditor/index.jsx @@ -88,7 +88,7 @@ export const TextEditor = ({ return (
diff --git a/src/editors/containers/VideoEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/VideoEditor/__snapshots__/index.test.jsx.snap index d0aab7998..be2090bb2 100644 --- a/src/editors/containers/VideoEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/VideoEditor/__snapshots__/index.test.jsx.snap @@ -5,7 +5,6 @@ exports[`VideoEditor snapshots renders as expected with default behavior 1`] = ` value="hooks.errorsHook.error" > diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget.jsx deleted file mode 100644 index 94e5d95d1..000000000 --- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import { useDispatch } from 'react-redux'; -// import PropTypes from 'prop-types'; - -import hooks from './hooks'; -import CollapsibleFormWidget from './CollapsibleFormWidget'; - -/** - * Collapsible Form widget controlling video thumbnail - */ -export const ThumbnailWidget = () => { - const dispatch = useDispatch(); - const { thumbnail } = hooks.widgetValues({ - dispatch, - fields: { [hooks.selectorKeys.thumbnail]: hooks.genericWidget }, - }); - return ( - -

{thumbnail.formValue}

-
- ); -}; - -export default ThumbnailWidget; diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/__snapshots__/index.test.jsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/__snapshots__/index.test.jsx.snap new file mode 100644 index 000000000..ddcdab5e1 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/__snapshots__/index.test.jsx.snap @@ -0,0 +1,144 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ThumbnailWidget snapshots snapshots: renders as expected where thumbnail uploads are allowed 1`] = ` + + + + + + Image used as thumbnail for video + + +`; + +exports[`ThumbnailWidget snapshots snapshots: renders as expected where videoType equals edxVideo 1`] = ` + + + Image used as thumbnail for video + + + + } + placement="top" + > + + + + +`; + +exports[`ThumbnailWidget snapshots snapshots: renders as expected with a thumbnail provided 1`] = ` + + + Image used as thumbnail for video + + +`; + +exports[`ThumbnailWidget snapshots snapshots: renders as expected with default props 1`] = ` + + + + + +
+ +
+
+ +
+ + +
+
+`; diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js new file mode 100644 index 000000000..ffd8463b1 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { useDispatch } from 'react-redux'; +import { thunkActions } from '../../../../../../data/redux'; + +export const fileInput = ({ setThumbnailSrc }) => { + const dispatch = useDispatch(); + const ref = React.useRef(); + const click = () => ref.current.click(); + const addFile = (e) => { + const file = e.target.files[0]; + const reader = new FileReader(); + const image = file; + reader.onload = () => { + setThumbnailSrc(reader.result); + }; + if (image) { + reader.readAsDataURL(image); + dispatch(thunkActions.video.uploadThumbnail({ thumbnail: image })); + } + }; + return { + click, + addFile, + ref, + }; +}; + +export default { + fileInput, +}; diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.js new file mode 100644 index 000000000..337925feb --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { dispatch } from 'react-redux'; +import { thunkActions } from '../../../../../../data/redux'; + +import * as hooks from './hooks'; + +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useRef: jest.fn(val => ({ current: val })), + useEffect: jest.fn(), + useCallback: (cb, prereqs) => ({ cb, prereqs }), +})); + +jest.mock('react-redux', () => { + const dispatchFn = jest.fn(); + return { + ...jest.requireActual('react-redux'), + dispatch: dispatchFn, + useDispatch: jest.fn(() => dispatchFn), + }; +}); + +jest.mock('../../../../../../data/redux', () => ({ + thunkActions: { + video: { + uploadThumbnail: jest.fn(), + }, + }, +})); + +let hook; +const setThumbnailSrc = jest.fn(); +const testValue = 'testVALUEVALIDIMAGE'; + +describe('fileInput', () => { + beforeEach(() => { + hook = hooks.fileInput({ setThumbnailSrc }); + }); + it('returns a ref for the file input', () => { + expect(hook.ref).toEqual({ current: undefined }); + }); + test('click calls current.click on the ref', () => { + const click = jest.fn(); + React.useRef.mockReturnValueOnce({ current: { click } }); + hook = hooks.fileInput({ setThumbnailSrc }); + hook.click(); + expect(click).toHaveBeenCalled(); + }); + describe('addFile (uploadImage args)', () => { + const eventSuccess = { target: { files: [new File([testValue], 'sOMEUrl.jpg')] } }; + const image = eventSuccess.target.files[0]; + it('dispatches updateField action with the first target file', () => { + hook.addFile(eventSuccess); + expect(dispatch).toHaveBeenCalledWith(thunkActions.video.uploadThumbnail({ thumbnail: image })); + }); + }); +}); diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx new file mode 100644 index 000000000..e376305d5 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx @@ -0,0 +1,113 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import { + FormattedMessage, + injectIntl, + intlShape, +} from '@edx/frontend-platform/i18n'; +import { + Image, + Stack, + Button, + OverlayTrigger, + Icon, + IconButton, + Tooltip, + Alert, +} from '@edx/paragon'; +import { Delete, FileUpload } from '@edx/paragon/icons'; + +import { actions, selectors } from '../../../../../../data/redux'; +import { acceptedImgKeys } from './utils'; +import * as hooks from './hooks'; +import messages from './messages'; + +import CollapsibleFormWidget from '../CollapsibleFormWidget'; +import FileInput from '../../../../../../sharedComponents/FileInput'; + +/** + * Collapsible Form widget controlling video thumbnail + */ +export const ThumbnailWidget = ({ + // injected + intl, + // redux + allowThumbnailUpload, + thumbnail, + updateField, + videoType, +}) => { + const [thumbnailSrc, setThumbnailSrc] = React.useState(thumbnail); + const fileInput = hooks.fileInput({ setThumbnailSrc }); + const isEdxVideo = videoType === 'edxVideo'; + return ( + + {isEdxVideo ? null : ( + + + + )} + {thumbnail ? ( + + {intl.formatMessage(messages.thumbnailAltText)} + { (allowThumbnailUpload && isEdxVideo) ? ( + + + + )} + > + updateField({ thumbnail: null })} + /> + + ) : null } + + ) : ( + +
+ +
+
+ +
+ + +
+ )} +
+ ); +}; + +ThumbnailWidget.propTypes = { + // injected + intl: intlShape.isRequired, + // redux + allowThumbnailUpload: PropTypes.bool.isRequired, + thumbnail: PropTypes.string.isRequired, + updateField: PropTypes.func.isRequired, + videoType: PropTypes.string.isRequired, +}; +export const mapStateToProps = (state) => ({ + allowThumbnailUpload: selectors.video.allowThumbnailUpload(state), + thumbnail: selectors.video.thumbnail(state), + videoType: selectors.video.videoType(state), +}); + +export const mapDispatchToProps = (dispatch) => ({ + updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)), +}); + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ThumbnailWidget)); diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx new file mode 100644 index 000000000..2ecf50fc9 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx @@ -0,0 +1,80 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import { formatMessage } from '../../../../../../../testUtils'; +import { actions, selectors } from '../../../../../../data/redux'; +import { ThumbnailWidget, mapStateToProps, mapDispatchToProps } from '.'; + +jest.mock('../../../../../../data/redux', () => ({ + actions: { + video: { + updateField: jest.fn().mockName('actions.video.updateField'), + }, + }, + selectors: { + video: { + allowThumbnailUpload: jest.fn(state => ({ allowThumbnailUpload: state })), + thumbnail: jest.fn(state => ({ thumbnail: state })), + videoType: jest.fn(state => ({ videoType: state })), + }, + }, +})); + +describe('ThumbnailWidget', () => { + const props = { + error: {}, + title: 'tiTLE', + intl: { formatMessage }, + allowThumbnailUpload: false, + thumbnail: null, + videoType: '', + updateField: jest.fn().mockName('args.updateField'), + }; + + describe('snapshots', () => { + test('snapshots: renders as expected with default props', () => { + expect( + shallow(), + ).toMatchSnapshot(); + }); + test('snapshots: renders as expected with a thumbnail provided', () => { + expect( + shallow(), + ).toMatchSnapshot(); + }); + test('snapshots: renders as expected where thumbnail uploads are allowed', () => { + expect( + shallow(), + ).toMatchSnapshot(); + }); + test('snapshots: renders as expected where videoType equals edxVideo', () => { + expect( + shallow(), + ).toMatchSnapshot(); + }); + }); + describe('mapStateToProps', () => { + const testState = { A: 'pple', B: 'anana', C: 'ucumber' }; + test('allowThumbnailUpload from video.allowThumbnailUpload', () => { + expect( + mapStateToProps(testState).allowThumbnailUpload, + ).toEqual(selectors.video.allowThumbnailUpload(testState)); + }); + test('thumbnail from video.thumbnail', () => { + expect( + mapStateToProps(testState).thumbnail, + ).toEqual(selectors.video.thumbnail(testState)); + }); + test('videoType from video.videoType', () => { + expect( + mapStateToProps(testState).videoType, + ).toEqual(selectors.video.videoType(testState)); + }); + }); + describe('mapDispatchToProps', () => { + const dispatch = jest.fn(); + test('updateField from actions.video.updateField', () => { + expect(mapDispatchToProps.updateField).toEqual(dispatch(actions.video.updateField)); + }); + }); +}); diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.js new file mode 100644 index 000000000..ee65734e2 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/messages.js @@ -0,0 +1,44 @@ +export const messages = { + title: { + id: 'authoring.videoeditor.thumbnail.title', + defaultMessage: 'Thumbnail', + description: 'Title for thumbnail widget', + }, + unavailableSubtitle: { + id: 'authoring.videoeditor.thumbnail.unavailable.subtitle', + defaultMessage: 'Unavailable', + description: 'Subtitle for unavailable thumbnail widget', + }, + unavailableMessage: { + id: 'authoring.videoeditor.thumbnail.unavailable.message', + defaultMessage: 'Select a video from your library to enable this feature', + description: 'Message for unavailable thumbnail widget', + }, + uploadButtonLabel: { + id: 'authoring.videoeditor.thumbnail.upload.label', + defaultMessage: 'Upload Thumbnail', + description: 'Label for upload button', + }, + addThumbnail: { + id: 'authoring.videoeditor.thumbnail.upload.message', + defaultMessage: 'Upload an image for learners to see before playing the video.', + description: 'Message for adding thumbnail', + }, + aspectRequirements: { + id: 'authoring.videoeditor.thumbnail.upload.aspectRequirements', + defaultMessage: 'Images must have an aspect ratio of 16:9 (1280x720 px recommended)', + description: 'Message for thumbnail aspectRequirements', + }, + thumbnailAltText: { + id: 'authoring.videoeditor.thumbnail.altText', + defaultMessage: 'Image used as thumbnail for video', + description: 'Alternative test for thumbnail', + }, + deleteThumbnail: { + id: 'authoring.videoeditor.thumbnail.deleteThumbnail', + defaultMessage: 'Delete', + description: 'Message presented to user for action to delete thumbnail', + }, +}; + +export default messages; diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/utils.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/utils.js new file mode 100644 index 000000000..1acb5b31c --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/utils.js @@ -0,0 +1,11 @@ +import { StrictDict } from '../../../../../../utils'; + +export const acceptedImgKeys = StrictDict({ + gif: '.gif', + jpg: '.jpg', + jpeg: '.jpeg', + png: '.png', + bmp: '.bmp', +}); + +export default { acceptedImgKeys }; diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptListItem.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptListItem.test.jsx index 7dcfac2b9..866d776fd 100644 --- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptListItem.test.jsx +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptListItem.test.jsx @@ -17,7 +17,7 @@ jest.mock('react-redux', () => { jest.mock('../../../../../../data/redux', () => ({ thunkActions: { video: { - deleteTranscript: jest.fn().mockName('actions.video.deleteTranscript'), + deleteTranscript: jest.fn().mockName('thunkActions.video.deleteTranscript'), }, }, selectors: { diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx index c94ca6b7b..595f289e7 100644 --- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx @@ -1,7 +1,10 @@ import React from 'react'; import { connect, useDispatch } from 'react-redux'; import PropTypes from 'prop-types'; - +import { + FormattedMessage, + injectIntl, +} from '@edx/frontend-platform/i18n'; import { Form, Button, @@ -12,10 +15,6 @@ import { Alert, } from '@edx/paragon'; import { FileUpload, Info } from '@edx/paragon/icons'; -import { - FormattedMessage, - injectIntl, -} from '@edx/frontend-platform/i18n'; import { actions, selectors } from '../../../../../../data/redux'; import * as hooks from './hooks'; @@ -46,7 +45,6 @@ export const TranscriptWidget = ({ const languagesArr = hooks.transcriptLanguages(transcripts); const fileInput = hooks.fileInput({ onAddFile: hooks.addFileCallback({ dispatch: useDispatch() }) }); const hasTranscripts = hooks.hasTranscripts(transcripts); - return ( ({ }, thunkActions: { video: { - deleteTranscript: jest.fn().mockName('actions.video.deleteTranscript'), + deleteTranscript: jest.fn().mockName('thunkActions.video.deleteTranscript'), }, }, diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/__snapshots__/index.test.jsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/__snapshots__/index.test.jsx.snap index 7e3afd6fb..785145388 100644 --- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/__snapshots__/index.test.jsx.snap @@ -34,7 +34,7 @@ exports[`VideoSourceWidget snapshots snapshots: renders as expected with default id="authoring.videoeditor.videoSource.fallbackVideo.message" /> - - - + - +