diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java index 18786de6321cd440836757ee1b705336077ec021..423ea79b6e4f9d7975b68cd9a7714c2997758557 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentityCourseController.java @@ -74,6 +74,8 @@ public class AssessmentIdentityCourseController extends BasicController implemen private CourseNodeSelectionController courseNodeChooserCtrl; private CloseableCalloutWindowController courseNodeChooserCalloutCtrl; + private CourseNode currentCourseNode; + @Autowired private BaseSecurity securityManager; @@ -182,6 +184,11 @@ public class AssessmentIdentityCourseController extends BasicController implemen courseNodeChooserCtrl = new CourseNodeSelectionController(ureq, getWindowControl(), courseEntry); listenTo(courseNodeChooserCtrl); + if(currentCourseNode != null) { + courseNodeChooserCtrl.selectedCourseNode(currentCourseNode); + } else { + courseNodeChooserCtrl.selectedCourseNode(treeOverviewCtrl.getSelectedCourseNode()); + } courseNodeChooserCalloutCtrl = new CloseableCalloutWindowController(ureq, getWindowControl(), courseNodeChooserCtrl.getInitialComponent(), courseNodeSelectionLink, "", true, ""); @@ -210,7 +217,8 @@ public class AssessmentIdentityCourseController extends BasicController implemen private void doSelectCourseNode(UserRequest ureq, CourseNode courseNode) { if(courseNode == null) { return; - } + } + currentCourseNode = courseNode; stackPanel.popUpToController(this); if(treeOverviewCtrl.isRoot(courseNode)) { return; @@ -241,7 +249,9 @@ public class AssessmentIdentityCourseController extends BasicController implemen nextLink = LinkFactory.createToolLink("nextelement", translate("next"), this, "o_icon_next"); nextLink.setTitle(translate("command.next")); - nextLink.setEnabled(index > 0 && index < numOfNodes); + CourseNode nextNode = treeOverviewCtrl.getNextNode(courseNode); + boolean hasNext = (nextNode != null && nextNode.getParent() != null); + nextLink.setEnabled(hasNext); stackPanel.addTool(nextLink, Align.rightEdge, false); } } diff --git a/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java b/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java index 4102b829d3dbecde40da3586a5f4ecac22f5460f..64478f027ac14f8eaa063d34112657ae612b20bc 100644 --- a/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java +++ b/src/main/java/org/olat/course/assessment/ui/tool/CourseNodeSelectionController.java @@ -22,16 +22,21 @@ package org.olat.course.assessment.ui.tool; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.tree.MenuTree; +import org.olat.core.gui.components.tree.TreeEvent; import org.olat.core.gui.components.tree.TreeModel; +import org.olat.core.gui.components.tree.TreeNode; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; +import org.olat.core.util.tree.TreeHelper; import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.AssessmentHelper; import org.olat.course.assessment.ui.tool.event.CourseNodeEvent; +import org.olat.course.nodes.AssessableCourseNode; import org.olat.course.nodes.CourseNode; +import org.olat.course.nodes.STCourseNode; import org.olat.repository.RepositoryEntry; /** @@ -53,6 +58,7 @@ public class CourseNodeSelectionController extends BasicController { menuTree = new MenuTree("menuTree"); TreeModel tm = AssessmentHelper.assessmentTreeModel(course); menuTree.setTreeModel(tm); + menuTree.setExpandSelectedNode(true); menuTree.setSelectedNodeId(tm.getRootNode().getIdent()); menuTree.addListener(this); @@ -65,15 +71,36 @@ public class CourseNodeSelectionController extends BasicController { protected void doDispose() { // } + + public void selectedCourseNode(CourseNode courseNode) { + TreeNode selectedNode = TreeHelper.findNodeByUserObject(courseNode, menuTree.getTreeModel().getRootNode()); + if(selectedNode != null) { + menuTree.setSelectedNode(selectedNode); + } + } @Override protected void event(UserRequest ureq, Component source, Event event) { if (source == menuTree) { - if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) { - Object uo = menuTree.getSelectedNode().getUserObject(); - if(uo instanceof CourseNode) { - CourseNode selectedNode = (CourseNode)uo; - fireEvent(ureq, new CourseNodeEvent(CourseNodeEvent.SELECT_COURSE_NODE, selectedNode.getIdent())); + if(event instanceof TreeEvent) { + TreeEvent te = (TreeEvent)event; + if(TreeEvent.COMMAND_TREENODE_OPEN.equals(te.getSubCommand()) || TreeEvent.COMMAND_TREENODE_CLOSE.equals(te.getSubCommand())) { + Object uo = menuTree.getSelectedNode().getUserObject(); + if(menuTree.getSelectedNode() == menuTree.getTreeModel().getRootNode()) { + //do nothing + } else if(uo instanceof AssessableCourseNode && !(uo instanceof STCourseNode)) { + AssessableCourseNode selectedNode = (AssessableCourseNode)uo; + fireEvent(ureq, new CourseNodeEvent(CourseNodeEvent.SELECT_COURSE_NODE, selectedNode.getIdent())); + } + } else if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) { + Object uo = menuTree.getSelectedNode().getUserObject(); + if(menuTree.getSelectedNode() == menuTree.getTreeModel().getRootNode()) { + CourseNode rootNode = (CourseNode)uo; + fireEvent(ureq, new CourseNodeEvent(CourseNodeEvent.SELECT_COURSE_NODE, rootNode.getIdent())); + } else if(uo instanceof AssessableCourseNode && !(uo instanceof STCourseNode)) { + AssessableCourseNode selectedNode = (AssessableCourseNode)uo; + fireEvent(ureq, new CourseNodeEvent(CourseNodeEvent.SELECT_COURSE_NODE, selectedNode.getIdent())); + } } } } diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java index f58ffed61e2bf94140c0b81fd91ce587ffc651c4..35c58576e2a37d8bac7e329a6f4e8dffe5af1464 100644 --- a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java +++ b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java @@ -473,6 +473,12 @@ public class QTI12To21Converter { String questionText = question.getQuestion().renderAsHtmlForEditor(); itemBuilder.setQuestion(questionText); + String hintText = question.getHintText(); + if(StringHelper.containsNonWhitespace(hintText)) { + ModalFeedbackBuilder hint = itemBuilder.createHint(); + hint.setText(hintText); + } + String feedbackMastery = QTIEditHelper.getFeedbackMasteryText(item); if(StringHelper.containsNonWhitespace(feedbackMastery)) { ModalFeedbackBuilder feedback = itemBuilder.createCorrectFeedback(); @@ -484,6 +490,7 @@ public class QTI12To21Converter { ModalFeedbackBuilder feedback = itemBuilder.createIncorrectFeedback(); feedback.setText(feedbackFail); } + } private void convertDuration(Duration duration, ControlObject<?> parent) { 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 a13c81485bf0d3059acbfaa6f3209c62e5569400..45a342ffaf3485adc654a081759d455e1742f807 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 @@ -97,3 +97,5 @@ test.complete=Test complete test.entry.page.text=This test consists of up to {0} parts. test.entry.page.title=Test entry test.part.complete=Test part complete +unsupported.custom.interaction=Unsupported custom interaction + 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 cb29ac41fb7b15b6da5f1280565ff84ae0f5eb79..48640f47fb8aac1b988150ee03de490477d46468 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 @@ -82,6 +82,7 @@ import org.olat.core.logging.Tracing; import org.olat.core.util.CodeHelper; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; +import org.olat.ims.qti21.QTI21Module; import org.olat.ims.qti21.QTI21Service; import org.olat.ims.qti21.XmlUtilities; import org.xml.sax.InputSource; @@ -595,6 +596,12 @@ public abstract class AssessmentObjectComponentRenderer extends DefaultComponent } break; } + case "mathEntryInteraction": { + if(!CoreSpringFactory.getImpl(QTI21Module.class).isMathAssessExtensionEnabled()) { + interactionName = "mathEntryInteractionNotEnabled"; + break; + } + } default: interactionName = interaction.getQtiClassName(); break; } diff --git a/src/main/java/org/olat/ims/qti21/ui/components/_content/unsupportedCustomInteraction.html b/src/main/java/org/olat/ims/qti21/ui/components/_content/unsupportedCustomInteraction.html index 03b3761d0546d3a8ee46484bd6a0535321592105..b4e165e9ada46aaf2a8ac073b4a2f50b24542eba 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/_content/unsupportedCustomInteraction.html +++ b/src/main/java/org/olat/ims/qti21/ui/components/_content/unsupportedCustomInteraction.html @@ -1 +1 @@ -<h1>Unsupported custom interaction</h1> \ No newline at end of file +<div class="o_warning">$r.translate("unsupported.custom.interaction") <strong><$localName></strong></div> \ No newline at end of file diff --git a/src/main/java/org/olat/user/propertyhandlers/DateDisplayPropertyHandler.java b/src/main/java/org/olat/user/propertyhandlers/DateDisplayPropertyHandler.java index f770c83c5f10a7eaa097ac052b07cc8027c10b47..de3d7b7dc3dc4e969ac95e8c66381d6b97345b8a 100644 --- a/src/main/java/org/olat/user/propertyhandlers/DateDisplayPropertyHandler.java +++ b/src/main/java/org/olat/user/propertyhandlers/DateDisplayPropertyHandler.java @@ -142,4 +142,9 @@ public class DateDisplayPropertyHandler extends AbstractUserPropertyHandler { public String getStringValue(String displayValue, Locale locale) { return displayValue; } + + @Override + protected void setInternalGetterSetter(String name) { + //do nothing, artificial value + } } \ No newline at end of file