Skip to content
Snippets Groups Projects
Commit 16ad03c4 authored by srosse's avatar srosse
Browse files

OO-1593: allow to add images in QTI editors and enhance rendering of medias...

OO-1593: allow to add images in QTI editors and enhance rendering of medias with relative path between manifest / test / items
parent 8ca42bd6
No related branches found
No related tags found
No related merge requests found
Showing
with 318 additions and 149 deletions
/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.ims.qti21;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;
/**
*
* Initial date: 10.03.2016<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public final class XmlUtilities {
private static final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
static {
parserFactory.setNamespaceAware(true);
parserFactory.setValidating(false);
}
/**
* @return XMLReader namespace aware but not validating.
*/
public static final XMLReader createNsAwareSaxReader() {
try {
return parserFactory.newSAXParser().getXMLReader();
} catch (final Exception e) {
throw new RuntimeException("Could not create NS-aware SAXParser with validating=false. Check deployment/runtime ClassPath", e);
}
}
}
...@@ -69,7 +69,6 @@ import org.olat.ims.qti21.model.CandidateItemEventType; ...@@ -69,7 +69,6 @@ import org.olat.ims.qti21.model.CandidateItemEventType;
import org.olat.ims.qti21.model.CandidateTestEventType; import org.olat.ims.qti21.model.CandidateTestEventType;
import org.olat.ims.qti21.model.ResponseLegality; import org.olat.ims.qti21.model.ResponseLegality;
import org.olat.ims.qti21.model.jpa.CandidateEvent; import org.olat.ims.qti21.model.jpa.CandidateEvent;
import org.olat.ims.qti21.ui.rendering.XmlUtilities;
import org.olat.modules.assessment.AssessmentEntry; import org.olat.modules.assessment.AssessmentEntry;
import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntry;
import org.olat.repository.RepositoryEntryRef; import org.olat.repository.RepositoryEntryRef;
...@@ -110,6 +109,7 @@ import uk.ac.ed.ph.jqtiplus.value.NumberValue; ...@@ -110,6 +109,7 @@ import uk.ac.ed.ph.jqtiplus.value.NumberValue;
import uk.ac.ed.ph.jqtiplus.value.RecordValue; import uk.ac.ed.ph.jqtiplus.value.RecordValue;
import uk.ac.ed.ph.jqtiplus.value.SingleValue; import uk.ac.ed.ph.jqtiplus.value.SingleValue;
import uk.ac.ed.ph.jqtiplus.value.Value; import uk.ac.ed.ph.jqtiplus.value.Value;
import uk.ac.ed.ph.jqtiplus.xmlutils.XmlFactories;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ClassPathResourceLocator; import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ClassPathResourceLocator;
import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator; import uk.ac.ed.ph.jqtiplus.xmlutils.locators.ResourceLocator;
import uk.ac.ed.ph.jqtiplus.xmlutils.xslt.XsltSerializationOptions; import uk.ac.ed.ph.jqtiplus.xmlutils.xslt.XsltSerializationOptions;
...@@ -362,8 +362,8 @@ public class QTI21ServiceImpl implements QTI21Service, InitializingBean, Disposa ...@@ -362,8 +362,8 @@ public class QTI21ServiceImpl implements QTI21Service, InitializingBean, Disposa
private Document loadStateDocument(AssessmentTestSession candidateSession) { private Document loadStateDocument(AssessmentTestSession candidateSession) {
File sessionFile = getTestSessionStateFile(candidateSession); File sessionFile = getTestSessionStateFile(candidateSession);
if(sessionFile.exists()) { if(sessionFile.exists()) {
DocumentBuilder documentBuilder = XmlUtilities.createNsAwareDocumentBuilder();
try { try {
DocumentBuilder documentBuilder = XmlFactories.newDocumentBuilder();
return documentBuilder.parse(sessionFile); return documentBuilder.parse(sessionFile);
} catch (final Exception e) { } catch (final Exception e) {
throw new OLATRuntimeException("Could not parse serailized state XML. This is an internal error as we currently don't expose this data to clients", e); throw new OLATRuntimeException("Could not parse serailized state XML. This is an internal error as we currently don't expose this data to clients", e);
......
...@@ -29,6 +29,7 @@ import org.olat.core.gui.control.Controller; ...@@ -29,6 +29,7 @@ import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event; import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.QTI21Service; import org.olat.ims.qti21.QTI21Service;
import org.olat.ims.qti21.ui.editor.AssessmentItemEditorController; import org.olat.ims.qti21.ui.editor.AssessmentItemEditorController;
import org.olat.ims.qti21.ui.editor.events.AssessmentItemEvent; import org.olat.ims.qti21.ui.editor.events.AssessmentItemEvent;
...@@ -65,6 +66,7 @@ public class QTI21EditorController extends BasicController implements QPoolItemE ...@@ -65,6 +66,7 @@ public class QTI21EditorController extends BasicController implements QPoolItemE
mainVC = createVelocityContainer("pool_editor"); mainVC = createVelocityContainer("pool_editor");
File resourceDirectory = qpoolService.getRootDirectory(questionItem); File resourceDirectory = qpoolService.getRootDirectory(questionItem);
VFSContainer resourceContainer = qpoolService.getRootContainer(questionItem);
resourceFile = qpoolService.getRootFile(questionItem); resourceFile = qpoolService.getRootFile(questionItem);
URI assessmentItemUri = resourceFile.toURI(); URI assessmentItemUri = resourceFile.toURI();
...@@ -72,7 +74,7 @@ public class QTI21EditorController extends BasicController implements QPoolItemE ...@@ -72,7 +74,7 @@ public class QTI21EditorController extends BasicController implements QPoolItemE
.loadAndResolveAssessmentItem(assessmentItemUri, resourceDirectory); .loadAndResolveAssessmentItem(assessmentItemUri, resourceDirectory);
editorCtrl = new AssessmentItemEditorController(ureq, wControl, editorCtrl = new AssessmentItemEditorController(ureq, wControl,
resolvedAssessmentItem, resourceDirectory, resourceFile); resolvedAssessmentItem, resourceDirectory, resourceContainer, resourceFile);
listenTo(editorCtrl); listenTo(editorCtrl);
mainVC.put("editor", editorCtrl.getInitialComponent()); mainVC.put("editor", editorCtrl.getInitialComponent());
......
...@@ -43,6 +43,11 @@ public class AssessmentItemComponent extends AssessmentObjectComponent { ...@@ -43,6 +43,11 @@ public class AssessmentItemComponent extends AssessmentObjectComponent {
this.qtiItem = qtiItem; this.qtiItem = qtiItem;
} }
@Override
public String relativePathTo(ResolvedAssessmentItem item) {
return "";
}
public ResolvedAssessmentItem getResolvedAssessmentItem() { public ResolvedAssessmentItem getResolvedAssessmentItem() {
return resolvedAssessmentItem; return resolvedAssessmentItem;
} }
...@@ -51,6 +56,7 @@ public class AssessmentItemComponent extends AssessmentObjectComponent { ...@@ -51,6 +56,7 @@ public class AssessmentItemComponent extends AssessmentObjectComponent {
this.resolvedAssessmentItem = resolvedAssessmentItem; this.resolvedAssessmentItem = resolvedAssessmentItem;
} }
@Override
public AssessmentItemFormItem getQtiItem() { public AssessmentItemFormItem getQtiItem() {
return qtiItem; return qtiItem;
} }
...@@ -68,7 +74,6 @@ public class AssessmentItemComponent extends AssessmentObjectComponent { ...@@ -68,7 +74,6 @@ public class AssessmentItemComponent extends AssessmentObjectComponent {
this.itemSessionController = itemSessionController; this.itemSessionController = itemSessionController;
} }
@Override @Override
public AssessmentItemComponentRenderer getHTMLRendererSingleton() { public AssessmentItemComponentRenderer getHTMLRendererSingleton() {
return RENDERER; return RENDERER;
......
...@@ -40,6 +40,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem; ...@@ -40,6 +40,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration; import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration;
import uk.ac.ed.ph.jqtiplus.node.outcome.declaration.OutcomeDeclaration; import uk.ac.ed.ph.jqtiplus.node.outcome.declaration.OutcomeDeclaration;
import uk.ac.ed.ph.jqtiplus.node.result.SessionStatus; import uk.ac.ed.ph.jqtiplus.node.result.SessionStatus;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.running.ItemSessionController; import uk.ac.ed.ph.jqtiplus.running.ItemSessionController;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState; import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
import uk.ac.ed.ph.jqtiplus.types.Identifier; import uk.ac.ed.ph.jqtiplus.types.Identifier;
...@@ -162,19 +163,20 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe ...@@ -162,19 +163,20 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe
URLBuilder ubu, Translator translator) { URLBuilder ubu, Translator translator) {
final AssessmentItem assessmentItem = component.getAssessmentItem(); final AssessmentItem assessmentItem = component.getAssessmentItem();
final ResolvedAssessmentItem resolvedAssessmentItem = component.getResolvedAssessmentItem();
//title + status //title + status
sb.append("<h1 class='itemTitle'>"); sb.append("<h1 class='itemTitle'>");
renderItemStatus(renderer, sb, itemSessionState, translator); renderItemStatus(renderer, sb, itemSessionState, translator);
sb.append(assessmentItem.getTitle()).append("</h1>"); sb.append(assessmentItem.getTitle()).append("</h1>")
sb.append("<div id='itemBody'>"); .append("<div id='itemBody'>");
//TODO prompt //TODO prompt
//render itemBody //render itemBody
assessmentItem.getItemBody().getBlocks().forEach((block) assessmentItem.getItemBody().getBlocks().forEach((block)
-> renderBlock(renderer, sb, component, assessmentItem, itemSessionState, block, ubu, translator)); -> renderBlock(renderer, sb, component, resolvedAssessmentItem, itemSessionState, block, ubu, translator));
//comment //comment
renderComment(renderer, sb, component, itemSessionState, translator); renderComment(renderer, sb, component, itemSessionState, translator);
...@@ -190,7 +192,7 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe ...@@ -190,7 +192,7 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe
// Display active modal feedback (only after responseProcessing) // Display active modal feedback (only after responseProcessing)
if(itemSessionState.getSessionStatus() == SessionStatus.FINAL) { if(itemSessionState.getSessionStatus() == SessionStatus.FINAL) {
renderTestItemModalFeedback(renderer, sb, component, assessmentItem, itemSessionState, ubu, translator); renderTestItemModalFeedback(renderer, sb, component, resolvedAssessmentItem, itemSessionState, ubu, translator);
} }
} }
...@@ -203,8 +205,8 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe ...@@ -203,8 +205,8 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe
} }
@Override @Override
protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb, AssessmentObjectComponent component, AssessmentItem assessmentItem, ItemSessionState itemSessionState, protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb, AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem,
PrintedVariable printedVar) { ItemSessionState itemSessionState, PrintedVariable printedVar) {
Identifier identifier = printedVar.getIdentifier(); Identifier identifier = printedVar.getIdentifier();
Value templateValue = itemSessionState.getTemplateValues().get(identifier); Value templateValue = itemSessionState.getTemplateValues().get(identifier);
...@@ -212,10 +214,12 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe ...@@ -212,10 +214,12 @@ public class AssessmentItemComponentRenderer extends AssessmentObjectComponentRe
sb.append("<span class='printedVariable'>"); sb.append("<span class='printedVariable'>");
if(outcomeValue != null) { if(outcomeValue != null) {
OutcomeDeclaration outcomeDeclaration = assessmentItem.getOutcomeDeclaration(identifier); OutcomeDeclaration outcomeDeclaration = resolvedAssessmentItem.getRootNodeLookup()
.extractIfSuccessful().getOutcomeDeclaration(identifier);
renderPrintedVariable(renderer, sb, printedVar, outcomeDeclaration, outcomeValue); renderPrintedVariable(renderer, sb, printedVar, outcomeDeclaration, outcomeValue);
} else if(templateValue != null) { } else if(templateValue != null) {
TemplateDeclaration templateDeclaration = assessmentItem.getTemplateDeclaration(identifier); TemplateDeclaration templateDeclaration = resolvedAssessmentItem.getRootNodeLookup()
.extractIfSuccessful().getTemplateDeclaration(identifier);
renderPrintedVariable(renderer, sb, printedVar, templateDeclaration, templateValue); renderPrintedVariable(renderer, sb, printedVar, templateDeclaration, templateValue);
} else { } else {
sb.append("(variable ").append(identifier.toString()).append(" was not found)"); sb.append("(variable ").append(identifier.toString()).append(" was not found)");
......
...@@ -36,6 +36,7 @@ import org.olat.ims.qti21.ui.CandidateSessionContext; ...@@ -36,6 +36,7 @@ import org.olat.ims.qti21.ui.CandidateSessionContext;
import uk.ac.ed.ph.jqtiplus.node.content.variable.FeedbackElement; import uk.ac.ed.ph.jqtiplus.node.content.variable.FeedbackElement;
import uk.ac.ed.ph.jqtiplus.node.item.ModalFeedback; import uk.ac.ed.ph.jqtiplus.node.item.ModalFeedback;
import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode; import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState; import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
import uk.ac.ed.ph.jqtiplus.types.Identifier; import uk.ac.ed.ph.jqtiplus.types.Identifier;
import uk.ac.ed.ph.jqtiplus.value.Value; import uk.ac.ed.ph.jqtiplus.value.Value;
...@@ -78,6 +79,8 @@ public abstract class AssessmentObjectComponent extends AbstractComponent implem ...@@ -78,6 +79,8 @@ public abstract class AssessmentObjectComponent extends AbstractComponent implem
this.assessmentObjectUri = assessmentObjectUri; this.assessmentObjectUri = assessmentObjectUri;
} }
public abstract String relativePathTo(ResolvedAssessmentItem resolvedAssessmentItem);
public ResourceLocator getResourceLocator() { public ResourceLocator getResourceLocator() {
return resourceLocator; return resourceLocator;
} }
......
...@@ -67,6 +67,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.content.Gap; ...@@ -67,6 +67,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.content.Gap;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.AssociableHotspot; import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.AssociableHotspot;
import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.HotspotChoice; import uk.ac.ed.ph.jqtiplus.node.item.interaction.graphic.HotspotChoice;
import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration; import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState; import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
import uk.ac.ed.ph.jqtiplus.types.Identifier; import uk.ac.ed.ph.jqtiplus.types.Identifier;
import uk.ac.ed.ph.jqtiplus.types.ResponseData; import uk.ac.ed.ph.jqtiplus.types.ResponseData;
...@@ -96,20 +97,22 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -96,20 +97,22 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
private final AssessmentItem assessmentItem; private final AssessmentItem assessmentItem;
private final ItemSessionState itemSessionState; private final ItemSessionState itemSessionState;
private final ResolvedAssessmentItem resolvedAssessmentItem;
private final AssessmentObjectComponent avc; private final AssessmentObjectComponent avc;
public AssessmentObjectVelocityRenderDecorator(AssessmentRenderer renderer, StringOutput target, AssessmentObjectComponent vc, public AssessmentObjectVelocityRenderDecorator(AssessmentRenderer renderer, StringOutput target, AssessmentObjectComponent vc,
AssessmentItem assessmentItem, ItemSessionState itemSessionState, URLBuilder ubu, Translator translator) { ResolvedAssessmentItem resolvedAssessmentItem, ItemSessionState itemSessionState, URLBuilder ubu, Translator translator) {
super(renderer.getRenderer(), vc, target); super(renderer.getRenderer(), vc, target);
this.avc = vc; this.avc = vc;
this.ubu = ubu; this.ubu = ubu;
this.target = target; this.target = target;
this.renderer = renderer; this.renderer = renderer;
this.translator = translator; this.translator = translator;
this.assessmentItem = assessmentItem;
this.itemSessionState = itemSessionState; this.itemSessionState = itemSessionState;
this.resolvedAssessmentItem = resolvedAssessmentItem;
this.assessmentItem = resolvedAssessmentItem.getRootNodeLookup().extractIfSuccessful();
} }
public boolean isSolutionMode() { public boolean isSolutionMode() {
...@@ -126,11 +129,11 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -126,11 +129,11 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
} }
public String convertLink(String uri) { public String convertLink(String uri) {
return AssessmentRenderFunctions.convertLink(avc, uri); return AssessmentRenderFunctions.convertLink(avc, resolvedAssessmentItem, uri);
} }
public String convertLinkFull(String uri) { public String convertLinkFull(String uri) {
return AssessmentRenderFunctions.convertLink(avc, uri); return AssessmentRenderFunctions.convertLink(avc, resolvedAssessmentItem, uri);
} }
public boolean isNullValue(Value value) { public boolean isNullValue(Value value) {
...@@ -477,14 +480,14 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -477,14 +480,14 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
public String renderPrompt(Prompt prompt) { public String renderPrompt(Prompt prompt) {
if(prompt != null) { if(prompt != null) {
prompt.getInlineStatics().forEach((inline) prompt.getInlineStatics().forEach((inline)
-> avc.getHTMLRendererSingleton().renderInline(renderer, target, avc, assessmentItem, itemSessionState, inline, ubu, translator)); -> avc.getHTMLRendererSingleton().renderInline(renderer, target, avc, resolvedAssessmentItem, itemSessionState, inline, ubu, translator));
} }
return ""; return "";
} }
public String renderBlock(Block block) { public String renderBlock(Block block) {
if(block != null) { if(block != null) {
avc.getHTMLRendererSingleton().renderBlock(renderer, target, avc, assessmentItem, itemSessionState, block, ubu, translator); avc.getHTMLRendererSingleton().renderBlock(renderer, target, avc, resolvedAssessmentItem, itemSessionState, block, ubu, translator);
} }
return ""; return "";
} }
...@@ -492,7 +495,7 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -492,7 +495,7 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
public String renderBlockStatics(List<BlockStatic> blockStaticList) { public String renderBlockStatics(List<BlockStatic> blockStaticList) {
if(blockStaticList != null && blockStaticList.size() > 0) { if(blockStaticList != null && blockStaticList.size() > 0) {
blockStaticList.forEach((block) blockStaticList.forEach((block)
-> avc.getHTMLRendererSingleton().renderBlock(renderer, target, avc, assessmentItem, itemSessionState, block, ubu, translator)); -> avc.getHTMLRendererSingleton().renderBlock(renderer, target, avc, resolvedAssessmentItem, itemSessionState, block, ubu, translator));
} }
return ""; return "";
} }
...@@ -500,7 +503,7 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -500,7 +503,7 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
public String renderFlowStatics(List<FlowStatic> flowStaticList) { public String renderFlowStatics(List<FlowStatic> flowStaticList) {
if(flowStaticList != null && flowStaticList.size() > 0) { if(flowStaticList != null && flowStaticList.size() > 0) {
flowStaticList.forEach((flow) flowStaticList.forEach((flow)
-> avc.getHTMLRendererSingleton().renderFlow(renderer, target, avc, assessmentItem, itemSessionState, flow, ubu, translator)); -> avc.getHTMLRendererSingleton().renderFlow(renderer, target, avc, resolvedAssessmentItem, itemSessionState, flow, ubu, translator));
} }
return ""; return "";
} }
...@@ -508,14 +511,14 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor ...@@ -508,14 +511,14 @@ public class AssessmentObjectVelocityRenderDecorator extends VelocityRenderDecor
public String renderTextOrVariables(List<TextOrVariable> textOrVariables) { public String renderTextOrVariables(List<TextOrVariable> textOrVariables) {
if(textOrVariables != null && textOrVariables.size() > 0) { if(textOrVariables != null && textOrVariables.size() > 0) {
textOrVariables.forEach((textOrVariable) textOrVariables.forEach((textOrVariable)
-> avc.getHTMLRendererSingleton().renderTextOrVariable(renderer, target, avc, assessmentItem, itemSessionState, textOrVariable)); -> avc.getHTMLRendererSingleton().renderTextOrVariable(renderer, target, avc, resolvedAssessmentItem, itemSessionState, textOrVariable));
} }
return ""; return "";
} }
public String renderFlow(Flow flow) { public String renderFlow(Flow flow) {
if(flow != null) { if(flow != null) {
avc.getHTMLRendererSingleton().renderFlow(renderer, target, avc, assessmentItem, itemSessionState, flow, ubu, translator); avc.getHTMLRendererSingleton().renderFlow(renderer, target, avc, resolvedAssessmentItem, itemSessionState, flow, ubu, translator);
} }
return ""; return "";
} }
......
...@@ -40,6 +40,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.Choice; ...@@ -40,6 +40,7 @@ import uk.ac.ed.ph.jqtiplus.node.item.interaction.choice.Choice;
import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration; import uk.ac.ed.ph.jqtiplus.node.item.response.declaration.ResponseDeclaration;
import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration; import uk.ac.ed.ph.jqtiplus.node.item.template.declaration.TemplateDeclaration;
import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode; import uk.ac.ed.ph.jqtiplus.node.test.VisibilityMode;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState; import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
import uk.ac.ed.ph.jqtiplus.types.Identifier; import uk.ac.ed.ph.jqtiplus.types.Identifier;
import uk.ac.ed.ph.jqtiplus.types.ResponseData; import uk.ac.ed.ph.jqtiplus.types.ResponseData;
...@@ -517,7 +518,7 @@ public class AssessmentRenderFunctions { ...@@ -517,7 +518,7 @@ public class AssessmentRenderFunctions {
* @return * @return
*/ */
@SuppressWarnings({ "rawtypes" }) @SuppressWarnings({ "rawtypes" })
public static final String getHtmlAttributeValue(AssessmentObjectComponent component, Attribute attribute) { public static final String getHtmlAttributeValue(AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem, Attribute attribute) {
String value; String value;
String name = attribute.getLocalName(); String name = attribute.getLocalName();
switch(name) { switch(name) {
...@@ -530,7 +531,7 @@ public class AssessmentRenderFunctions { ...@@ -530,7 +531,7 @@ public class AssessmentRenderFunctions {
case "href": case "href":
case "src": case "src":
String uri = getDomAttributeValue(attribute); String uri = getDomAttributeValue(attribute);
value = convertLink(component, uri); value = convertLink(component, resolvedAssessmentItem, uri);
break; break;
default: default:
value = null; value = null;
...@@ -564,11 +565,14 @@ public class AssessmentRenderFunctions { ...@@ -564,11 +565,14 @@ public class AssessmentRenderFunctions {
</xsl:choose> </xsl:choose>
</xsl:function> </xsl:function>
*/ */
public static final String convertLink(AssessmentObjectComponent component, String uri) { public static final String convertLink(AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem, String uri) {
if(uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("mailto:")) { if(uri.startsWith("http:") || uri.startsWith("https:") || uri.startsWith("mailto:")) {
return uri; return uri;
} }
uri = component.getMapperUri() + "/file?href=" + uri;
String relativePath = component.relativePathTo(resolvedAssessmentItem);
uri = component.getMapperUri() + "/file?href=" + relativePath + uri;
System.out.println("Rewrite: " + uri);
return uri; return uri;
} }
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
*/ */
package org.olat.ims.qti21.ui.components; package org.olat.ims.qti21.ui.components;
import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.util.List; import java.util.List;
import org.olat.ims.qti21.ui.components.AssessmentObjectComponentRenderer.RenderingRequest; import org.olat.ims.qti21.ui.components.AssessmentObjectComponentRenderer.RenderingRequest;
...@@ -28,6 +31,7 @@ import uk.ac.ed.ph.jqtiplus.node.result.SessionStatus; ...@@ -28,6 +31,7 @@ import uk.ac.ed.ph.jqtiplus.node.result.SessionStatus;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentSection; import uk.ac.ed.ph.jqtiplus.node.test.AssessmentSection;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest; import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
import uk.ac.ed.ph.jqtiplus.node.test.TestPart; import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest; import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
import uk.ac.ed.ph.jqtiplus.running.TestSessionController; import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
import uk.ac.ed.ph.jqtiplus.state.ItemSessionState; import uk.ac.ed.ph.jqtiplus.state.ItemSessionState;
...@@ -102,6 +106,22 @@ public class AssessmentTestComponent extends AssessmentObjectComponent { ...@@ -102,6 +106,22 @@ public class AssessmentTestComponent extends AssessmentObjectComponent {
public void setResolvedAssessmentTest(ResolvedAssessmentTest resolvedAssessmentTest) { public void setResolvedAssessmentTest(ResolvedAssessmentTest resolvedAssessmentTest) {
this.resolvedAssessmentTest = resolvedAssessmentTest; this.resolvedAssessmentTest = resolvedAssessmentTest;
} }
@Override
public String relativePathTo(ResolvedAssessmentItem resolvedAssessmentItem) {
URI itemUri = resolvedAssessmentItem.getItemLookup().getSystemId();
File itemFile = new File(itemUri);
URI testUri = resolvedAssessmentTest.getTestLookup().getSystemId();
File testFile = new File(testUri);
Path relativePath = testFile.toPath().getParent().relativize(itemFile.toPath().getParent());
String relativePathString = relativePath.toString();
if(relativePathString.isEmpty()) {
return relativePathString;
} else if(relativePathString.endsWith("/")) {
return relativePathString;
}
return relativePathString.concat("/");
}
public AssessmentTest getAssessmentTest() { public AssessmentTest getAssessmentTest() {
return getResolvedAssessmentTest().getRootNodeLookup().extractIfSuccessful(); return getResolvedAssessmentTest().getRootNodeLookup().extractIfSuccessful();
......
...@@ -344,7 +344,7 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe ...@@ -344,7 +344,7 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
//render itemBody //render itemBody
assessmentItem.getItemBody().getBlocks().forEach((block) assessmentItem.getItemBody().getBlocks().forEach((block)
-> renderBlock(renderer, sb, component, assessmentItem, itemSessionState, block, ubu, translator)); -> renderBlock(renderer, sb, component, resolvedAssessmentItem, itemSessionState, block, ubu, translator));
//comment //comment
renderComment(renderer, sb, component, itemSessionState, translator); renderComment(renderer, sb, component, itemSessionState, translator);
...@@ -359,12 +359,12 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe ...@@ -359,12 +359,12 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
// Display active modal feedback (only after responseProcessing) // Display active modal feedback (only after responseProcessing)
if(component.isItemFeedbackAllowed(itemNode, assessmentItem, options)) { if(component.isItemFeedbackAllowed(itemNode, assessmentItem, options)) {
renderTestItemModalFeedback(renderer, sb, component, assessmentItem, itemSessionState, ubu, translator); renderTestItemModalFeedback(renderer, sb, component, resolvedAssessmentItem, itemSessionState, ubu, translator);
} }
} }
@Override @Override
protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb, AssessmentObjectComponent component, AssessmentItem assessmentItem, protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb, AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem,
ItemSessionState itemSessionState, PrintedVariable printedVar) { ItemSessionState itemSessionState, PrintedVariable printedVar) {
AssessmentTestComponent testCmp = (AssessmentTestComponent)component; AssessmentTestComponent testCmp = (AssessmentTestComponent)component;
...@@ -380,10 +380,12 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe ...@@ -380,10 +380,12 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
Value templateValue = itemSessionState.getTemplateValues().get(identifier); Value templateValue = itemSessionState.getTemplateValues().get(identifier);
Value outcomeValue = itemSessionState.getOutcomeValues().get(identifier); Value outcomeValue = itemSessionState.getOutcomeValues().get(identifier);
if(outcomeValue != null) { if(outcomeValue != null) {
OutcomeDeclaration outcomeDeclaration = assessmentItem.getOutcomeDeclaration(identifier); OutcomeDeclaration outcomeDeclaration = resolvedAssessmentItem.getRootNodeLookup()
.extractIfSuccessful().getOutcomeDeclaration(identifier);
renderPrintedVariable(renderer, sb, printedVar, outcomeDeclaration, outcomeValue); renderPrintedVariable(renderer, sb, printedVar, outcomeDeclaration, outcomeValue);
} else if(templateValue != null) { } else if(templateValue != null) {
TemplateDeclaration templateDeclaration = assessmentItem.getTemplateDeclaration(identifier); TemplateDeclaration templateDeclaration = resolvedAssessmentItem.getRootNodeLookup()
.extractIfSuccessful().getTemplateDeclaration(identifier);
renderPrintedVariable(renderer, sb, printedVar, templateDeclaration, templateValue); renderPrintedVariable(renderer, sb, printedVar, templateDeclaration, templateValue);
} else { } else {
sb.append("(variable ").append(identifier.toString()).append(" was not found)"); sb.append("(variable ").append(identifier.toString()).append(" was not found)");
...@@ -394,9 +396,9 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe ...@@ -394,9 +396,9 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
@Override @Override
protected void renderMath(AssessmentRenderer renderer, StringOutput out, AssessmentObjectComponent component, protected void renderMath(AssessmentRenderer renderer, StringOutput out, AssessmentObjectComponent component,
AssessmentItem assessmentItem, ItemSessionState itemSessionState, QtiNode mathElement) { ResolvedAssessmentItem resolvedAssessmentItem, ItemSessionState itemSessionState, QtiNode mathElement) {
if(assessmentItem != null) { if(resolvedAssessmentItem != null) {
super.renderMath(renderer, out, component, assessmentItem, itemSessionState, mathElement); super.renderMath(renderer, out, component, resolvedAssessmentItem, itemSessionState, mathElement);
} else if(mathElement instanceof ForeignElement) { } else if(mathElement instanceof ForeignElement) {
ForeignElement fElement = (ForeignElement)mathElement; ForeignElement fElement = (ForeignElement)mathElement;
boolean mi = fElement.getQtiClassName().equals("mi"); boolean mi = fElement.getQtiClassName().equals("mi");
...@@ -414,15 +416,15 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe ...@@ -414,15 +416,15 @@ public class AssessmentTestComponentRenderer extends AssessmentObjectComponentRe
substituteMi(out, outcomeValue); substituteMi(out, outcomeValue);
} }
} else { } else {
renderStartHtmlTag(out, component, fElement, null); renderStartHtmlTag(out, component, resolvedAssessmentItem, fElement, null);
fElement.getChildren().forEach((child) fElement.getChildren().forEach((child)
-> renderMath(renderer, out, component, assessmentItem, itemSessionState, child)); -> renderMath(renderer, out, component, resolvedAssessmentItem, itemSessionState, child));
renderEndTag(out, fElement); renderEndTag(out, fElement);
} }
} else { } else {
renderStartHtmlTag(out, component, fElement, null); renderStartHtmlTag(out, component, resolvedAssessmentItem, fElement, null);
fElement.getChildren().forEach((child) fElement.getChildren().forEach((child)
-> renderMath(renderer, out, component, assessmentItem, itemSessionState, child)); -> renderMath(renderer, out, component, resolvedAssessmentItem, itemSessionState, child));
renderEndTag(out, fElement); renderEndTag(out, fElement);
} }
} else if(mathElement instanceof TextRun) { } else if(mathElement instanceof TextRun) {
......
...@@ -22,6 +22,7 @@ package org.olat.ims.qti21.ui.components; ...@@ -22,6 +22,7 @@ package org.olat.ims.qti21.ui.components;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest; import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest; import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
import uk.ac.ed.ph.jqtiplus.running.ItemProcessingContext; import uk.ac.ed.ph.jqtiplus.running.ItemProcessingContext;
import uk.ac.ed.ph.jqtiplus.running.TestSessionController; import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
...@@ -50,6 +51,11 @@ public class AssessmentTreeComponent extends AssessmentObjectComponent { ...@@ -50,6 +51,11 @@ public class AssessmentTreeComponent extends AssessmentObjectComponent {
this.qtiItem = qtiItem; this.qtiItem = qtiItem;
} }
@Override
public String relativePathTo(ResolvedAssessmentItem resolvedAssessmentItem) {
return "";
}
@Override @Override
public AssessmentTreeFormItem getQtiItem() { public AssessmentTreeFormItem getQtiItem() {
return qtiItem; return qtiItem;
......
...@@ -36,9 +36,9 @@ import org.olat.ims.qti21.ui.CandidateSessionContext; ...@@ -36,9 +36,9 @@ import org.olat.ims.qti21.ui.CandidateSessionContext;
import org.olat.ims.qti21.ui.QTIWorksAssessmentTestEvent.Event; import org.olat.ims.qti21.ui.QTIWorksAssessmentTestEvent.Event;
import uk.ac.ed.ph.jqtiplus.node.content.variable.PrintedVariable; import uk.ac.ed.ph.jqtiplus.node.content.variable.PrintedVariable;
import uk.ac.ed.ph.jqtiplus.node.item.AssessmentItem;
import uk.ac.ed.ph.jqtiplus.node.test.NavigationMode; import uk.ac.ed.ph.jqtiplus.node.test.NavigationMode;
import uk.ac.ed.ph.jqtiplus.node.test.TestPart; import uk.ac.ed.ph.jqtiplus.node.test.TestPart;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentItem;
import uk.ac.ed.ph.jqtiplus.running.ItemProcessingContext; import uk.ac.ed.ph.jqtiplus.running.ItemProcessingContext;
import uk.ac.ed.ph.jqtiplus.running.ItemSessionController; import uk.ac.ed.ph.jqtiplus.running.ItemSessionController;
import uk.ac.ed.ph.jqtiplus.running.TestSessionController; import uk.ac.ed.ph.jqtiplus.running.TestSessionController;
...@@ -249,8 +249,8 @@ public class AssessmentTreeComponentRenderer extends AssessmentObjectComponentRe ...@@ -249,8 +249,8 @@ public class AssessmentTreeComponentRenderer extends AssessmentObjectComponentRe
@Override @Override
protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb, protected void renderPrintedVariable(AssessmentRenderer renderer, StringOutput sb,
AssessmentObjectComponent component, AssessmentItem assessmentItem, ItemSessionState itemSessionState, AssessmentObjectComponent component, ResolvedAssessmentItem resolvedAssessmentItem, ItemSessionState itemSessionState,
PrintedVariable printedVar) { PrintedVariable printedVar) {
//
} }
} }
\ No newline at end of file
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
package org.olat.ims.qti21.ui.editor; package org.olat.ims.qti21.ui.editor;
import java.io.File; import java.io.File;
import java.net.URI;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Component;
...@@ -30,6 +29,7 @@ import org.olat.core.gui.control.Controller; ...@@ -30,6 +29,7 @@ import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event; import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController; import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.QTI21Service; import org.olat.ims.qti21.QTI21Service;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.QTI21QuestionTypeDetector; import org.olat.ims.qti21.model.QTI21QuestionTypeDetector;
...@@ -77,6 +77,10 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -77,6 +77,10 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemDisplayController displayCtrl; private AssessmentItemDisplayController displayCtrl;
private Controller itemEditor, scoreEditor, feedbackEditor; private Controller itemEditor, scoreEditor, feedbackEditor;
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private AssessmentItemBuilder itemBuilder; private AssessmentItemBuilder itemBuilder;
private ManifestMetadataBuilder metadataBuilder; private ManifestMetadataBuilder metadataBuilder;
...@@ -87,9 +91,13 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -87,9 +91,13 @@ public class AssessmentItemEditorController extends BasicController {
public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl, public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl,
ResolvedAssessmentItem resolvedAssessmentItem, File unzippedDirectory, File itemFile) { ResolvedAssessmentItem resolvedAssessmentItem,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl); super(ureq, wControl);
this.itemRef = null; this.itemRef = null;
this.itemFile = itemFile;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
this.resolvedAssessmentItem = resolvedAssessmentItem; this.resolvedAssessmentItem = resolvedAssessmentItem;
mainVC = createVelocityContainer("assessment_item_editor"); mainVC = createVelocityContainer("assessment_item_editor");
...@@ -99,7 +107,7 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -99,7 +107,7 @@ public class AssessmentItemEditorController extends BasicController {
initItemEditor(ureq); initItemEditor(ureq);
displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(), resolvedAssessmentItem, unzippedDirectory, itemFile); displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(), resolvedAssessmentItem, rootDirectory, itemFile);
listenTo(displayCtrl); listenTo(displayCtrl);
tabbedPane.addTab("Preview", displayCtrl.getInitialComponent()); tabbedPane.addTab("Preview", displayCtrl.getInitialComponent());
...@@ -108,10 +116,13 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -108,10 +116,13 @@ public class AssessmentItemEditorController extends BasicController {
public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl, RepositoryEntry testEntry, public AssessmentItemEditorController(UserRequest ureq, WindowControl wControl, RepositoryEntry testEntry,
ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, ManifestMetadataBuilder metadataBuilder, ResolvedAssessmentItem resolvedAssessmentItem, AssessmentItemRef itemRef, ManifestMetadataBuilder metadataBuilder,
File unzippedDirectory) { File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl); super(ureq, wControl);
this.itemRef = itemRef; this.itemRef = itemRef;
this.metadataBuilder = metadataBuilder; this.metadataBuilder = metadataBuilder;
this.itemFile = itemFile;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
this.resolvedAssessmentItem = resolvedAssessmentItem; this.resolvedAssessmentItem = resolvedAssessmentItem;
mainVC = createVelocityContainer("assessment_item_editor"); mainVC = createVelocityContainer("assessment_item_editor");
...@@ -123,7 +134,7 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -123,7 +134,7 @@ public class AssessmentItemEditorController extends BasicController {
AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(getIdentity(), testEntry, null, testEntry); AssessmentEntry assessmentEntry = assessmentService.getOrCreateAssessmentEntry(getIdentity(), testEntry, null, testEntry);
displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(), displayCtrl = new AssessmentItemDisplayController(ureq, getWindowControl(),
testEntry, assessmentEntry, true, resolvedAssessmentItem, itemRef, unzippedDirectory); testEntry, assessmentEntry, true, resolvedAssessmentItem, itemRef, rootDirectory);
listenTo(displayCtrl); listenTo(displayCtrl);
tabbedPane.addTab("Preview", displayCtrl.getInitialComponent()); tabbedPane.addTab("Preview", displayCtrl.getInitialComponent());
...@@ -167,7 +178,8 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -167,7 +178,8 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemBuilder initSingleChoiceEditors(UserRequest ureq, AssessmentItem item) { private AssessmentItemBuilder initSingleChoiceEditors(UserRequest ureq, AssessmentItem item) {
SingleChoiceAssessmentItemBuilder scItemBuilder = new SingleChoiceAssessmentItemBuilder(item, qtiService.qtiSerializer()); SingleChoiceAssessmentItemBuilder scItemBuilder = new SingleChoiceAssessmentItemBuilder(item, qtiService.qtiSerializer());
itemEditor = new SingleChoiceEditorController(ureq, getWindowControl(), scItemBuilder); itemEditor = new SingleChoiceEditorController(ureq, getWindowControl(), scItemBuilder,
rootDirectory, rootContainer, itemFile);
listenTo(itemEditor); listenTo(itemEditor);
scoreEditor = new ChoiceScoreController(ureq, getWindowControl(), scItemBuilder, itemRef); scoreEditor = new ChoiceScoreController(ureq, getWindowControl(), scItemBuilder, itemRef);
listenTo(scoreEditor); listenTo(scoreEditor);
...@@ -182,7 +194,8 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -182,7 +194,8 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemBuilder initMultipleChoiceEditors(UserRequest ureq, AssessmentItem item) { private AssessmentItemBuilder initMultipleChoiceEditors(UserRequest ureq, AssessmentItem item) {
MultipleChoiceAssessmentItemBuilder mcItemBuilder = new MultipleChoiceAssessmentItemBuilder(item, qtiService.qtiSerializer()); MultipleChoiceAssessmentItemBuilder mcItemBuilder = new MultipleChoiceAssessmentItemBuilder(item, qtiService.qtiSerializer());
itemEditor = new MultipleChoiceEditorController(ureq, getWindowControl(), mcItemBuilder); itemEditor = new MultipleChoiceEditorController(ureq, getWindowControl(), mcItemBuilder,
rootDirectory, rootContainer, itemFile);
listenTo(itemEditor); listenTo(itemEditor);
scoreEditor = new ChoiceScoreController(ureq, getWindowControl(), mcItemBuilder, itemRef); scoreEditor = new ChoiceScoreController(ureq, getWindowControl(), mcItemBuilder, itemRef);
listenTo(scoreEditor); listenTo(scoreEditor);
...@@ -197,7 +210,8 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -197,7 +210,8 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemBuilder initKPrimChoiceEditors(UserRequest ureq, AssessmentItem item) { private AssessmentItemBuilder initKPrimChoiceEditors(UserRequest ureq, AssessmentItem item) {
KPrimAssessmentItemBuilder kprimItemBuilder = new KPrimAssessmentItemBuilder(item, qtiService.qtiSerializer()); KPrimAssessmentItemBuilder kprimItemBuilder = new KPrimAssessmentItemBuilder(item, qtiService.qtiSerializer());
itemEditor = new KPrimEditorController(ureq, getWindowControl(), kprimItemBuilder); itemEditor = new KPrimEditorController(ureq, getWindowControl(), kprimItemBuilder,
rootDirectory, rootContainer, itemFile);
listenTo(itemEditor); listenTo(itemEditor);
scoreEditor = new MinimalScoreController(ureq, getWindowControl(), kprimItemBuilder, itemRef); scoreEditor = new MinimalScoreController(ureq, getWindowControl(), kprimItemBuilder, itemRef);
listenTo(scoreEditor); listenTo(scoreEditor);
...@@ -212,7 +226,8 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -212,7 +226,8 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemBuilder initFIBEditors(UserRequest ureq, AssessmentItem item) { private AssessmentItemBuilder initFIBEditors(UserRequest ureq, AssessmentItem item) {
FIBAssessmentItemBuilder kprimItemBuilder = new FIBAssessmentItemBuilder(item, qtiService.qtiSerializer()); FIBAssessmentItemBuilder kprimItemBuilder = new FIBAssessmentItemBuilder(item, qtiService.qtiSerializer());
itemEditor = new FIBEditorController(ureq, getWindowControl(), kprimItemBuilder); itemEditor = new FIBEditorController(ureq, getWindowControl(), kprimItemBuilder,
rootDirectory, rootContainer, itemFile);
listenTo(itemEditor); listenTo(itemEditor);
scoreEditor = new FIBScoreController(ureq, getWindowControl(), kprimItemBuilder, itemRef); scoreEditor = new FIBScoreController(ureq, getWindowControl(), kprimItemBuilder, itemRef);
listenTo(scoreEditor); listenTo(scoreEditor);
...@@ -227,7 +242,8 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -227,7 +242,8 @@ public class AssessmentItemEditorController extends BasicController {
private AssessmentItemBuilder initEssayEditors(UserRequest ureq, AssessmentItem item) { private AssessmentItemBuilder initEssayEditors(UserRequest ureq, AssessmentItem item) {
EssayAssessmentItemBuilder essayItemBuilder = new EssayAssessmentItemBuilder(item, qtiService.qtiSerializer()); EssayAssessmentItemBuilder essayItemBuilder = new EssayAssessmentItemBuilder(item, qtiService.qtiSerializer());
itemEditor = new EssayEditorController(ureq, getWindowControl(), essayItemBuilder); itemEditor = new EssayEditorController(ureq, getWindowControl(), essayItemBuilder,
rootDirectory, rootContainer, itemFile);
listenTo(itemEditor); listenTo(itemEditor);
scoreEditor = new MinimalScoreController(ureq, getWindowControl(), essayItemBuilder, itemRef); scoreEditor = new MinimalScoreController(ureq, getWindowControl(), essayItemBuilder, itemRef);
listenTo(scoreEditor); listenTo(scoreEditor);
...@@ -271,8 +287,6 @@ public class AssessmentItemEditorController extends BasicController { ...@@ -271,8 +287,6 @@ public class AssessmentItemEditorController extends BasicController {
if(itemBuilder != null) { if(itemBuilder != null) {
itemBuilder.build(); itemBuilder.build();
} }
URI itemUri = resolvedAssessmentItem.getItemLookup().getSystemId();
File itemFile = new File(itemUri);
qtiService.updateAssesmentObject(itemFile, resolvedAssessmentItem); qtiService.updateAssesmentObject(itemFile, resolvedAssessmentItem);
} }
......
...@@ -55,6 +55,7 @@ import org.olat.core.gui.control.generic.wizard.StepRunnerCallback; ...@@ -55,6 +55,7 @@ import org.olat.core.gui.control.generic.wizard.StepRunnerCallback;
import org.olat.core.gui.control.generic.wizard.StepsMainRunController; import org.olat.core.gui.control.generic.wizard.StepsMainRunController;
import org.olat.core.gui.control.generic.wizard.StepsRunContext; import org.olat.core.gui.control.generic.wizard.StepsRunContext;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.fileresource.FileResourceManager; import org.olat.fileresource.FileResourceManager;
import org.olat.ims.qti21.QTI21Constants; import org.olat.ims.qti21.QTI21Constants;
import org.olat.ims.qti21.QTI21Service; import org.olat.ims.qti21.QTI21Service;
...@@ -128,6 +129,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -128,6 +129,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
private final LayoutMain3ColsController columnLayoutCtr; private final LayoutMain3ColsController columnLayoutCtr;
private final File unzippedDirRoot; private final File unzippedDirRoot;
private final VFSContainer unzippedContRoot;
private final RepositoryEntry testEntry; private final RepositoryEntry testEntry;
private ManifestBuilder manifestBuilder; private ManifestBuilder manifestBuilder;
private ResolvedAssessmentTest resolvedAssessmentTest; private ResolvedAssessmentTest resolvedAssessmentTest;
...@@ -161,6 +164,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -161,6 +164,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
FileResourceManager frm = FileResourceManager.getInstance(); FileResourceManager frm = FileResourceManager.getInstance();
unzippedDirRoot = frm.unzipFileResource(testEntry.getOlatResource()); unzippedDirRoot = frm.unzipFileResource(testEntry.getOlatResource());
unzippedContRoot = frm.unzipContainerResource(testEntry.getOlatResource());
updateTreeModel(); updateTreeModel();
manifestBuilder = ManifestBuilder.read(new File(unzippedDirRoot, "imsmanifest.xml")); manifestBuilder = ManifestBuilder.read(new File(unzippedDirRoot, "imsmanifest.xml"));
...@@ -536,8 +540,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -536,8 +540,8 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
} }
//persist metadata //persist metadata
manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
doSaveManifest();
updateTreeModel(); updateTreeModel();
TreeNode newItemNode = menuTree.getTreeModel().getNodeById(firstItemId); TreeNode newItemNode = menuTree.getTreeModel().getNodeById(firstItemId);
...@@ -562,7 +566,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -562,7 +566,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest); qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest);
manifestBuilder.appendAssessmentItem(itemFile.getName()); manifestBuilder.appendAssessmentItem(itemFile.getName());
manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml")); doSaveManifest();
return itemRef; return itemRef;
} }
...@@ -651,7 +655,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -651,7 +655,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest); qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest);
manifestBuilder.appendAssessmentItem(itemFile.getName()); manifestBuilder.appendAssessmentItem(itemFile.getName());
manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml")); doSaveManifest();
updateTreeModel(); updateTreeModel();
...@@ -685,7 +689,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -685,7 +689,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
} }
private void doSaveManifest() { private void doSaveManifest() {
this.manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml")); manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml"));
} }
private void doUpdate(Identifier identifier, String newTitle) { private void doUpdate(Identifier identifier, String newTitle) {
...@@ -730,9 +734,11 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -730,9 +734,11 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
currentEditorCtrl = new BadResourceController(ureq, getWindowControl(), currentEditorCtrl = new BadResourceController(ureq, getWindowControl(),
item.getItemLookup().getBadResourceException(), unzippedDirRoot, itemRef.getHref()); item.getItemLookup().getBadResourceException(), unzippedDirRoot, itemRef.getHref());
} else { } else {
URI itemUri = resolvedAssessmentTest.getSystemIdByItemRefMap().get(itemRef);
File itemFile = new File(itemUri);
ManifestMetadataBuilder metadata = getMetadataBuilder(itemRef); ManifestMetadataBuilder metadata = getMetadataBuilder(itemRef);
currentEditorCtrl = new AssessmentItemEditorController(ureq, getWindowControl(), testEntry, currentEditorCtrl = new AssessmentItemEditorController(ureq, getWindowControl(), testEntry,
item, itemRef, metadata, unzippedDirRoot); item, itemRef, metadata, unzippedDirRoot, unzippedContRoot, itemFile);
} }
} }
...@@ -765,8 +771,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -765,8 +771,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
itemRef.setIdentifier(Identifier.parseString(itemId)); itemRef.setIdentifier(Identifier.parseString(itemId));
itemFile = new File(unzippedDirRoot, itemId + ".xml"); itemFile = new File(unzippedDirRoot, itemId + ".xml");
itemRef.setHref(new URI(itemFile.getName())); itemRef.setHref(new URI(itemFile.getName()));
try(OutputStream out = new FileOutputStream(itemFile)) { try(OutputStream out = new FileOutputStream(itemFile)) {
//make the copy //make the copy
qtiService.qtiSerializer().serializeJqtiObject(originalAssessmentItem, out); qtiService.qtiSerializer().serializeJqtiObject(originalAssessmentItem, out);
...@@ -786,7 +791,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -786,7 +791,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest); qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest);
manifestBuilder.appendAssessmentItem(itemFile.getName()); manifestBuilder.appendAssessmentItem(itemFile.getName());
manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml")); doSaveManifest();
} catch (Exception e) { } catch (Exception e) {
logError("", e); logError("", e);
} }
...@@ -840,7 +845,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController ...@@ -840,7 +845,7 @@ public class AssessmentTestComposerController extends MainLayoutBasicController
URI testUri = resolvedAssessmentTest.getTestLookup().getSystemId(); URI testUri = resolvedAssessmentTest.getTestLookup().getSystemId();
File testFile = new File(testUri); File testFile = new File(testUri);
qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest); qtiService.updateAssesmentObject(testFile, resolvedAssessmentTest);
manifestBuilder.write(new File(unzippedDirRoot, "imsmanifest.xml")); doSaveManifest();
updateTreeModel(); updateTreeModel();
if(selectedNode != null && selectedNode.getParent() != null) { if(selectedNode != null && selectedNode.getParent() != null) {
......
...@@ -19,17 +19,19 @@ ...@@ -19,17 +19,19 @@
*/ */
package org.olat.ims.qti21.ui.editor.interactions; package org.olat.ims.qti21.ui.editor.interactions;
import java.io.File;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.RichTextElement; import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController; 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.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.richText.RichTextConfiguration;
import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder; import org.olat.ims.qti21.model.xml.interactions.EssayAssessmentItemBuilder;
import org.olat.ims.qti21.ui.editor.AssessmentTestEditorController; import org.olat.ims.qti21.ui.editor.AssessmentTestEditorController;
...@@ -47,13 +49,20 @@ public class EssayEditorController extends FormBasicController { ...@@ -47,13 +49,20 @@ public class EssayEditorController extends FormBasicController {
private TextElement placeholderEl; private TextElement placeholderEl;
private TextElement widthEl, heightEl, minWordsEl, maxWordsEl; private TextElement widthEl, heightEl, minWordsEl, maxWordsEl;
private RichTextElement textEl; private RichTextElement textEl;
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private final EssayAssessmentItemBuilder itemBuilder; private final EssayAssessmentItemBuilder itemBuilder;
public EssayEditorController(UserRequest ureq, WindowControl wControl, EssayAssessmentItemBuilder itemBuilder) { public EssayEditorController(UserRequest ureq, WindowControl wControl, EssayAssessmentItemBuilder itemBuilder,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl); super(ureq, wControl);
setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale())); setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
this.itemFile = itemFile;
this.itemBuilder = itemBuilder; this.itemBuilder = itemBuilder;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
initForm(ureq); initForm(ureq);
} }
...@@ -62,11 +71,12 @@ public class EssayEditorController extends FormBasicController { ...@@ -62,11 +71,12 @@ public class EssayEditorController extends FormBasicController {
titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout); titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), formLayout);
titleEl.setMandatory(true); titleEl.setMandatory(true);
String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
String description = itemBuilder.getQuestion(); String description = itemBuilder.getQuestion();
textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, null, null, textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, itemContainer, null,
formLayout, ureq.getUserSession(), getWindowControl()); formLayout, ureq.getUserSession(), getWindowControl());
RichTextConfiguration richTextConfig = textEl.getEditorConfiguration();
richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
String placeholder = itemBuilder.getPlaceholder(); String placeholder = itemBuilder.getPlaceholder();
placeholderEl = uifactory.addTextElement("placeholder", "fib.placeholder", 256, placeholder, formLayout); placeholderEl = uifactory.addTextElement("placeholder", "fib.placeholder", 256, placeholder, formLayout);
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
*/ */
package org.olat.ims.qti21.ui.editor.interactions; package org.olat.ims.qti21.ui.editor.interactions;
import java.io.File;
import org.olat.core.gui.UserRequest; import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem; 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.FormItemContainer;
...@@ -33,6 +35,7 @@ import org.olat.core.gui.control.Event; ...@@ -33,6 +35,7 @@ import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder; import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder;
import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder.TextEntry; import org.olat.ims.qti21.model.xml.interactions.FIBAssessmentItemBuilder.TextEntry;
...@@ -52,13 +55,20 @@ public class FIBEditorController extends FormBasicController { ...@@ -52,13 +55,20 @@ public class FIBEditorController extends FormBasicController {
private CloseableModalController cmc; private CloseableModalController cmc;
private FIBTextEntrySettingsController gapEntrySettingsCtrl; private FIBTextEntrySettingsController gapEntrySettingsCtrl;
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private final FIBAssessmentItemBuilder itemBuilder; private final FIBAssessmentItemBuilder itemBuilder;
public FIBEditorController(UserRequest ureq, WindowControl wControl, FIBAssessmentItemBuilder itemBuilder) { public FIBEditorController(UserRequest ureq, WindowControl wControl, FIBAssessmentItemBuilder itemBuilder,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl, "fib"); super(ureq, wControl, "fib");
setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale())); setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
this.itemFile = itemFile;
this.itemBuilder = itemBuilder; this.itemBuilder = itemBuilder;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
initForm(ureq); initForm(ureq);
} }
...@@ -72,13 +82,15 @@ public class FIBEditorController extends FormBasicController { ...@@ -72,13 +82,15 @@ public class FIBEditorController extends FormBasicController {
titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata); titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
titleEl.setMandatory(true); titleEl.setMandatory(true);
String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
String description = itemBuilder.getQuestion(); String description = itemBuilder.getQuestion();
textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, null, null, textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, itemContainer, null,
metadata, ureq.getUserSession(), getWindowControl()); metadata, ureq.getUserSession(), getWindowControl());
textEl.addActionListener(FormEvent.ONCLICK); textEl.addActionListener(FormEvent.ONCLICK);
RichTextConfiguration richTextConfig = textEl.getEditorConfiguration(); RichTextConfiguration richTextConfig = textEl.getEditorConfiguration();
richTextConfig.enableQTITools(); richTextConfig.enableQTITools();
richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
// Submit Button // Submit Button
FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); FormLayoutContainer buttonsContainer = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
package org.olat.ims.qti21.ui.editor.interactions; package org.olat.ims.qti21.ui.editor.interactions;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -32,11 +33,11 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement; ...@@ -32,11 +33,11 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.richText.RichTextConfiguration;
import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.QTI21Constants; import org.olat.ims.qti21.QTI21Constants;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder; import org.olat.ims.qti21.model.xml.interactions.KPrimAssessmentItemBuilder;
...@@ -65,12 +66,19 @@ public class KPrimEditorController extends FormBasicController { ...@@ -65,12 +66,19 @@ public class KPrimEditorController extends FormBasicController {
private final List<KprimWrapper> choiceWrappers = new ArrayList<>(); private final List<KprimWrapper> choiceWrappers = new ArrayList<>();
private int count = 0; private int count = 0;
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private final KPrimAssessmentItemBuilder itemBuilder; private final KPrimAssessmentItemBuilder itemBuilder;
public KPrimEditorController(UserRequest ureq, WindowControl wControl, KPrimAssessmentItemBuilder itemBuilder) { public KPrimEditorController(UserRequest ureq, WindowControl wControl, KPrimAssessmentItemBuilder itemBuilder,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl, "simple_choices_editor"); super(ureq, wControl, "simple_choices_editor");
setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale())); setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
this.itemFile = itemFile;
this.itemBuilder = itemBuilder; this.itemBuilder = itemBuilder;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
initForm(ureq); initForm(ureq);
} }
...@@ -84,13 +92,12 @@ public class KPrimEditorController extends FormBasicController { ...@@ -84,13 +92,12 @@ public class KPrimEditorController extends FormBasicController {
titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata); titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
titleEl.setMandatory(true); titleEl.setMandatory(true);
String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
String description = itemBuilder.getQuestion(); String description = itemBuilder.getQuestion();
textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, null, null, textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, itemContainer, null,
metadata, ureq.getUserSession(), getWindowControl()); metadata, ureq.getUserSession(), getWindowControl());
RichTextConfiguration richTextConfig = textEl.getEditorConfiguration();
richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
//points -> in other controller
//shuffle //shuffle
String[] yesnoValues = new String[]{ translate("yes"), translate("no") }; String[] yesnoValues = new String[]{ translate("yes"), translate("no") };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
package org.olat.ims.qti21.ui.editor.interactions; package org.olat.ims.qti21.ui.editor.interactions;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -32,12 +33,12 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement; ...@@ -32,12 +33,12 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.richText.RichTextConfiguration;
import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.model.IdentifierGenerator; import org.olat.ims.qti21.model.IdentifierGenerator;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.xml.AssessmentItemFactory; import org.olat.ims.qti21.model.xml.AssessmentItemFactory;
...@@ -64,15 +65,24 @@ public class MultipleChoiceEditorController extends FormBasicController { ...@@ -64,15 +65,24 @@ public class MultipleChoiceEditorController extends FormBasicController {
private FormLayoutContainer answersCont; private FormLayoutContainer answersCont;
private final List<SimpleChoiceWrapper> choiceWrappers = new ArrayList<>(); private final List<SimpleChoiceWrapper> choiceWrappers = new ArrayList<>();
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private int count = 0; private int count = 0;
private final MultipleChoiceAssessmentItemBuilder itemBuilder; private final MultipleChoiceAssessmentItemBuilder itemBuilder;
private static final String[] yesnoKeys = new String[]{ "y", "n"}; private static final String[] yesnoKeys = new String[]{ "y", "n"};
public MultipleChoiceEditorController(UserRequest ureq, WindowControl wControl, MultipleChoiceAssessmentItemBuilder itemBuilder) { public MultipleChoiceEditorController(UserRequest ureq, WindowControl wControl,
MultipleChoiceAssessmentItemBuilder itemBuilder,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl, "simple_choices_editor"); super(ureq, wControl, "simple_choices_editor");
setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale())); setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
this.itemBuilder = itemBuilder; this.itemBuilder = itemBuilder;
this.itemFile = itemFile;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
initForm(ureq); initForm(ureq);
} }
...@@ -88,13 +98,12 @@ public class MultipleChoiceEditorController extends FormBasicController { ...@@ -88,13 +98,12 @@ public class MultipleChoiceEditorController extends FormBasicController {
titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata); titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
titleEl.setMandatory(true); titleEl.setMandatory(true);
String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
String description = itemBuilder.getQuestion(); String description = itemBuilder.getQuestion();
textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, null, null, textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, itemContainer, null,
metadata, ureq.getUserSession(), getWindowControl()); metadata, ureq.getUserSession(), getWindowControl());
RichTextConfiguration richTextConfig = textEl.getEditorConfiguration();
richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
//points -> in other controller
//shuffle //shuffle
String[] yesnoValues = new String[]{ translate("yes"), translate("no") }; String[] yesnoValues = new String[]{ translate("yes"), translate("no") };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
package org.olat.ims.qti21.ui.editor.interactions; package org.olat.ims.qti21.ui.editor.interactions;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -32,12 +33,12 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement; ...@@ -32,12 +33,12 @@ import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.form.flexible.impl.elements.richText.RichTextConfiguration;
import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.WindowControl;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.Util; import org.olat.core.util.Util;
import org.olat.core.util.vfs.VFSContainer;
import org.olat.ims.qti21.model.QTI21QuestionType; import org.olat.ims.qti21.model.QTI21QuestionType;
import org.olat.ims.qti21.model.xml.AssessmentItemFactory; import org.olat.ims.qti21.model.xml.AssessmentItemFactory;
import org.olat.ims.qti21.model.xml.interactions.SingleChoiceAssessmentItemBuilder; import org.olat.ims.qti21.model.xml.interactions.SingleChoiceAssessmentItemBuilder;
...@@ -63,14 +64,22 @@ public class SingleChoiceEditorController extends FormBasicController { ...@@ -63,14 +64,22 @@ public class SingleChoiceEditorController extends FormBasicController {
private final List<SimpleChoiceWrapper> choiceWrappers = new ArrayList<>(); private final List<SimpleChoiceWrapper> choiceWrappers = new ArrayList<>();
private int count = 0; private int count = 0;
private final File itemFile;
private final File rootDirectory;
private final VFSContainer rootContainer;
private final SingleChoiceAssessmentItemBuilder itemBuilder; private final SingleChoiceAssessmentItemBuilder itemBuilder;
private static final String[] yesnoKeys = new String[]{ "y", "n"}; private static final String[] yesnoKeys = new String[]{ "y", "n"};
public SingleChoiceEditorController(UserRequest ureq, WindowControl wControl, SingleChoiceAssessmentItemBuilder itemBuilder) { public SingleChoiceEditorController(UserRequest ureq, WindowControl wControl,
SingleChoiceAssessmentItemBuilder itemBuilder,
File rootDirectory, VFSContainer rootContainer, File itemFile) {
super(ureq, wControl, "simple_choices_editor"); super(ureq, wControl, "simple_choices_editor");
setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale())); setTranslator(Util.createPackageTranslator(AssessmentTestEditorController.class, getLocale()));
this.itemBuilder = itemBuilder; this.itemBuilder = itemBuilder;
this.itemFile = itemFile;
this.rootDirectory = rootDirectory;
this.rootContainer = rootContainer;
initForm(ureq); initForm(ureq);
} }
...@@ -83,14 +92,13 @@ public class SingleChoiceEditorController extends FormBasicController { ...@@ -83,14 +92,13 @@ public class SingleChoiceEditorController extends FormBasicController {
titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata); titleEl = uifactory.addTextElement("title", "form.imd.title", -1, itemBuilder.getTitle(), metadata);
titleEl.setMandatory(true); titleEl.setMandatory(true);
String relativePath = rootDirectory.toPath().relativize(itemFile.toPath().getParent()).toString();
VFSContainer itemContainer = (VFSContainer)rootContainer.resolve(relativePath);
String description = itemBuilder.getQuestion(); String description = itemBuilder.getQuestion();
textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, null, null, textEl = uifactory.addRichTextElementForStringData("desc", "form.imd.descr", description, 8, -1, true, itemContainer, null,
metadata, ureq.getUserSession(), getWindowControl()); metadata, ureq.getUserSession(), getWindowControl());
RichTextConfiguration richTextConfig = textEl.getEditorConfiguration();
richTextConfig.setFileBrowserUploadRelPath("media");// set upload dir to the media dir
//points -> in other controller
//shuffle //shuffle
String[] yesnoValues = new String[]{ translate("yes"), translate("no") }; String[] yesnoValues = new String[]{ translate("yes"), translate("no") };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment