diff --git a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap index 95f9a30b3..1cd6ca86b 100644 --- a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap @@ -56,6 +56,7 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` "openModal": [MockFunction modal.openModal], "setEditorRef": [MockFunction hooks.prepareEditorRef.setEditorRef], "setSelection": [MockFunction hooks.selectedImage.setSelection], + "studioEndpointUrl": "sOmEoThERvaLue.cOm", } } /> @@ -174,6 +175,7 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = ` "openModal": [MockFunction modal.openModal], "setEditorRef": [MockFunction hooks.prepareEditorRef.setEditorRef], "setSelection": [MockFunction hooks.selectedImage.setSelection], + "studioEndpointUrl": "sOmEoThERvaLue.cOm", } } /> diff --git a/src/editors/containers/TextEditor/hooks.js b/src/editors/containers/TextEditor/hooks.js index 68274dace..308ecd9ab 100644 --- a/src/editors/containers/TextEditor/hooks.js +++ b/src/editors/containers/TextEditor/hooks.js @@ -20,11 +20,13 @@ export const setupCustomBehavior = ({ openModal, setImage }) => (editor) => { // image upload button editor.ui.registry.addButton(tinyMCE.buttons.imageUploadButton, { icon: 'image', + tooltip: 'Add Image', onAction: openModal, }); // editing an existing image editor.ui.registry.addButton(tinyMCE.buttons.editImageSettings, { icon: 'image', + tooltip: 'Edit Image Settings', onAction: module.openModalWithSelectedImage({ editor, setImage, openModal }), }); // overriding the code plugin's icon with 'HTML' text @@ -34,14 +36,32 @@ export const setupCustomBehavior = ({ openModal, setImage }) => (editor) => { tooltip: 'Source code', onAction: openCodeEditor, }); + // add a custom simple inline code block formatter. + const toggleCodeFormatting = () => editor.formatter.toggle('code'); + editor.ui.registry.addButton(tinyMCE.buttons.codeBlock, { + icon: 'sourcecode', + tooltip: 'Code Block', + onAction: toggleCodeFormatting, + }); + const toggleBlockQuoteFormatting = () => editor.formatter.toggle('blockquote'); + editor.ui.registry.addButton(tinyMCE.buttons.blockQuote, { + icon: 'quote', + tooltip: 'Block Quote', + onAction: toggleBlockQuoteFormatting, + }); }; +// imagetools_cors_hosts needs a protocol-sanatized url +export const removeProtocolFromUrl = (url) => url.replace(/^https?:\/\//, ''); + export const editorConfig = ({ setEditorRef, blockValue, openModal, initializeEditor, setSelection, + lmsEndpointUrl, + studioEndpointUrl, }) => ({ onInit: (evt, editor) => { setEditorRef(editor); @@ -58,6 +78,7 @@ export const editorConfig = ({ ...pluginConfig.config, valid_elements: '*[*]', valid_children: '+body[style]', + imagetools_cors_hosts: [removeProtocolFromUrl(lmsEndpointUrl), removeProtocolFromUrl(studioEndpointUrl)], }, }); diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx index 59fc17f21..e1d12a4ab 100644 --- a/src/editors/containers/TextEditor/hooks.test.jsx +++ b/src/editors/containers/TextEditor/hooks.test.jsx @@ -65,13 +65,17 @@ describe('TextEditor hooks', () => { const mockOpenModalWithImage = args => ({ openModalWithSelectedImage: args }); const expectedSettingsAction = mockOpenModalWithImage({ editor, setImage, openModal }); const openCodeEditor = expect.any(Function); + const toggleCodeFormatting = expect.any(Function); + const toggleBlockQuoteFormatting = expect.any(Function); jest.spyOn(module, moduleKeys.openModalWithSelectedImage) .mockImplementationOnce(mockOpenModalWithImage); output = module.setupCustomBehavior({ openModal, setImage })(editor); expect(addButton.mock.calls).toEqual([ - [tinyMCE.buttons.imageUploadButton, { icon: 'image', onAction: openModal }], - [tinyMCE.buttons.editImageSettings, { icon: 'image', onAction: expectedSettingsAction }], + [tinyMCE.buttons.imageUploadButton, { icon: 'image', tooltip: 'Add Image', onAction: openModal }], + [tinyMCE.buttons.editImageSettings, { icon: 'image', tooltip: 'Edit Image Settings', onAction: expectedSettingsAction }], [tinyMCE.buttons.code, { text: 'HTML', tooltip: 'Source code', onAction: openCodeEditor }], + [tinyMCE.buttons.codeBlock, { icon: 'sourcecode', tooltip: 'Code Block', onAction: toggleCodeFormatting }], + [tinyMCE.buttons.blockQuote, { icon: 'quote', tooltip: 'Block Quote', onAction: toggleBlockQuoteFormatting }], ]); expect(openModal).not.toHaveBeenCalled(); }); @@ -80,7 +84,8 @@ describe('TextEditor hooks', () => { describe('editorConfig', () => { const props = { blockValue: null, - // lmsEndpointUrl: 'sOmEuRl.cOm', + lmsEndpointUrl: 'sOmEuRl.cOm', + studioEndpointUrl: 'sOmEoThEruRl.cOm', }; const evt = 'fakeEvent'; const editor = 'myEditor'; diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx index 459e481fb..928af03bd 100644 --- a/src/editors/containers/TextEditor/index.jsx +++ b/src/editors/containers/TextEditor/index.jsx @@ -39,6 +39,7 @@ export const TextEditor = ({ // redux blockValue, lmsEndpointUrl, + studioEndpointUrl, blockFailed, blockFinished, initializeEditor, @@ -86,6 +87,7 @@ export const TextEditor = ({ openModal, initializeEditor, lmsEndpointUrl, + studioEndpointUrl, setSelection: imageSelection.setSelection, clearSelection: imageSelection.clearSelection, })} @@ -99,6 +101,7 @@ export const TextEditor = ({ TextEditor.defaultProps = { blockValue: null, lmsEndpointUrl: null, + studioEndpointUrl: null, }; TextEditor.propTypes = { onClose: PropTypes.func.isRequired, @@ -107,6 +110,7 @@ TextEditor.propTypes = { data: PropTypes.shape({ data: PropTypes.string }), }), lmsEndpointUrl: PropTypes.string, + studioEndpointUrl: PropTypes.string, blockFailed: PropTypes.bool.isRequired, blockFinished: PropTypes.bool.isRequired, initializeEditor: PropTypes.func.isRequired, @@ -117,6 +121,7 @@ TextEditor.propTypes = { export const mapStateToProps = (state) => ({ blockValue: selectors.app.blockValue(state), lmsEndpointUrl: selectors.app.lmsEndpointUrl(state), + studioEndpointUrl: selectors.app.studioEndpointUrl(state), blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }), blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }), }); diff --git a/src/editors/containers/TextEditor/index.test.jsx b/src/editors/containers/TextEditor/index.test.jsx index 70c4aa61e..34be09ecc 100644 --- a/src/editors/containers/TextEditor/index.test.jsx +++ b/src/editors/containers/TextEditor/index.test.jsx @@ -61,6 +61,7 @@ jest.mock('../../data/redux', () => ({ app: { blockValue: jest.fn(state => ({ blockValue: state })), lmsEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })), + studioEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })), }, requests: { isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })), @@ -75,6 +76,7 @@ describe('TextEditor', () => { // redux blockValue: { data: { some: 'eDiTablE Text' } }, lmsEndpointUrl: 'sOmEvaLue.cOm', + studioEndpointUrl: 'sOmEoThERvaLue.cOm', blockFailed: false, blockFinished: true, initializeEditor: jest.fn().mockName('args.intializeEditor'), diff --git a/src/editors/containers/TextEditor/pluginConfig.js b/src/editors/containers/TextEditor/pluginConfig.js index 6784ab480..b4cfd714f 100644 --- a/src/editors/containers/TextEditor/pluginConfig.js +++ b/src/editors/containers/TextEditor/pluginConfig.js @@ -34,8 +34,8 @@ export default StrictDict({ buttons.outdent, buttons.indent, ], - [buttons.imageUploadButton, buttons.link, buttons.unlink, buttons.table], - [buttons.emoticons, buttons.charmap, buttons.hr], + [buttons.imageUploadButton, buttons.link, buttons.unlink, buttons.blockQuote, buttons.codeBlock], + [buttons.table, buttons.emoticons, buttons.charmap, buttons.hr], [buttons.removeFormat, buttons.code], ]), imageToolbar: mapToolbars([ diff --git a/src/editors/data/constants/tinyMCE.js b/src/editors/data/constants/tinyMCE.js index baeeb67b3..308c06237 100644 --- a/src/editors/data/constants/tinyMCE.js +++ b/src/editors/data/constants/tinyMCE.js @@ -10,6 +10,8 @@ export const commands = StrictDict({ export const buttons = StrictDict({ addImageButton: 'addimagebutton', + blockQuote: 'blockQuote', + codeBlock: 'codeBlock', align: StrictDict({ center: 'aligncenter', justify: 'alignjustify',