diff --git a/src/main/java/org/olat/core/dispatcher/mapper/MapperDispatcher.java b/src/main/java/org/olat/core/dispatcher/mapper/MapperDispatcher.java index 321c9c1bc6cbeb80cb90b41e58eaf7660f8d8290..13b219ef8cb1a95cff216256306908389ed2860e 100644 --- a/src/main/java/org/olat/core/dispatcher/mapper/MapperDispatcher.java +++ b/src/main/java/org/olat/core/dispatcher/mapper/MapperDispatcher.java @@ -31,13 +31,13 @@ import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.logging.log4j.Logger; import org.olat.core.CoreSpringFactory; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherModule; import org.olat.core.gui.media.MediaResource; import org.olat.core.gui.media.ServletUtil; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.UserSession; import org.olat.core.util.session.UserSessionManager; @@ -91,20 +91,21 @@ public class MapperDispatcher implements Dispatcher { // e.g. non-cacheable: 23423 // e.g. cacheable: my.mapper.path UserSession usess = CoreSpringFactory.getImpl(UserSessionManager.class).getUserSession(hreq); - Mapper m = CoreSpringFactory.getImpl(MapperService.class).getMapperById(usess, smappath); + MapperService mapperService = CoreSpringFactory.getImpl(MapperService.class); + Mapper m = mapperService.getMapperById(usess, smappath); if (m == null) { //an anonymous mapper? - m = CoreSpringFactory.getImpl(MapperService.class).getMapperById(null, smappath); + m = mapperService.getMapperById(null, smappath); if(m == null) { log.warn("Call to mapped resource, but mapper does not exist for path::" + smappath); - DispatcherModule.sendNotFound(pathInfo, hres); + hres.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } } String mod = slashPos > 0 ? subInfo.substring(slashPos) : ""; if (mod.indexOf("..") != -1) { log.warn("Illegal mapper path::" + mod + " contains '..'"); - DispatcherModule.sendForbidden(pathInfo, hres); + hres.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } // /bla/blu.html diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java index dd27e14b5acc654693f9aa3103b625bbc45a86c4..9517f550ea39638828152d5490e3dac7ded2c995 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/Form.java @@ -437,14 +437,21 @@ public class Form { } private final void submit(UserRequest ureq, Event validationOkEvent) { + boolean isValid = validate(ureq); + formWrapperComponent.fireValidation(ureq, isValid, validationOkEvent); + isValidAndSubmitted = isValid; + hasAlreadyFired = true; + } + + public boolean validate(UserRequest ureq) { ValidatingFormComponentVisitor vfcv = new ValidatingFormComponentVisitor(); FormComponentTraverser ct = new FormComponentTraverser(vfcv, formLayout, false); ct.visitAll(ureq); // validate all form elements and gather validation status ValidationStatus[] status = vfcv.getStatus(); - // + boolean isValid = status == null || status.length == 0; - // let the businesslogic validate this is implemented by the outside listener + // let the business logic validate this is implemented by the outside listener for (Iterator<FormBasicController> iterator = formListeners.iterator(); iterator.hasNext();) { FormBasicController fbc = iterator.next(); @@ -452,10 +459,7 @@ public class Form { //let further validate even if one fails. isValid = fbc.validateFormLogic(ureq) && isValid; } - - formWrapperComponent.fireValidation(ureq, isValid, validationOkEvent); - isValidAndSubmitted = isValid; - hasAlreadyFired = true; + return isValid; } diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java index 98b7357b861ea57b71162c06ea68d7eeafe954ca..643ad5575db65d23239f21a82cd690b3d8abeec3 100644 --- a/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java @@ -249,6 +249,13 @@ public class AssessmentModeCoordinationServiceImpl implements AssessmentModeCoor mode = ensureStatusOfMode(mode, Status.none); sendEvent(AssessmentModeNotificationEvent.BEFORE, mode, assessmentModeManager.getAssessedIdentityKeys(mode)); + } else if(mode.getStatus() == Status.followup && mode.isManualBeginEnd() && !forceStatus) { + // close manual assessment mode in the follow-up time but started before the begin date + if(mode.getEndWithFollowupTime().compareTo(now) < 0) { + mode = ensureStatusOfMode(mode, Status.end); + sendEvent(AssessmentModeNotificationEvent.END, mode, + assessmentModeManager.getAssessedIdentityKeys(mode)); + } } } else if(mode.getBeginWithLeadTime().compareTo(now) <= 0 && mode.getBegin().compareTo(now) > 0 && mode.getBeginWithLeadTime().compareTo(mode.getBegin()) != 0) { diff --git a/src/main/java/org/olat/course/editor/MultiSPController.java b/src/main/java/org/olat/course/editor/MultiSPController.java index a442b06916fcfca918e623c6a752ec65102e07a1..d53da1dd07c0edd2b2bbc9c213b7c5fed93afc80 100644 --- a/src/main/java/org/olat/course/editor/MultiSPController.java +++ b/src/main/java/org/olat/course/editor/MultiSPController.java @@ -21,6 +21,8 @@ package org.olat.course.editor; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -130,7 +132,10 @@ public class MultiSPController extends FormBasicController { if(item instanceof VFSContainer) { VFSContainer container = (VFSContainer)item; - for(VFSItem subItem:container.getItems(new MultiSPVFSItemFilter())) { + List<VFSItem> subItems = container.getItems(new MultiSPVFSItemFilter()); + Collections.sort(subItems, new VFSItemNameComparator()); + + for(VFSItem subItem:subItems) { MultipleSelectionElement sel = initTreeRec(level + 1, subItem, layoutcont); node.getChildren().add(sel); } @@ -233,7 +238,8 @@ public class MultiSPController extends FormBasicController { } //recurse - for(MultipleSelectionElement childElement:node.getChildren()) { + List<MultipleSelectionElement> childElements = node.getChildren(); + for(MultipleSelectionElement childElement:childElements) { create(childElement, course, parentNode); } } @@ -336,11 +342,29 @@ public class MultiSPController extends FormBasicController { } } - public class MultiSPVFSItemFilter implements VFSItemFilter { + public static class MultiSPVFSItemFilter implements VFSItemFilter { @Override public boolean accept(VFSItem vfsItem) { String name = vfsItem.getName(); return !name.startsWith("."); } } + + public static class VFSItemNameComparator implements Comparator<VFSItem> { + + @Override + public int compare(VFSItem o1, VFSItem o2) { + if(o1 == null && o2 == null) return 0; + if(o1 == null) return -1; + if(o2 == null) return 1; + + String n1 = o1.getName(); + String n2 = o2.getName(); + + if(n1 == null && n2 == null) return 0; + if(n1 == null) return -1; + if(n2 == null) return 1; + return n1.compareToIgnoreCase(n2); + } + } } \ No newline at end of file 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 63838760be8157be3bccdf4d6d63a3ff8ecee719..f530557c0403f7e5f0e8f44840fd8b9928605647 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 @@ -518,6 +518,14 @@ jEl.css('height', jEl.attr('height') + "px"); } }); + jQuery('#collapse_${itemResult.interactionResults.solutionFormItem.name} div.o_oo_hotcontainer>div').each(function(index, el) { + var jEl = jQuery(el); + if(jEl.css('height') == '0px') { + var containerEl = jEl.closest("div.o_oo_hotcontainer"); + jEl.css('height', containerEl.css('height')); + jEl.css('background-size', containerEl.css('width') + " " + containerEl.css('height')); + } + }); }) }); /* ]]> */ diff --git a/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java b/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java index 2a01c6473aa63a92773395cbc47eb9ae03b5d9e0..dae813353e24884f18c451fb20e097d5e05468b8 100644 --- a/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java +++ b/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java @@ -181,13 +181,17 @@ public class RubricStatisticImpl implements RubricStatistic { Double mean = sumAverage.getAverage(); if (mean == null) return null; - List<Double> scaledValues = getScaledValues(stepCounts); - if (scaledValues.size() < 2) return null; - double temp = 0; - for(double a: scaledValues) - temp += (a-mean)*(a-mean); - return temp/(scaledValues.size() - 1); + int size = 0; + for (int step = 1; step <= rubric.getSteps(); step++) { + double value = rubric.getScaleType().getStepValue(rubric.getSteps(), step, rubric.getWeight()); + int count = stepCounts.get(step - 1).intValue(); + for (int i = 0; i < count; i++) { + temp += (value-mean)*(value-mean); + size++; + } + } + return size > 2? temp/(size - 1): null; } private Double getStdDev(List<Long> stepCounts) { @@ -197,21 +201,6 @@ public class RubricStatisticImpl implements RubricStatistic { return Math.sqrt(getVariance(stepCounts)); } - private List<Double> getScaledValues(List<Long> stepCounts) { - List<Double> scaledValues = new ArrayList<>(); - for (int step = 1; step <= rubric.getSteps(); step++) { - Long count = stepCounts.get(step - 1); - if (count != null) { - double stepValue = rubric.getScaleType().getStepValue(rubric.getSteps(), step, rubric.getWeight()); - for (int i = 0; i < count; i++) { - double scaledValue = stepValue * step; - scaledValues.add(Double.valueOf(scaledValue)); - } - } - } - return scaledValues; - } - private void calculateTotalStatistics() { Long numberOfNoResponses = countedNoResponses.stream().mapToLong(CalculatedLong::getValue).sum(); List<Long> totalStepCounts = getTotalStepCounts(); diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java index 6e35c328746b9380d7a656ba3594419e5455b63c..1c80773559172f913543d3804c6c704d150c4baa 100644 --- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java +++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java @@ -92,8 +92,6 @@ public class EvaluationFormExecutionController extends FormBasicController imple private boolean readOnly; private boolean showDoneButton; - private boolean immediateSave = false; - private EvaluationFormSession session; private final EvaluationFormResponses responses; @@ -268,11 +266,9 @@ public class EvaluationFormExecutionController extends FormBasicController imple @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if (saveLink == source) { - immediateSave = true; - mainForm.submit(ureq); - } else if (doneLink == source) { - immediateSave = false; - mainForm.submit(ureq); + if(mainForm.validate(ureq)) { + doSaveResponses(); + } } super.formInnerEvent(ureq, source, event); } @@ -290,7 +286,7 @@ public class EvaluationFormExecutionController extends FormBasicController imple @Override protected void formOK(UserRequest ureq) { boolean responsesSaved = doSaveResponses(); - if (!immediateSave && responsesSaved) { + if (responsesSaved) { doConfirmDone(ureq); } } @@ -340,7 +336,7 @@ public class EvaluationFormExecutionController extends FormBasicController imple List<ValidationMessage> messages = new ArrayList<>(); validate(ureq, messages); - if (messages.size() > 0) { + if (!messages.isEmpty()) { for (ValidationMessage message : messages) { sb.append("<p class='o_warning'>").append(message.getMessage()).append("</p>"); } diff --git a/src/main/java/org/olat/modules/forms/ui/TextInputController.java b/src/main/java/org/olat/modules/forms/ui/TextInputController.java index a01405357f9667098c6a52267a67ffcba348a104..b289e631eda83f30dcf4ee7e860cbdb6bf947402 100644 --- a/src/main/java/org/olat/modules/forms/ui/TextInputController.java +++ b/src/main/java/org/olat/modules/forms/ui/TextInputController.java @@ -103,7 +103,7 @@ public class TextInputController extends FormBasicController implements Evaluati @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); if (textInput.isNumeric()) { String val = singleRowEl.getValue(); @@ -117,7 +117,7 @@ public class TextInputController extends FormBasicController implements Evaluati } } - return allOk & super.validateFormLogic(ureq); + return allOk; } @Override diff --git a/src/main/webapp/static/js/jquery/openolat/jquery.contenteditor.js b/src/main/webapp/static/js/jquery/openolat/jquery.contenteditor.js index ad7ac0d8491cf8ada4e26a7b8228b27393123496..f709154f000ac02d6585e30214e875e3c0052a47 100644 --- a/src/main/webapp/static/js/jquery/openolat/jquery.contenteditor.js +++ b/src/main/webapp/static/js/jquery/openolat/jquery.contenteditor.js @@ -83,7 +83,8 @@ || jQuery(e.target).closest(".mce-container").length > 0 || jQuery(e.target).closest(".mce-widget").length > 0 || jQuery(e.target).closest(".o_layered_panel .popover").length > 0 - || jQuery(e.target).closest(".o_layered_panel .modal-dialog").length > 0; + || jQuery(e.target).closest(".o_layered_panel .modal-dialog").length > 0 + || e.target.nodeName == 'BODY'; if(!edited && !excludedEls) { o_XHREvent(componentUrl, false, false, 'cid', 'close_edit_fragment'); } diff --git a/src/test/java/org/olat/modules/adobeconnect/manager/AdobeConnectProviderTest.java b/src/test/java/org/olat/modules/adobeconnect/manager/AdobeConnectProviderTest.java index 1146fb3195d0430939782fc3ce9c5e7e3817138b..29eb13166745594c2d1fc268cd8e16c3c1327c6c 100644 --- a/src/test/java/org/olat/modules/adobeconnect/manager/AdobeConnectProviderTest.java +++ b/src/test/java/org/olat/modules/adobeconnect/manager/AdobeConnectProviderTest.java @@ -21,6 +21,7 @@ package org.olat.modules.adobeconnect.manager; import java.util.Calendar; import java.util.Date; +import java.util.TimeZone; import org.junit.Assert; import org.junit.Test; @@ -38,9 +39,10 @@ public class AdobeConnectProviderTest { String dateStr = "2019-04-18T12:28:28.587+02:00"; Date date = AbstractAdobeConnectProvider.parseIsoDate(dateStr); Assert.assertNotNull(date); - + Calendar cal = Calendar.getInstance(); cal.setTime(date); + cal.setTimeZone(TimeZone.getTimeZone("Europe/Zurich")); Assert.assertEquals(12, cal.get(Calendar.HOUR_OF_DAY)); }