feat: remove the ability to use image tools for content libraries
This commit is contained in:
@@ -1,5 +1,74 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TextEditor snapshots ImageUploadModal is not rendered 1`] = `
|
||||
<EditorContainer
|
||||
getContent={
|
||||
Object {
|
||||
"getContent": Object {
|
||||
"editorRef": Object {
|
||||
"current": Object {
|
||||
"value": "something",
|
||||
},
|
||||
},
|
||||
"isRaw": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
onClose={[MockFunction props.onClose]}
|
||||
>
|
||||
<div
|
||||
className="editor-body h-75 overflow-auto"
|
||||
>
|
||||
<SourceCodeModal
|
||||
close={[MockFunction modal.closeModal]}
|
||||
editorRef={
|
||||
Object {
|
||||
"current": Object {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
isOpen={false}
|
||||
/>
|
||||
<Toast
|
||||
onClose={[MockFunction hooks.nullMethod]}
|
||||
show={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error: Could Not Load Text Content"
|
||||
description="Error Message Dispayed When HTML content fails to Load"
|
||||
id="authoring.texteditor.load.error"
|
||||
/>
|
||||
</Toast>
|
||||
<Editor
|
||||
editorConfig={
|
||||
Object {
|
||||
"blockValue": Object {
|
||||
"data": Object {
|
||||
"some": "eDiTablE Text",
|
||||
},
|
||||
},
|
||||
"clearSelection": [MockFunction hooks.selectedImage.clearSelection],
|
||||
"images": Object {
|
||||
"sOmEuiMAge": Object {
|
||||
"staTICUrl": "/assets/sOmEuiMAge",
|
||||
},
|
||||
},
|
||||
"initializeEditor": [MockFunction args.intializeEditor],
|
||||
"isLibrary": true,
|
||||
"lmsEndpointUrl": "sOmEvaLue.cOm",
|
||||
"openImgModal": [MockFunction modal.openModal],
|
||||
"openSourceCodeModal": [MockFunction modal.openModal],
|
||||
"setEditorRef": [MockFunction hooks.prepareEditorRef.setEditorRef],
|
||||
"setSelection": [MockFunction hooks.selectedImage.setSelection],
|
||||
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
`;
|
||||
|
||||
exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
|
||||
<EditorContainer
|
||||
getContent={
|
||||
@@ -76,6 +145,7 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
|
||||
},
|
||||
},
|
||||
"initializeEditor": [MockFunction args.intializeEditor],
|
||||
"isLibrary": false,
|
||||
"lmsEndpointUrl": "sOmEvaLue.cOm",
|
||||
"openImgModal": [MockFunction modal.openModal],
|
||||
"openSourceCodeModal": [MockFunction modal.openModal],
|
||||
@@ -313,6 +383,7 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = `
|
||||
},
|
||||
},
|
||||
"initializeEditor": [MockFunction args.intializeEditor],
|
||||
"isLibrary": false,
|
||||
"lmsEndpointUrl": "sOmEvaLue.cOm",
|
||||
"openImgModal": [MockFunction modal.openModal],
|
||||
"openSourceCodeModal": [MockFunction modal.openModal],
|
||||
|
||||
@@ -100,6 +100,7 @@ export const editorConfig = ({
|
||||
setSelection,
|
||||
studioEndpointUrl,
|
||||
images,
|
||||
isLibrary,
|
||||
}) => ({
|
||||
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: '*[*]',
|
||||
},
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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}
|
||||
>
|
||||
<div className="editor-body h-75 overflow-auto">
|
||||
<ImageUploadModal
|
||||
isOpen={isImgOpen}
|
||||
close={closeImgModal}
|
||||
editorRef={editorRef}
|
||||
images={images}
|
||||
{...imageSelection}
|
||||
/>
|
||||
{isLibrary ? null : (
|
||||
<ImageUploadModal
|
||||
isOpen={isImgOpen}
|
||||
close={closeImgModal}
|
||||
editorRef={editorRef}
|
||||
images={images}
|
||||
{...imageSelection}
|
||||
/>
|
||||
)}
|
||||
<SourceCodeModal
|
||||
isOpen={isSourceCodeOpen}
|
||||
close={closeSourceCodeModal}
|
||||
@@ -125,6 +129,7 @@ export const TextEditor = ({
|
||||
TextEditor.defaultProps = {
|
||||
blockValue: null,
|
||||
isRaw: null,
|
||||
isLibrary: null,
|
||||
lmsEndpointUrl: null,
|
||||
studioEndpointUrl: null,
|
||||
images: null,
|
||||
@@ -141,6 +146,7 @@ TextEditor.propTypes = {
|
||||
blockFailed: PropTypes.bool.isRequired,
|
||||
initializeEditor: PropTypes.func.isRequired,
|
||||
isRaw: PropTypes.bool,
|
||||
isLibrary: PropTypes.bool,
|
||||
imagesFinished: PropTypes.bool,
|
||||
images: PropTypes.shape({}),
|
||||
// inject
|
||||
@@ -153,6 +159,7 @@ export const mapStateToProps = (state) => ({
|
||||
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),
|
||||
});
|
||||
|
||||
@@ -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(<TextEditor {...props} blockFailed />)).toMatchSnapshot();
|
||||
});
|
||||
test('ImageUploadModal is not rendered', () => {
|
||||
expect(shallow(<TextEditor {...props} isLibrary />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('mapStateToProps', () => {
|
||||
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
|
||||
test('blockValue from app.blockValue', () => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user