Merge branch 'main' into kenclary/TNL-9943

This commit is contained in:
kenclary
2022-05-25 17:23:07 -04:00
committed by GitHub
7 changed files with 42 additions and 5 deletions

View File

@@ -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",
}
}
/>

View File

@@ -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)],
},
});

View File

@@ -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';

View File

@@ -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 }),
});

View File

@@ -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'),

View File

@@ -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([

View File

@@ -10,6 +10,8 @@ export const commands = StrictDict({
export const buttons = StrictDict({
addImageButton: 'addimagebutton',
blockQuote: 'blockQuote',
codeBlock: 'codeBlock',
align: StrictDict({
center: 'aligncenter',
justify: 'alignjustify',