From 4e69fffbef4fa25caa533e1416ea9b99d57e9489 Mon Sep 17 00:00:00 2001 From: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com> Date: Tue, 30 Aug 2022 16:40:17 -0400 Subject: [PATCH] feat: remove the ability to use image tools for content libraries --- .../__snapshots__/index.test.jsx.snap | 71 +++++++++++ src/editors/containers/TextEditor/hooks.js | 9 +- .../containers/TextEditor/hooks.test.jsx | 11 +- src/editors/containers/TextEditor/index.jsx | 21 ++-- .../containers/TextEditor/index.test.jsx | 6 + .../containers/TextEditor/pluginConfig.js | 111 ++++++++++-------- src/editors/data/redux/app/selectors.js | 14 +++ src/editors/data/redux/app/selectors.test.js | 19 +++ 8 files changed, 196 insertions(+), 66 deletions(-) diff --git a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap index afc1f02f6..df4497eb1 100644 --- a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap @@ -1,5 +1,74 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`TextEditor snapshots ImageUploadModal is not rendered 1`] = ` + +
+ + + + + +
+
+`; + exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` ({ onInit: (evt, editor) => { setEditorRef(editor); @@ -107,7 +108,7 @@ export const editorConfig = ({ }, initialValue: blockValue ? blockValue.data.data : '', init: { - ...pluginConfig.config, + ...pluginConfig(isLibrary).config, skin: false, content_css: false, content_style: tinyMCEStyles, @@ -115,14 +116,14 @@ export const editorConfig = ({ document_base_url: lmsEndpointUrl, init_instance_callback: module.checkRelativeUrl(module.fetchImageUrls(images)), imagetools_cors_hosts: [removeProtocolFromUrl(lmsEndpointUrl), removeProtocolFromUrl(studioEndpointUrl)], - imagetools_toolbar: pluginConfig.imageToolbar, - plugins: pluginConfig.plugins, + imagetools_toolbar: pluginConfig(isLibrary).imageToolbar, + plugins: pluginConfig(isLibrary).plugins, setup: module.setupCustomBehavior({ openImgModal, openSourceCodeModal, setImage: setSelection, }), - toolbar: pluginConfig.toolbar, + toolbar: pluginConfig(isLibrary).toolbar, valid_children: '+body[style]', valid_elements: '*[*]', }, diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx index ce9e4060e..15e276b78 100644 --- a/src/editors/containers/TextEditor/hooks.test.jsx +++ b/src/editors/containers/TextEditor/hooks.test.jsx @@ -107,6 +107,7 @@ describe('TextEditor hooks', () => { lmsEndpointUrl: 'sOmEuRl.cOm', studioEndpointUrl: 'sOmEoThEruRl.cOm', images: { sOmEuiMAge: { staTICUrl: '/assets/sOmEuiMAge' } }, + isLibrary: false, }; const evt = 'fakeEvent'; const editor = 'myEditor'; @@ -135,11 +136,11 @@ describe('TextEditor hooks', () => { expect(output.initialValue).toBe(htmltext); }); test('It configures plugins and toolbars correctly', () => { - expect(output.init.plugins).toEqual(pluginConfig.plugins); - expect(output.init.imagetools_toolbar).toEqual(pluginConfig.imageToolbar); - expect(output.init.toolbar).toEqual(pluginConfig.toolbar); - Object.keys(pluginConfig.config).forEach(key => { - expect(output.init[key]).toEqual(pluginConfig.config[key]); + expect(output.init.plugins).toEqual(pluginConfig(props.isLibrary).plugins); + expect(output.init.imagetools_toolbar).toEqual(pluginConfig(props.isLibrary).imageToolbar); + expect(output.init.toolbar).toEqual(pluginConfig(props.isLibrary).toolbar); + Object.keys(pluginConfig(props.isLibrary).config).forEach(key => { + expect(output.init[key]).toEqual(pluginConfig(props.isLibrary).config[key]); }); // Commented out as we investigate whether this is only needed for image proxy // expect(output.init.imagetools_cors_hosts).toMatchObject([props.lmsEndpointUrl]); diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx index 21db092ac..524b0b0e4 100644 --- a/src/editors/containers/TextEditor/index.jsx +++ b/src/editors/containers/TextEditor/index.jsx @@ -40,6 +40,7 @@ export const TextEditor = ({ onClose, // redux isRaw, + isLibrary, blockValue, lmsEndpointUrl, studioEndpointUrl, @@ -76,6 +77,7 @@ export const TextEditor = ({ initializeEditor, lmsEndpointUrl, studioEndpointUrl, + isLibrary, images, setSelection: imageSelection.setSelection, clearSelection: imageSelection.clearSelection, @@ -90,13 +92,15 @@ export const TextEditor = ({ onClose={onClose} >
- + {isLibrary ? null : ( + + )} ({ studioEndpointUrl: selectors.app.studioEndpointUrl(state), blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }), isRaw: selectors.app.isRaw(state), + isLibrary: selectors.app.isLibrary(state), imagesFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchImages }), images: selectors.app.images(state), }); diff --git a/src/editors/containers/TextEditor/index.test.jsx b/src/editors/containers/TextEditor/index.test.jsx index 26372dc3b..718f2de1b 100644 --- a/src/editors/containers/TextEditor/index.test.jsx +++ b/src/editors/containers/TextEditor/index.test.jsx @@ -71,6 +71,7 @@ jest.mock('../../data/redux', () => ({ studioEndpointUrl: jest.fn(state => ({ studioEndpointUrl: state })), isRaw: jest.fn(state => ({ isRaw: state })), images: jest.fn(state => ({ images: state })), + isLibrary: jest.fn(state => ({ isLibrary: state })), }, requests: { isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })), @@ -89,6 +90,7 @@ describe('TextEditor', () => { blockFailed: false, initializeEditor: jest.fn().mockName('args.intializeEditor'), isRaw: false, + isLibrary: false, imagesFinished: true, images: { sOmEuiMAge: { staTICUrl: '/assets/sOmEuiMAge' } }, // inject @@ -117,7 +119,11 @@ describe('TextEditor', () => { test('block failed to load, Toast is shown', () => { expect(shallow()).toMatchSnapshot(); }); + test('ImageUploadModal is not rendered', () => { + expect(shallow()).toMatchSnapshot(); + }); }); + describe('mapStateToProps', () => { const testState = { A: 'pple', B: 'anana', C: 'ucumber' }; test('blockValue from app.blockValue', () => { diff --git a/src/editors/containers/TextEditor/pluginConfig.js b/src/editors/containers/TextEditor/pluginConfig.js index 7bef74375..d1b46b0fb 100644 --- a/src/editors/containers/TextEditor/pluginConfig.js +++ b/src/editors/containers/TextEditor/pluginConfig.js @@ -3,53 +3,64 @@ import { buttons, plugins } from '../../data/constants/tinyMCE'; const mapToolbars = toolbars => toolbars.map(toolbar => toolbar.join(' ')).join(' | '); -export default StrictDict({ - plugins: [ - plugins.link, - plugins.lists, - plugins.codesample, - plugins.emoticons, - plugins.table, - plugins.hr, - plugins.charmap, - plugins.code, - plugins.autoresize, - plugins.image, - plugins.imagetools, - ].join(' '), - menubar: false, - toolbar: mapToolbars([ - [buttons.undo, buttons.redo], - [buttons.formatSelect], - [buttons.bold, buttons.italic, buttons.underline, buttons.foreColor, buttons.backColor], - [ - buttons.align.left, - buttons.align.center, - buttons.align.right, - buttons.align.justify, - ], - [ - buttons.bullist, - buttons.numlist, - buttons.outdent, - buttons.indent, - ], - [buttons.imageUploadButton, buttons.link, buttons.unlink, buttons.blockQuote, buttons.codeBlock], - [buttons.table, buttons.emoticons, buttons.charmap, buttons.hr], - [buttons.removeFormat, buttons.code], - ]), - imageToolbar: mapToolbars([ - // [buttons.rotate.left, buttons.rotate.right], - // [buttons.flip.horiz, buttons.flip.vert], - [buttons.editImageSettings], - ]), - config: { - branding: false, - height: '100%', - menubar: false, - min_height: 500, - toolbar_sticky: true, - relative_urls: true, - convert_urls: false, - }, -}); +const pluginConfig = (isLibrary) => { + const image = isLibrary ? '' : plugins.image; + const imageTools = isLibrary ? '' : plugins.imagetools; + const imageUploadButton = isLibrary ? '' : buttons.imageUploadButton; + const editImageSettings = isLibrary ? '' : buttons.editImageSettings; + + return ( + StrictDict({ + plugins: [ + plugins.link, + plugins.lists, + plugins.codesample, + plugins.emoticons, + plugins.table, + plugins.hr, + plugins.charmap, + plugins.code, + plugins.autoresize, + image, + imageTools, + ].join(' '), + menubar: false, + toolbar: mapToolbars([ + [buttons.undo, buttons.redo], + [buttons.formatSelect], + [buttons.bold, buttons.italic, buttons.underline, buttons.foreColor, buttons.backColor], + [ + buttons.align.left, + buttons.align.center, + buttons.align.right, + buttons.align.justify, + ], + [ + buttons.bullist, + buttons.numlist, + buttons.outdent, + buttons.indent, + ], + [imageUploadButton, buttons.link, buttons.unlink, buttons.blockQuote, buttons.codeBlock], + [buttons.table, buttons.emoticons, buttons.charmap, buttons.hr], + [buttons.removeFormat, buttons.code], + ]), + imageToolbar: mapToolbars([ + // [buttons.rotate.left, buttons.rotate.right], + // [buttons.flip.horiz, buttons.flip.vert], + [editImageSettings], + ]), + config: { + branding: false, + height: '100%', + menubar: false, + min_height: 500, + toolbar_sticky: true, + relative_urls: true, + convert_urls: false, + }, + }) + ); +}; + +export default pluginConfig; diff --git a/src/editors/data/redux/app/selectors.js b/src/editors/data/redux/app/selectors.js index d828a9ec4..f9e11f8d7 100644 --- a/src/editors/data/redux/app/selectors.js +++ b/src/editors/data/redux/app/selectors.js @@ -82,6 +82,19 @@ export const isRaw = createSelector( }, ); +export const isLibrary = createSelector( + [module.simpleSelectors.learningContextId], + (learningContextId) => { + if (!learningContextId) { + return null; + } + if (learningContextId && learningContextId.startsWith('library-v1')) { + return true; + } + return false; + }, +); + export default { ...simpleSelectors, isInitialized, @@ -89,4 +102,5 @@ export default { displayTitle, analytics, isRaw, + isLibrary, }; diff --git a/src/editors/data/redux/app/selectors.test.js b/src/editors/data/redux/app/selectors.test.js index eb05f2375..1b42fd26f 100644 --- a/src/editors/data/redux/app/selectors.test.js +++ b/src/editors/data/redux/app/selectors.test.js @@ -140,4 +140,23 @@ describe('app selectors unit tests', () => { expect(selectors.isRaw.cb(studioViewVisual)).toEqual(false); }); }); + + describe('isLibrary', () => { + const learningContextIdLibrary = 'library-v1:name'; + const learningContextIdCourse = 'course-v1:name'; + it('is memoized based on studioView', () => { + expect(selectors.isLibrary.preSelectors).toEqual([ + simpleSelectors.learningContextId, + ]); + }); + it('returns null if blockId is null', () => { + expect(selectors.isLibrary.cb(null)).toEqual(null); + }); + it('returns true if blockId starts with lib', () => { + expect(selectors.isLibrary.cb(learningContextIdLibrary)).toEqual(true); + }); + it('returns false if the blockId does not start with lib', () => { + expect(selectors.isLibrary.cb(learningContextIdCourse)).toEqual(false); + }); + }); });