fix editor deleting description (#444)

internal issue: https://2u-internal.atlassian.net/browse/TNL-11311

This fixes a bug where the editor was deleting the OLX tag when editing in the simple editor and then saving.
Also the description was being converted to em for the simple editor, but then not converted back. However, the xblock renders label and then em in reverse order for some reason.
To fix it, the em gets converted back to description now, but not for every em tag (added a class "olx_description" for the tags that should be converted).
This commit is contained in:
Jesper Hodge
2023-12-20 16:44:27 -05:00
committed by GitHub
parent 47a3fd6836
commit 50c580cca2
5 changed files with 75 additions and 25 deletions

View File

@@ -193,29 +193,31 @@ class ReactStateOLXParser {
/** addQuestion()
* The editorObject saved to the class constuctor is parsed for the attribute question. The question is parsed and
* checked for label tags. After the question is fully updated, the questionObject is returned.
* checked for label and em tags. After the question is fully updated, the questionObject is returned.
* TODO: this is very brittle and unreliable. Needs improvement.
* @return {object} object representaion of question
*/
addQuestion() {
const { question } = this.editorObject;
const questionObject = this.richTextParser.parse(question);
/* Removes block tags like <p> or <h1> that surround the <label> format.
/* Removes block tags like <p> or <h1> that surround the <label> or <em> format.
Block tags are required by tinyMCE but have adverse effect on css in studio.
*/
questionObject.forEach((tag, ind) => {
const tagName = Object.keys(tag)[0];
let label = null;
tag[tagName].forEach(subTag => {
const subTagName = Object.keys(subTag)[0];
if (subTagName === 'label') {
label = subTag;
}
});
if (label) {
questionObject[ind] = label;
const resultQuestion = [];
const relevantSubnodes = ['label', 'em'];
questionObject.forEach((tag) => {
const subNodes = Object.values(tag)[0];
const containsRelevantSubnodes = subNodes.some(subNode => relevantSubnodes.includes(Object.keys(subNode)[0]));
if (!containsRelevantSubnodes) {
resultQuestion.push(tag);
} else {
resultQuestion.push(...subNodes);
}
});
return questionObject;
return resultQuestion;
}
/** buildMultiSelectProblem()
@@ -259,13 +261,22 @@ class ReactStateOLXParser {
default:
break;
}
const updatedString = `${problemTypeTag}\n${questionString}`;
const questionStringWithEmDescriptionReplace = this.replaceEmWithDescriptionTag(questionString);
const updatedString = `${problemTypeTag}\n${questionStringWithEmDescriptionReplace}`;
const problemBodyString = problemBody.replace(problemTypeTag, updatedString);
const fullProblemString = `<problem>${problemBodyString}${hintString}\n</problem>`;
return fullProblemString;
}
replaceEmWithDescriptionTag(xmlString) {
const regexPattern = /<em class="olx_description">(.*?)<\/em>/g;
const replacement = '<description>$1</description>';
const updatedHtml = xmlString.replace(regexPattern, replacement);
return updatedHtml;
}
/** buildTextInput()
* String response OLX builder. The question builder has a different format than the
* other parts (demand hint, answers, and solution) of the problem so it has to be