diff --git a/src/main/java/org/olat/ims/qti/resultexport/QTI21ResultsExportMediaResource.java b/src/main/java/org/olat/ims/qti/resultexport/QTI21ResultsExportMediaResource.java index 02f7972c8f7c600b03d4f3fc47d659962d6ee55a..4357f9b831553dc31071c8d01e1ee4199d60dba4 100644 --- a/src/main/java/org/olat/ims/qti/resultexport/QTI21ResultsExportMediaResource.java +++ b/src/main/java/org/olat/ims/qti/resultexport/QTI21ResultsExportMediaResource.java @@ -193,7 +193,7 @@ public class QTI21ResultsExportMediaResource implements MediaResource { Controller assessmentResultController = new AssessmentResultController( ureq, mockwControl, identity, false, session, - ShowResultsOnFinish.details, fUnzippedDirRoot, null); + ShowResultsOnFinish.details, fUnzippedDirRoot, null, false); Component component = assessmentResultController.getInitialComponent(); String componentHTML = createResultHTML(component); diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java index efd993a6fc3c3f9d33dbc12b485c80907638b29a..a6bcd9a3ed140deb236634096bb7438dee69a568 100644 --- a/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java +++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentResultController.java @@ -29,11 +29,14 @@ import java.util.Map; import org.olat.admin.user.UserShortDescription; import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.Component; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.creator.ControllerCreator; import org.olat.core.id.Identity; import org.olat.core.util.StringHelper; import org.olat.course.assessment.AssessmentHelper; @@ -49,9 +52,12 @@ import org.olat.ims.qti21.ui.components.InteractionResultFormItem; import org.springframework.beans.factory.annotation.Autowired; import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem; +import uk.ac.ed.ph.jqtiplus.node.item.interaction.DrawingInteraction; import uk.ac.ed.ph.jqtiplus.node.item.interaction.EndAttemptInteraction; +import uk.ac.ed.ph.jqtiplus.node.item.interaction.ExtendedTextInteraction; import uk.ac.ed.ph.jqtiplus.node.item.interaction.Interaction; import uk.ac.ed.ph.jqtiplus.node.item.interaction.PositionObjectInteraction; +import uk.ac.ed.ph.jqtiplus.node.item.interaction.UploadInteraction; import uk.ac.ed.ph.jqtiplus.node.result.AssessmentResult; import uk.ac.ed.ph.jqtiplus.node.result.ItemResult; import uk.ac.ed.ph.jqtiplus.node.result.ItemVariable; @@ -87,10 +93,14 @@ public class AssessmentResultController extends FormBasicController { private final ShowResultsOnFinish resultsOnfinish; private final boolean anonym; + private final boolean withPrint; + private final Identity assessedIdentity; private final TestSessionState testSessionState; private final AssessmentResult assessmentResult; + private final AssessmentTestSession candidateSession; private final CandidateSessionContext candidateSessionContext; + private final File fUnzippedDirRoot; private final URI assessmentObjectUri; private final ResourceLocator inputResourceLocator; private final ResolvedAssessmentTest resolvedAssessmentTest; @@ -102,12 +112,17 @@ public class AssessmentResultController extends FormBasicController { private QTI21Service qtiService; public AssessmentResultController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity, boolean anonym, - AssessmentTestSession candidateSession, ShowResultsOnFinish resultsOnfinish, File fUnzippedDirRoot, String mapperUri) { + AssessmentTestSession candidateSession, ShowResultsOnFinish resultsOnfinish, File fUnzippedDirRoot, String mapperUri, + boolean withPrint) { super(ureq, wControl, "assessment_results"); this.anonym = anonym; this.mapperUri = mapperUri; + this.withPrint = withPrint; this.resultsOnfinish = resultsOnfinish; + this.assessedIdentity = assessedIdentity; + this.candidateSession = candidateSession; + this.fUnzippedDirRoot = fUnzippedDirRoot; ResourceLocator fileResourceLocator = new PathResourceLocator(fUnzippedDirRoot.toPath()); inputResourceLocator = @@ -130,8 +145,16 @@ public class AssessmentResultController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + if(formLayout instanceof FormLayoutContainer) { FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout; + layoutCont.contextPut("print", new Boolean(withPrint)); + layoutCont.contextPut("printCommand", Boolean.FALSE); + if(withPrint) { + layoutCont.contextPut("winid", "w" + layoutCont.getFormItemComponent().getDispatchID()); + layoutCont.getFormItemComponent().addListener(this); + } + if(assessedIdentityInfosCtrl != null) { layoutCont.put("assessedIdentityInfos", assessedIdentityInfosCtrl.getInitialComponent()); } else if(anonym) { @@ -226,11 +249,17 @@ public class AssessmentResultController extends FormBasicController { layoutCont.add(responseId, responseFormItem); //solution - String solutionId = "solutionItem" + count++; - InteractionResultFormItem solutionFormItem = new InteractionResultFormItem(solutionId, interaction, resolvedAssessmentItem); - solutionFormItem.setShowSolution(true); - initInteractionResultFormItem(solutionFormItem, sessionState); - layoutCont.add(solutionId, solutionFormItem); + InteractionResultFormItem solutionFormItem; + + if(interaction instanceof ExtendedTextInteraction || interaction instanceof UploadInteraction || interaction instanceof DrawingInteraction) { + solutionFormItem = null;// no solution + } else { + String solutionId = "solutionItem" + count++; + solutionFormItem = new InteractionResultFormItem(solutionId, interaction, resolvedAssessmentItem); + solutionFormItem.setShowSolution(true); + initInteractionResultFormItem(solutionFormItem, sessionState); + layoutCont.add(solutionId, solutionFormItem); + } r.getInteractionResults().add(new InteractionResults(responseFormItem, solutionFormItem)); } @@ -285,7 +314,29 @@ public class AssessmentResultController extends FormBasicController { protected void formOK(UserRequest ureq) { // } - + + @Override + public void event(UserRequest ureq, Component source, Event event) { + if(flc.getFormItemComponent() == source && "print".equals(event.getCommand())) { + doPrint(ureq); + } + super.event(ureq, source, event); + } + + private void doPrint(UserRequest ureq) { + ControllerCreator creator = new ControllerCreator() { + @Override + public Controller createController(UserRequest uureq, WindowControl wwControl) { + AssessmentResultController printViewCtrl = new AssessmentResultController(uureq, wwControl, assessedIdentity, anonym, + candidateSession, resultsOnfinish, fUnzippedDirRoot, mapperUri, false); + printViewCtrl.flc.contextPut("printCommand", Boolean.TRUE); + listenTo(printViewCtrl); + return printViewCtrl; + } + }; + openInNewBrowserWindow(ureq, creator); + } + public class InteractionResults { private InteractionResultFormItem responseFormItem; private InteractionResultFormItem solutionFormItem; diff --git a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java index 399ee99e2b09305ca4898547583b63f79f1865be..6d1c66ed9b6c3e10f584429fe5384c9dd0f7c370 100644 --- a/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java +++ b/src/main/java/org/olat/ims/qti21/ui/AssessmentTestDisplayController.java @@ -1478,7 +1478,7 @@ public class AssessmentTestDisplayController extends BasicController implements removeAsListenerAndDispose(resultCtrl); resultCtrl = new AssessmentResultController(ureq, getWindowControl(), assessedIdentity, anonym, AssessmentTestDisplayController.this.getCandidateSession(), - deliveryOptions.getShowResultsOnFinish(), fUnzippedDirRoot, mapperUri); + deliveryOptions.getShowResultsOnFinish(), fUnzippedDirRoot, mapperUri, false); listenTo(resultCtrl); flc.add("qtiResults", resultCtrl.getInitialFormItem()); resultsVisible = true; diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java index 3f9efe5a4d0526dce948f05f7485992294e0cd1f..f33c6dbf8ac9319014da94625020e2c5e859f32d 100644 --- a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java +++ b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java @@ -343,7 +343,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController { new ResourcesMapper(assessmentObjectUri, submissionDir)); resultCtrl = new AssessmentResultController(ureq, getWindowControl(), assessedIdentity, false, session, - ShowResultsOnFinish.details, fUnzippedDirRoot, mapperUri); + ShowResultsOnFinish.details, fUnzippedDirRoot, mapperUri, true); listenTo(resultCtrl); cmc = new CloseableModalController(getWindowControl(), "close", resultCtrl.getInitialComponent(), true, translate("table.header.results")); 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 82bce60b7aa8fe45d40f08cbc8bf7bddf2556517..6a19d9297d2ccad9abf5b1697285bf4d667f2d4b 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 @@ -1,4 +1,23 @@ -<h3>$r.translate("head.assessment.details")</h3> +<div class="o_header_with_buttons"> + <h3>$r.translate("head.assessment.details")</h3> + #if($print) + <div class="o_button_group o_button_group_right"> + <script type="text/javascript"> + /* <![CDATA[ */ + function print() { + try { + var ww = window.open("$r.commandURI("print")", "$winid", "height=800,left=100,top=100,width=800,toolbar=no,titlebar=0,status=0,menubar=yes,location=no,scrollbars=1"); + ww.focus(); + } catch(e) { + if(jQuery(document).ooLog().isDebugEnabled()) jQuery(document).ooLog('debug','Error when trying to dock div id::$r.getId("undck")', "org.olat.core.gui.control.generic.docking._content.docked.html"); + } + } + /* ]]> */ + </script> + <a class="btn btn-default" href="javascript:print()" title="$r.translate("print")"><i class="o_icon o_icon_print"> </i> $r.translate("print")</a> + </div> + #end +</div> #if($r.visible("assessedIdentityInfos")) $r.render("assessedIdentityInfos") #end @@ -105,12 +124,29 @@ </div> #foreach($itemInteraction in $itemResult.interactionResults) <div class="row #if(!$foreach.hasNext ) o_block_bottom #end"> - <div class="col-sm-6"><h5>Response</h5> - $r.render($itemInteraction.responseFormItem.name) - </div> - <div class="col-sm-6"><h5>Solution</h5> - $r.render($itemInteraction.solutionFormItem.name) - </div> + #if($r.isNotNull($itemInteraction.solutionFormItem.name)) + <div class="col-sm-6"><h5>$r.translate("response")</h5> + $r.render($itemInteraction.responseFormItem.name) + </div> + <div class="col-sm-6"><h5>$r.translate("solution")</h5> + $r.render($itemInteraction.solutionFormItem.name) + </div> + #else + <div class="col-sm-12"><h5>$r.translate("response")</h5> + $r.render($itemInteraction.responseFormItem.name) + </div> + #end </div> #end -#end \ No newline at end of file +#end + +#if($printCommand) +<script type="text/javascript"> +/* <![CDATA[ */ + jQuery(function() { + window.focus(); + window.print(); + }); +/* ]]> */ +</script> +#end diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties index 1ff898855459e8d053a3d6976c9d55d6bced39fa..f1499894d135b480cf75d5574e0627c16275cb51 100644 --- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties @@ -140,10 +140,12 @@ retrievetest.confirm.text=$org.olat.ims.qti\:retrievetest.confirm.text retrievetest.confirm.text.plural=$org.olat.ims.qti.statistics.ui\:retrievetest.confirm.text.plural retrievetest.confirm.title=$org.olat.ims.qti.statistics.ui\:retrievetest.confirm.title retrievetest.nothing.todo=$org.olat.ims.qti.statistics.ui\:retrievetest.nothing.todo +response=Antwort review.responses=Ihre Antworten \u00FCberpr\u00FCfen review.responses.desc=Sie k\u00F6nnen Ihre Antworten von einer Sektion oder von allen Fragen \u00FCberpr\u00FCfen. Unten finden Sie die entsprechende Liste. score.max=$org.olat.ims.qti\:score.max serialize.error=Unerwarte Fehler w\u00E4hrend Speicherung von Datei +solution=L\u00F6sung submit=Antwort senden suspend.test=$org.olat.modules.iq\:suspendAssess tab.options=Optionen diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties index 629e2a8205596fde2db0c26403cbab8add35e288..22286ae4291f7c3cd5264e022180ae9ac383b19e 100644 --- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties @@ -140,10 +140,12 @@ retrievetest.confirm.text=$org.olat.ims.qti\:retrievetest.confirm.text retrievetest.confirm.text.plural=$org.olat.ims.qti.statistics.ui\:retrievetest.confirm.text.plural retrievetest.confirm.title=$org.olat.ims.qti.statistics.ui\:retrievetest.confirm.title retrievetest.nothing.todo=$org.olat.ims.qti.statistics.ui\:retrievetest.nothing.todo +response=Response review.responses=Review your responses review.responses.desc=You may review your responses to some (or all) questions. These are listed below. score.max=$org.olat.ims.qti\:score.max serialize.error=An unexpected happens while saving the file. +solution=Solution submit=Submit response suspend.test=$org.olat.modules.iq\:suspendAssess tab.options=Options diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java index 541a924199b2a51fb74ed67d41495b76f88ab8ca..bc10d4590dfbba03991fb5a5dbf1c36076ac1f43 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentObjectComponentRenderer.java @@ -1033,7 +1033,7 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent ItemSessionState itemSessionState, ExtendedTextInteraction interaction, String responseInputString) { String responseUniqueId = component.getResponseUniqueIdentifier(itemSessionState, interaction); - sb.append("<textarea id='").append(responseUniqueId).append("' name='qtiworks_response_").append(responseUniqueId).append("'"); + sb.append("<textarea id='oo_").append(responseUniqueId).append("' name='qtiworks_response_").append(responseUniqueId).append("'"); if(component.isItemSessionEnded(itemSessionState, renderer.isSolutionMode())) { sb.append(" disabled"); } @@ -1072,13 +1072,12 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent sb.append(responseInputString); } sb.append("</textarea>"); - FormJSHelper.appendFlexiFormDirty(sb, component.getQtiItem().getRootForm(), responseUniqueId); - sb.append(FormJSHelper.getJSStartWithVarDeclaration(responseUniqueId)) + + FormJSHelper.appendFlexiFormDirty(sb, component.getQtiItem().getRootForm(), "oo_" + responseUniqueId); + sb.append(FormJSHelper.getJSStartWithVarDeclaration("oo_" + responseUniqueId)) //plain textAreas should not propagate the keypress "enter" (keynum = 13) as this would submit the form - .append(responseUniqueId).append(".on('keypress', function(event, target){if (13 == event.keyCode) {event.stopPropagation()} })") + .append("oo_").append(responseUniqueId).append(".on('keypress', function(event, target){if (13 == event.keyCode) {event.stopPropagation()} })") .append(FormJSHelper.getJSEnd()); - - } protected abstract void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb,