fix: image rendering in single and multi select problems (#1731)
Fix images in single and multi select problems in libraries. Found following issues and fixed them: * Images were not being rendered in any of the fields in these problems. * Base url was not being set which is used by tinymce to load images with relative path. * Answer fields were set to inline mode which does not initialize images or base paths * If same image twice is used twice in a problem, the logic of replacing `static/image.jpg` with `/static/image.jpg` would replace the first occurrence twice resulting in `//static/image.jpg`, breaking both the links. * On initialization of answer fields, the absolute static asset urls were being replaced by relative urls causing the editor being set as dirty without user changes.
This commit is contained in:
@@ -9,12 +9,14 @@ exports[`ExpandableTextArea snapshots renders as expected with default behavior
|
||||
editorContentHtml="text"
|
||||
editorRef={
|
||||
{
|
||||
"current": null,
|
||||
"current": {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
editorType="expandable"
|
||||
placeholder={null}
|
||||
setEditorRef={[Function]}
|
||||
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
|
||||
updateContent={[MockFunction]}
|
||||
/>
|
||||
</div>
|
||||
@@ -30,12 +32,14 @@ exports[`ExpandableTextArea snapshots renders error message 1`] = `
|
||||
editorContentHtml="text"
|
||||
editorRef={
|
||||
{
|
||||
"current": null,
|
||||
"current": {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
editorType="expandable"
|
||||
placeholder={null}
|
||||
setEditorRef={[Function]}
|
||||
setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]}
|
||||
updateContent={[MockFunction]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -11,8 +11,9 @@ const ExpandableTextArea = ({
|
||||
errorMessage,
|
||||
...props
|
||||
}) => {
|
||||
const { editorRef, setEditorRef } = prepareEditorRef();
|
||||
const { editorRef, refReady, setEditorRef } = prepareEditorRef();
|
||||
|
||||
if (!refReady) { return null; }
|
||||
return (
|
||||
<>
|
||||
<div className="expandable-mce error">
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
margin: 16px 40px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*[contentEditable="false"] {
|
||||
outline: 1px solid #D7D3D1;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,15 @@ jest.mock('@tinymce/tinymce-react', () => {
|
||||
|
||||
jest.mock('../TinyMceWidget', () => 'TinyMceWidget');
|
||||
|
||||
// Mock the TinyMceWidget
|
||||
jest.mock('../TinyMceWidget/hooks', () => ({
|
||||
prepareEditorRef: jest.fn(() => ({
|
||||
editorRef: { current: { value: 'something' } },
|
||||
refReady: true,
|
||||
setEditorRef: jest.fn().mockName('hooks.prepareEditorRef.setEditorRef'),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('ExpandableTextArea', () => {
|
||||
const props = {
|
||||
value: 'text',
|
||||
|
||||
@@ -250,7 +250,12 @@ export const setupCustomBehavior = ({
|
||||
lmsEndpointUrl,
|
||||
learningContextId,
|
||||
});
|
||||
if (newContent) { updateContent(newContent); }
|
||||
// istanbul ignore if
|
||||
if (newContent) {
|
||||
// update content but mark as not dirty as user did not change anything
|
||||
updateContent(newContent, false);
|
||||
editor.setDirty(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -479,14 +484,21 @@ export const setAssetToStaticUrl = ({ editorValue, lmsEndpointUrl }) => {
|
||||
content = updatedContent;
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
const updatedStaticUrls = [];
|
||||
assetSrcs.filter(src => src.startsWith('static/')).forEach(src => {
|
||||
// Before storing assets we make sure that library static assets points again to
|
||||
// `/static/dummy.jpg` instead of using the relative url `static/dummy.jpg`
|
||||
const nameFromEditorSrc = parseAssetName(src);
|
||||
const portableUrl = `/${ nameFromEditorSrc}`;
|
||||
const portableUrl = `/${nameFromEditorSrc}`;
|
||||
if (updatedStaticUrls.includes(portableUrl)) {
|
||||
// If same image is used multiple times in the same src,
|
||||
// replace all occurence once and do not process them again.
|
||||
return;
|
||||
}
|
||||
// track updated urls to process only once.
|
||||
updatedStaticUrls.push(portableUrl);
|
||||
const currentSrc = src.substring(0, src.search(/("|")/));
|
||||
const updatedContent = content.replace(currentSrc, portableUrl);
|
||||
const updatedContent = content.replaceAll(currentSrc, portableUrl);
|
||||
content = updatedContent;
|
||||
});
|
||||
return content;
|
||||
|
||||
@@ -221,6 +221,12 @@ describe('TinyMceEditor hooks', () => {
|
||||
const content = module.setAssetToStaticUrl({ editorValue, lmsEndpointUrl });
|
||||
expect(content).toEqual('<img src="/static/soME_ImagE_URl1"/> <a href="/static/soMEImagEURl">testing link</a>');
|
||||
});
|
||||
it('returns content with updated static img links', () => {
|
||||
const editorValue = '<img src="static/goku.img"/> <a href="static/goku.img">testing link</a>';
|
||||
const lmsEndpointUrl = getConfig().LMS_BASE_URL;
|
||||
const content = module.setAssetToStaticUrl({ editorValue, lmsEndpointUrl });
|
||||
expect(content).toEqual('<img src="/static/goku.img"/> <a href="/static/goku.img">testing link</a>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('editorConfig', () => {
|
||||
|
||||
@@ -12,8 +12,9 @@ const pluginConfig = ({ placeholder, editorType, enableImageUpload }) => {
|
||||
const codeButton = editorType === 'text' ? buttons.code : '';
|
||||
const labelButton = editorType === 'question' ? buttons.customLabelButton : '';
|
||||
const quickToolbar = editorType === 'expandable' ? plugins.quickbars : '';
|
||||
const inline = editorType === 'expandable';
|
||||
const statusbar = editorType !== 'expandable';
|
||||
const toolbar = editorType !== 'expandable';
|
||||
const autoresizeBottomMargin = editorType === 'expandable' ? 10 : 50;
|
||||
const defaultFormat = (editorType === 'question' || editorType === 'expandable') ? 'div' : 'p';
|
||||
const hasStudioHeader = document.querySelector('.studio-header');
|
||||
|
||||
@@ -90,13 +91,14 @@ const pluginConfig = ({ placeholder, editorType, enableImageUpload }) => {
|
||||
relative_urls: true,
|
||||
convert_urls: false,
|
||||
placeholder,
|
||||
inline,
|
||||
statusbar,
|
||||
block_formats: 'Header 1=h1;Header 2=h2;Header 3=h3;Header 4=h4;Header 5=h5;Header 6=h6;Div=div;Paragraph=p;Preformatted=pre',
|
||||
forced_root_block: defaultFormat,
|
||||
powerpaste_allow_local_images: true,
|
||||
powerpaste_word_import: 'prompt',
|
||||
powerpaste_html_import: 'prompt',
|
||||
powerpaste_googledoc_import: 'prompt',
|
||||
autoresize_bottom_margin: autoresizeBottomMargin,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user