diff --git a/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java b/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java index c3938204abbba66e3117756687158de65e936654..0154b61011616c477c5d894527c2e5b0fda8bb10 100644 --- a/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java +++ b/src/main/java/org/olat/ims/qti21/manager/archive/QTI21ArchiveFormat.java @@ -49,6 +49,7 @@ import org.olat.core.util.Formatter; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.core.util.ZipUtil; +import org.olat.core.util.filter.FilterFactory; import org.olat.core.util.io.ShieldOutputStream; import org.olat.core.util.openxml.OpenXMLWorkbook; import org.olat.core.util.openxml.OpenXMLWorkbookResource; @@ -623,7 +624,7 @@ public class QTI21ArchiveFormat { } } if (exportConfig.isCommentCol()) { - dataRow.addCell(col++, itemSession.getCoachComment(), null); + dataRow.addCell(col++, getCoachComment(itemSession), null); } if (exportConfig.isTimeCols()) { if (anonymizerCallback == null){ @@ -646,6 +647,16 @@ public class QTI21ArchiveFormat { } } + private String getCoachComment(AssessmentItemSession itemSession) { + if(itemSession == null || !StringHelper.containsNonWhitespace(itemSession.getCoachComment())) return null; + + String comment = itemSession.getCoachComment(); + if(StringHelper.isHtml(comment)) { + comment = FilterFactory.getHtmlTagAndDescapingFilter().filter(comment); + } + return comment; + } + private BigDecimal calculateSectionScore(SessionResponses responses, SectionInfos section) { BigDecimal sectionScore = BigDecimal.valueOf(0l); diff --git a/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html b/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html index b22828353ac582f8a297517be20e598ce6715ed1..eb2979d8f7c272121cb7472bd06cd780457d26e0 100644 --- a/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html +++ b/src/main/java/org/olat/ims/qti21/ui/_content/assessment_results.html @@ -481,7 +481,7 @@ #if($r.isNotEmpty($itemResult.comment)) <div class="o_sel_assessmentitem_comment o_qti_item_comment"> <h4>$r.translate("results.comment")</h4> - $r.escapeHtml($itemResult.comment) + $r.xssScan($itemResult.comment) </div> #end diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityInteractionsController.java b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityInteractionsController.java index 9df4448b13feb680cc1ba7bdc3002d9b0aa0cdfe..013f21af421d29a0a45fd6b10113d9b3dc42f725 100644 --- a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityInteractionsController.java +++ b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityInteractionsController.java @@ -32,6 +32,7 @@ import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.elements.RichTextElement; import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.Form; @@ -41,6 +42,7 @@ import org.olat.core.gui.components.form.flexible.impl.FormJSHelper; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.elements.FormCancel; import org.olat.core.gui.components.form.flexible.impl.elements.FormSubmit; +import org.olat.core.gui.components.form.flexible.impl.elements.richText.TextMode; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -106,12 +108,11 @@ public class CorrectionIdentityInteractionsController extends FormBasicControlle private static final String[] onKeys = new String[] { "on" }; private TextElement scoreEl; - private TextElement commentEl; + private RichTextElement commentEl; private StaticTextElement statusEl; private FormLink viewSolutionButton; private FormLink overrideScoreButton; private FormLink viewCorrectSolutionButton; - private ItemBodyResultFormItem answerItem; private ItemBodyResultFormItem solutionItem; private FeedbackResultFormItem correctSolutionItem; private MultipleSelectionElement toReviewEl; @@ -180,7 +181,7 @@ public class CorrectionIdentityInteractionsController extends FormBasicControlle AssessmentTestSession testSession = correction.getTestSession(); TestSessionState testSessionState = correction.getTestSessionState(); - answerItem = initFormInteraction(testPlanNodeKey, testSessionState, testSession, formLayout, true, false); + ItemBodyResultFormItem answerItem = initFormInteraction(testPlanNodeKey, testSessionState, testSession, formLayout, true, false); formLayout.add("answer", answerItem); viewSolutionButton = uifactory.addFormLink("view.solution", formLayout); @@ -258,7 +259,10 @@ public class CorrectionIdentityInteractionsController extends FormBasicControlle overrideScoreButton.setDomReplacementWrapperRequired(false); overrideScoreButton.setVisible(!readOnly); } - commentEl = uifactory.addTextAreaElement("commentItem", "comment", 2500, 4, 60, false, false, coachComment, scoreCont); + commentEl = uifactory.addRichTextElementForStringData("commentItem", "comment", coachComment, 8, -1, + false, null, null, null, scoreCont, ureq.getUserSession(), getWindowControl()); + commentEl.getEditorConfiguration().setSimplestTextModeAllowed(TextMode.multiLine); + commentEl.getEditorConfiguration().setPathInStatusBar(false); commentEl.setHelpText(translate("comment.help")); commentEl.setEnabled(!readOnly); IdentityAssessmentItemWrapper wrapper = new IdentityAssessmentItemWrapper(fullname, assessmentItem, correction, responseItems,