fix: display image preview in libraries editor (#1403)
Prior to this commit, the TinyMCE editor image preview only worked in courses, and did not work for content libraries.
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
} from '@openedx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { actions, selectors } from '../../data/redux';
|
||||
import { RequestKeys } from '../../data/constants/requests';
|
||||
|
||||
@@ -24,6 +25,7 @@ const TextEditor = ({
|
||||
// redux
|
||||
showRawEditor,
|
||||
blockValue,
|
||||
blockId,
|
||||
blockFailed,
|
||||
initializeEditor,
|
||||
blockFinished,
|
||||
@@ -40,6 +42,10 @@ const TextEditor = ({
|
||||
learningContextId,
|
||||
});
|
||||
const editorContent = newContent || initialContent;
|
||||
let staticRootUrl;
|
||||
if (isLibrary) {
|
||||
staticRootUrl = `${getConfig().STUDIO_BASE_URL }/library_assets/blocks/${ blockId }/`;
|
||||
}
|
||||
|
||||
if (!refReady) { return null; }
|
||||
|
||||
@@ -65,6 +71,7 @@ const TextEditor = ({
|
||||
images,
|
||||
isLibrary,
|
||||
learningContextId,
|
||||
staticRootUrl,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -107,6 +114,7 @@ TextEditor.propTypes = {
|
||||
blockValue: PropTypes.shape({
|
||||
data: PropTypes.shape({ data: PropTypes.string }),
|
||||
}),
|
||||
blockId: PropTypes.string,
|
||||
blockFailed: PropTypes.bool.isRequired,
|
||||
initializeEditor: PropTypes.func.isRequired,
|
||||
showRawEditor: PropTypes.bool.isRequired,
|
||||
@@ -121,6 +129,7 @@ TextEditor.propTypes = {
|
||||
export const mapStateToProps = (state) => ({
|
||||
blockValue: selectors.app.blockValue(state),
|
||||
blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }),
|
||||
blockId: selectors.app.blockId(state),
|
||||
showRawEditor: selectors.app.showRawEditor(state),
|
||||
blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }),
|
||||
learningContextId: selectors.app.learningContextId(state),
|
||||
|
||||
@@ -59,6 +59,7 @@ jest.mock('../../data/redux', () => ({
|
||||
showRawEditor: jest.fn(state => ({ showRawEditor: state })),
|
||||
images: jest.fn(state => ({ images: state })),
|
||||
isLibrary: jest.fn(state => ({ isLibrary: state })),
|
||||
blockId: jest.fn(state => ({ blockId: state })),
|
||||
learningContextId: jest.fn(state => ({ learningContextId: state })),
|
||||
},
|
||||
requests: {
|
||||
|
||||
@@ -42,6 +42,7 @@ const app = createSlice({
|
||||
blockValue: payload,
|
||||
blockTitle: payload.data.display_name,
|
||||
}),
|
||||
setBlockId: (state, { payload }) => ({ ...state, blockId: payload }),
|
||||
setStudioView: (state, { payload }) => ({ ...state, studioView: payload }),
|
||||
setBlockContent: (state, { payload }) => ({ ...state, blockContent: payload }),
|
||||
setBlockTitle: (state, { payload }) => ({ ...state, blockTitle: payload }),
|
||||
|
||||
@@ -45,6 +45,7 @@ describe('app reducer', () => {
|
||||
['setUnitUrl', 'unitUrl'],
|
||||
['setStudioView', 'studioView'],
|
||||
['setBlockContent', 'blockContent'],
|
||||
['setBlockId', 'blockId'],
|
||||
['setBlockTitle', 'blockTitle'],
|
||||
['setSaveResponse', 'saveResponse'],
|
||||
['setVideos', 'videos'],
|
||||
|
||||
@@ -44,6 +44,7 @@ exports[`TinyMceWidget snapshots ImageUploadModal is not rendered 1`] = `
|
||||
"selection": "hooks.selectedImage.selection",
|
||||
"setEditorRef": undefined,
|
||||
"setSelection": [MockFunction hooks.selectedImage.setSelection],
|
||||
"staticRootUrl": undefined,
|
||||
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
|
||||
"updateContent": [Function],
|
||||
}
|
||||
@@ -112,6 +113,7 @@ exports[`TinyMceWidget snapshots SourcecodeModal is not rendered 1`] = `
|
||||
"selection": "hooks.selectedImage.selection",
|
||||
"setEditorRef": undefined,
|
||||
"setSelection": [MockFunction hooks.selectedImage.setSelection],
|
||||
"staticRootUrl": undefined,
|
||||
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
|
||||
"updateContent": [Function],
|
||||
}
|
||||
@@ -191,6 +193,7 @@ exports[`TinyMceWidget snapshots renders as expected with default behavior 1`] =
|
||||
"selection": "hooks.selectedImage.selection",
|
||||
"setEditorRef": undefined,
|
||||
"setSelection": [MockFunction hooks.selectedImage.setSelection],
|
||||
"staticRootUrl": undefined,
|
||||
"studioEndpointUrl": "sOmEoThERvaLue.cOm",
|
||||
"updateContent": [Function],
|
||||
}
|
||||
|
||||
@@ -84,20 +84,6 @@ export const replaceStaticWithAsset = ({
|
||||
editorType,
|
||||
lmsEndpointUrl,
|
||||
}) => {
|
||||
if (isLibraryKey(learningContextId)) {
|
||||
// This function doesn't currently know how to deal with Library assets.
|
||||
// Libraries don't mangle the path into an asset key–it might be sufficient
|
||||
// to remove the initial "/" in a "/static/images/foo.png" link, and then
|
||||
// set the base URL to the correct ComponentVersion base. If we let this
|
||||
// function try to deal with Library assets, it would convert them in such a
|
||||
// way that it wouldn't convert back later on, and we'd end up storing the
|
||||
// incorrect OLX and breaking the display from that point forward.
|
||||
//
|
||||
// So until we handle it better, just disable static asset URL substitutions
|
||||
// when dealing with Library content.
|
||||
return false;
|
||||
}
|
||||
|
||||
let content = initialContent;
|
||||
let hasChanges = false;
|
||||
const srcs = content.split(/(src="|src="|href="|href=")/g).filter(
|
||||
@@ -116,7 +102,15 @@ export const replaceStaticWithAsset = ({
|
||||
|
||||
// assets in expandable text areas do not support relative urls so all assets must have the lms
|
||||
// endpoint prepended to the relative url
|
||||
if (editorType === 'expandable') {
|
||||
if (isLibraryKey(learningContextId)) {
|
||||
// We are removing the initial "/" in a "/static/foo.png" link, and then
|
||||
// set the base URL to an endpoint serving the draft version of an asset by
|
||||
// its path.
|
||||
/* istanbul ignore next */
|
||||
if (isStatic) {
|
||||
staticFullUrl = assetSrc.substring(1);
|
||||
}
|
||||
} else if (editorType === 'expandable') {
|
||||
if (isCorrectAssetFormat) {
|
||||
staticFullUrl = `${lmsEndpointUrl}${assetSrc}`;
|
||||
} else {
|
||||
@@ -261,9 +255,12 @@ export const editorConfig = ({
|
||||
content,
|
||||
minHeight,
|
||||
learningContextId,
|
||||
staticRootUrl,
|
||||
}) => {
|
||||
const lmsEndpointUrl = getConfig().LMS_BASE_URL;
|
||||
const studioEndpointUrl = getConfig().STUDIO_BASE_URL;
|
||||
|
||||
const baseURL = staticRootUrl || lmsEndpointUrl;
|
||||
const {
|
||||
toolbar,
|
||||
config,
|
||||
@@ -290,7 +287,7 @@ export const editorConfig = ({
|
||||
min_height: minHeight,
|
||||
contextmenu: 'link table',
|
||||
directionality: isLocaleRtl ? 'rtl' : 'ltr',
|
||||
document_base_url: lmsEndpointUrl,
|
||||
document_base_url: baseURL,
|
||||
imagetools_cors_hosts: [removeProtocolFromUrl(lmsEndpointUrl), removeProtocolFromUrl(studioEndpointUrl)],
|
||||
imagetools_toolbar: imageToolbar,
|
||||
formats: { label: { inline: 'label' } },
|
||||
@@ -436,6 +433,17 @@ export const setAssetToStaticUrl = ({ editorValue, lmsEndpointUrl }) => {
|
||||
const updatedContent = content.replace(currentSrc, portableUrl);
|
||||
content = updatedContent;
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
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 currentSrc = src.substring(0, src.search(/("|")/));
|
||||
const updatedContent = content.replace(currentSrc, portableUrl);
|
||||
content = updatedContent;
|
||||
});
|
||||
return content;
|
||||
};
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ const TinyMceWidget = ({
|
||||
images,
|
||||
isLibrary,
|
||||
onChange,
|
||||
staticRootUrl,
|
||||
...editorConfig
|
||||
}) => {
|
||||
const { isImgOpen, openImgModal, closeImgModal } = hooks.imgModalToggle();
|
||||
@@ -85,6 +86,7 @@ const TinyMceWidget = ({
|
||||
learningContextId,
|
||||
images: imagesRef,
|
||||
editorContentHtml,
|
||||
staticRootUrl,
|
||||
...imageSelection,
|
||||
...editorConfig,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user