diff --git a/src/editors/containers/TextEditor/components/ImageUploadModal.jsx b/src/editors/containers/TextEditor/components/ImageUploadModal.jsx index ad86f9bae..89f085e3d 100644 --- a/src/editors/containers/TextEditor/components/ImageUploadModal.jsx +++ b/src/editors/containers/TextEditor/components/ImageUploadModal.jsx @@ -1,6 +1,10 @@ import React from 'react'; +import { connect } from 'react-redux'; import PropTypes from 'prop-types'; +import { injectIntl } from '@edx/frontend-platform/i18n'; + +import { selectors } from '../../../data/redux'; import tinyMCEKeys from '../../../data/constants/tinyMCE'; import ImageSettingsModal from './ImageSettingsModal'; import SelectImageModal from './SelectImageModal'; @@ -10,12 +14,23 @@ export const propsString = (props) => ( Object.keys(props).map((key) => `${key}="${props[key]}"`).join(' ') ); -export const imgProps = ({ settings, selection }) => ({ - src: selection.url, - alt: settings.isDecorative ? '' : settings.altText, - width: settings.dimensions.width, - height: settings.dimensions.height, -}); +export const imgProps = ({ + settings, + selection, + lmsEndpointUrl, +}) => { + let url = selection.externalUrl; + if (url.startsWith(lmsEndpointUrl)) { + const sourceEndIndex = lmsEndpointUrl.length; + url = url.substring(sourceEndIndex); + } + return { + src: url, + alt: settings.isDecorative ? '' : settings.altText, + width: settings.dimensions.width, + height: settings.dimensions.height, + }; +}; export const hooks = { createSaveCallback: ({ @@ -23,13 +38,18 @@ export const hooks = { editorRef, setSelection, selection, + lmsEndpointUrl, }) => ( settings, ) => { editorRef.current.execCommand( tinyMCEKeys.commands.insertContent, false, - module.hooks.imgTag({ settings, selection }), + module.hooks.imgTag({ + settings, + selection, + lmsEndpointUrl, + }), ); setSelection(null); close(); @@ -38,8 +58,8 @@ export const hooks = { clearSelection(); close(); }, - imgTag: ({ settings, selection }) => { - const props = module.imgProps({ settings, selection }); + imgTag: ({ settings, selection, lmsEndpointUrl }) => { + const props = module.imgProps({ settings, selection, lmsEndpointUrl }); return ``; }, }; @@ -53,6 +73,8 @@ export const ImageUploadModal = ({ selection, setSelection, images, + // redux + lmsEndpointUrl, }) => { if (selection) { return ( @@ -66,6 +88,7 @@ export const ImageUploadModal = ({ editorRef, selection, setSelection, + lmsEndpointUrl, }), returnToSelection: clearSelection, }} @@ -104,5 +127,13 @@ ImageUploadModal.propTypes = { }), setSelection: PropTypes.func.isRequired, images: PropTypes.shape({}).isRequired, + lmsEndpointUrl: PropTypes.string.isRequired, }; -export default ImageUploadModal; + +export const mapStateToProps = (state) => ({ + lmsEndpointUrl: selectors.app.lmsEndpointUrl(state), +}); + +export const mapDispatchToProps = {}; + +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ImageUploadModal)); diff --git a/src/editors/containers/TextEditor/components/ImageUploadModal.test.jsx b/src/editors/containers/TextEditor/components/ImageUploadModal.test.jsx index 4a0f5b0bc..e7baa4dc7 100644 --- a/src/editors/containers/TextEditor/components/ImageUploadModal.test.jsx +++ b/src/editors/containers/TextEditor/components/ImageUploadModal.test.jsx @@ -2,6 +2,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { keyStore } from '../../../utils'; +import { selectors } from '../../../data/redux'; import tinyMCEKeys from '../../../data/constants/tinyMCE'; import * as module from './ImageUploadModal'; @@ -9,8 +10,15 @@ import * as module from './ImageUploadModal'; jest.mock('./ImageSettingsModal', () => 'ImageSettingsModal'); jest.mock('./SelectImageModal', () => 'SelectImageModal'); -const { ImageUploadModal } = module; +const { ImageUploadModal, mapStateToProps, mapDispatchToProps } = module; +jest.mock('../../../data/redux', () => ({ + selectors: { + app: { + lmsEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })), + }, + }, +})); const hookKeys = keyStore(module.hooks); const settings = { @@ -25,9 +33,10 @@ const settings = { describe('ImageUploadModal', () => { describe('hooks', () => { describe('imgTag', () => { - const selection = { url: 'sOmEuRl.cOm' }; + const selection = { externalUrl: 'sOmEuRl.cOm' }; + const url = 'uRl.cOm'; const expected = { - src: selection.url, + src: url, alt: settings.altText, width: settings.dimensions.width, height: settings.dimensions.height, @@ -36,6 +45,7 @@ describe('ImageUploadModal', () => { const output = module.hooks.imgTag({ settings: args.settings, selection, + lmsEndpointUrl: 'sOmE', }); expect(output).toEqual(``); }; @@ -55,10 +65,11 @@ describe('ImageUploadModal', () => { const editorRef = { current: { some: 'dATa', execCommand: execCommandMock } }; const setSelection = jest.fn(); const selection = jest.fn(); + const lmsEndpointUrl = 'sOmE'; let output; beforeEach(() => { output = module.hooks.createSaveCallback({ - close, editorRef, setSelection, selection, + close, editorRef, setSelection, selection, lmsEndpointUrl, }); }); afterEach(() => { @@ -66,7 +77,7 @@ describe('ImageUploadModal', () => { }); test('It creates a callback, that when called, inserts to the editor, sets the selection to be null, and calls close', () => { jest.spyOn(module.hooks, hookKeys.imgTag) - .mockImplementationOnce((props) => ({ selection, settings: props.settings })); + .mockImplementationOnce((props) => ({ selection, settings: props.settings, lmsEndpointUrl })); expect(execCommandMock).not.toBeCalled(); expect(setSelection).not.toBeCalled(); expect(close).not.toBeCalled(); @@ -74,7 +85,7 @@ describe('ImageUploadModal', () => { expect(execCommandMock).toBeCalledWith( tinyMCEKeys.commands.insertContent, false, - { selection, settings }, + { selection, settings, lmsEndpointUrl }, ); expect(setSelection).toBeCalledWith(null); expect(close).toBeCalled(); @@ -103,6 +114,7 @@ describe('ImageUploadModal', () => { clearSelection: jest.fn().mockName('props.clearSelection'), selection: { some: 'images' }, setSelection: jest.fn().mockName('props.setSelection'), + lmsEndpointUrl: 'sOmE', }; module.hooks = { createSaveCallback: jest.fn().mockName('hooks.createSaveCallback'), @@ -119,4 +131,18 @@ describe('ImageUploadModal', () => { expect(shallow()).toMatchSnapshot(); }); }); + + describe('mapStateToProps', () => { + const testState = { A: 'pple', B: 'anana', C: 'ucumber' }; + test('lmsEndpointUrl from app.lmsEndpointUrl', () => { + expect( + mapStateToProps(testState).lmsEndpointUrl, + ).toEqual(selectors.app.lmsEndpointUrl(testState)); + }); + }); + describe('mapDispatchToProps', () => { + it('equals an empty object', () => { + expect(mapDispatchToProps).toEqual({}); + }); + }); });