From 52c19184665d21f201c5d545a36ef110bc4c3457 Mon Sep 17 00:00:00 2001 From: srosse <stephane.rosse@frentix.com> Date: Thu, 2 Jul 2020 15:36:34 +0200 Subject: [PATCH] OO-2036: handle assessment mode across several browser windows --- .../fullWebApp/BaseFullWebappController.java | 19 ++++++- .../commons/fullWebApp/LockResourceInfos.java | 55 +++++++++++++++++++ src/main/java/org/olat/core/gui/Windows.java | 19 +++++++ .../core/gui/control/ChiefController.java | 16 +++++- .../gui/control/DefaultChiefController.java | 10 +++- ...AssessmentModeCoordinationServiceImpl.java | 3 + .../interpreter/IsAssessmentModeFunction.java | 4 +- .../dispatcher/AuthenticatedDispatcher.java | 11 +++- 8 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/olat/core/commons/fullWebApp/LockResourceInfos.java diff --git a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java index 6586034fe17..e2bc2bd0465 100644 --- a/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java +++ b/src/main/java/org/olat/core/commons/fullWebApp/BaseFullWebappController.java @@ -1433,6 +1433,9 @@ public class BaseFullWebappController extends BasicController implements DTabs, return; } + String instanceId = getWindow().getInstanceId(); + System.out.println(instanceId + " " + event.getCommand()); + String cmd = event.getCommand(); switch(cmd) { case AssessmentModeNotificationEvent.STOP_WARNING: @@ -1478,8 +1481,9 @@ public class BaseFullWebappController extends BasicController implements DTabs, } @Override - public OLATResourceable getLockResource() { - return lockResource; + public LockResourceInfos getLockResourceInfos() { + if(lockResource == null) return null; + return new LockResourceInfos(lockStatus, lockResource, lockMode); } @Override @@ -1488,6 +1492,15 @@ public class BaseFullWebappController extends BasicController implements DTabs, lockGUI(); } + public void hardLockResource(LockResourceInfos lockInfos) { + if(lockInfos == null) return; + + lockResource = lockInfos.getLockResource(); + lockMode = lockInfos.getLockMode(); + lockStatus = lockInfos.getLockStatus(); + lockGUI(); + } + private void lockGUI() { if(topnavCtr != null) { topnavCtr.lock(); @@ -1758,7 +1771,7 @@ public class BaseFullWebappController extends BasicController implements DTabs, } } - private enum LockStatus { + protected enum LockStatus { need, popup, locked diff --git a/src/main/java/org/olat/core/commons/fullWebApp/LockResourceInfos.java b/src/main/java/org/olat/core/commons/fullWebApp/LockResourceInfos.java new file mode 100644 index 00000000000..a549e30134b --- /dev/null +++ b/src/main/java/org/olat/core/commons/fullWebApp/LockResourceInfos.java @@ -0,0 +1,55 @@ +/** + * <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.core.commons.fullWebApp; + +import org.olat.core.commons.fullWebApp.BaseFullWebappController.LockStatus; +import org.olat.core.id.OLATResourceable; +import org.olat.course.assessment.model.TransientAssessmentMode; + +/** + * + * Initial date: 2 juil. 2020<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public class LockResourceInfos { + + private final LockStatus lockStatus; + private final OLATResourceable lockResource; + private final TransientAssessmentMode lockMode; + + public LockResourceInfos(LockStatus lockStatus, OLATResourceable lockResource, TransientAssessmentMode lockMode) { + this.lockStatus = lockStatus; + this.lockResource = lockResource; + this.lockMode = lockMode; + } + + public LockStatus getLockStatus() { + return lockStatus; + } + + public OLATResourceable getLockResource() { + return lockResource; + } + + public TransientAssessmentMode getLockMode() { + return lockMode; + } +} diff --git a/src/main/java/org/olat/core/gui/Windows.java b/src/main/java/org/olat/core/gui/Windows.java index dbba15692d8..c6acb1e4168 100644 --- a/src/main/java/org/olat/core/gui/Windows.java +++ b/src/main/java/org/olat/core/gui/Windows.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; +import org.olat.core.commons.fullWebApp.LockResourceInfos; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.ComponentHelper; import org.olat.core.gui.components.Window; @@ -271,6 +272,24 @@ public class Windows implements Disposable, Serializable { } return ws.iterator(); } + + /** + * Search all the windows to find the first locked chief controller + * and returns informations about the locked resource. + * + * @return Informations about the current locked resource, or null if the + * user has not a chief controller locked. + */ + public LockResourceInfos getLockResourceInfos() { + List<ChiefController> chiefControllers = windows.values(); + for(ChiefController chiefController:chiefControllers) { + LockResourceInfos lockInfos = chiefController.getLockResourceInfos(); + if(lockInfos != null) { + return lockInfos; + } + } + return null; + } /** * @return the number of windows diff --git a/src/main/java/org/olat/core/gui/control/ChiefController.java b/src/main/java/org/olat/core/gui/control/ChiefController.java index 7fbef0b54f3..7dabfb3d2f2 100644 --- a/src/main/java/org/olat/core/gui/control/ChiefController.java +++ b/src/main/java/org/olat/core/gui/control/ChiefController.java @@ -26,6 +26,7 @@ package org.olat.core.gui.control; +import org.olat.core.commons.fullWebApp.LockResourceInfos; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Window; import org.olat.core.gui.components.htmlheader.jscss.CustomCSS; @@ -74,12 +75,23 @@ public interface ChiefController extends Controller { public void resetReload(); /** + * Lock softly the chief after interaction with the user. * - * @param resource + * @param resource The resource to lock */ public void lockResource(OLATResourceable resource); - public OLATResourceable getLockResource(); + /** + * Hard locking the chief controller after a copy/paste URL or + * such a thing. If the informations are null, the call is ignored. + * + * @param lockInfos The lock informations + */ + public void hardLockResource(LockResourceInfos lockInfos); + + public LockResourceInfos getLockResourceInfos(); + + /** * Set a class to the <body> diff --git a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java index 410348ae1be..668823e50e4 100644 --- a/src/main/java/org/olat/core/gui/control/DefaultChiefController.java +++ b/src/main/java/org/olat/core/gui/control/DefaultChiefController.java @@ -26,6 +26,7 @@ package org.olat.core.gui.control; +import org.olat.core.commons.fullWebApp.LockResourceInfos; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; import org.olat.core.gui.components.Window; @@ -86,12 +87,17 @@ public abstract class DefaultChiefController extends DefaultController implement } @Override - public OLATResourceable getLockResource() { + public final LockResourceInfos getLockResourceInfos() { return null; } @Override - public void lockResource(OLATResourceable resource) { + public final void lockResource(OLATResourceable resource) { + // + } + + @Override + public final void hardLockResource(LockResourceInfos lockInfos) { // } 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 ea5c8491c06..a7e1577b7ab 100644 --- a/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java +++ b/src/main/java/org/olat/course/assessment/manager/AssessmentModeCoordinationServiceImpl.java @@ -274,6 +274,9 @@ public class AssessmentModeCoordinationServiceImpl implements AssessmentModeCoor sendEvent(AssessmentModeNotificationEvent.END, mode, assessmentModeManager.getAssessedIdentityKeys(mode)); } + } else if(mode.getStatus() == Status.assessment) { + sendEvent(AssessmentModeNotificationEvent.START_ASSESSMENT, mode, + assessmentModeManager.getAssessedIdentityKeys(mode)); } } else { if(mode.getBegin().compareTo(now) <= 0 && mode.getEnd().compareTo(now) > 0) { diff --git a/src/main/java/org/olat/course/condition/interpreter/IsAssessmentModeFunction.java b/src/main/java/org/olat/course/condition/interpreter/IsAssessmentModeFunction.java index 725078dad38..eb8b87df327 100644 --- a/src/main/java/org/olat/course/condition/interpreter/IsAssessmentModeFunction.java +++ b/src/main/java/org/olat/course/condition/interpreter/IsAssessmentModeFunction.java @@ -24,6 +24,7 @@ import java.util.Date; import java.util.List; import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.fullWebApp.LockResourceInfos; import org.olat.core.gui.control.ChiefController; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.OLATResourceable; @@ -83,7 +84,8 @@ public class IsAssessmentModeFunction extends AbstractFunction { if(chiefController == null) { return ConditionInterpreter.INT_FALSE; } - OLATResourceable lockedResource = chiefController.getLockResource(); + LockResourceInfos lockInfos = chiefController.getLockResourceInfos(); + OLATResourceable lockedResource = lockInfos == null ? null : lockInfos.getLockResource(); boolean open = false; if(inStack != null && inStack.length == 2) { diff --git a/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java b/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java index f90778dfd0b..c59c1c0e1d5 100644 --- a/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java +++ b/src/main/java/org/olat/dispatcher/AuthenticatedDispatcher.java @@ -38,7 +38,9 @@ import org.apache.logging.log4j.Logger; import org.olat.NewControllerFactory; import org.olat.basesecurity.AuthHelper; import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.fullWebApp.BaseFullWebappController; import org.olat.core.commons.fullWebApp.LayoutMain3ColsController; +import org.olat.core.commons.fullWebApp.LockResourceInfos; import org.olat.core.dispatcher.Dispatcher; import org.olat.core.dispatcher.DispatcherModule; import org.olat.core.gui.UserRequest; @@ -313,8 +315,9 @@ public class AuthenticatedDispatcher implements Dispatcher { } return; } - - ChiefController chiefController = Windows.getWindows(usess).getChiefController(ureq); + + Windows windows = Windows.getWindows(usess); + ChiefController chiefController = windows.getChiefController(ureq); if(chiefController == null && !usess.isAuthenticated()) { redirectToDefaultDispatcher(ureq.getHttpReq(), ureq.getHttpResp()); return; @@ -342,6 +345,10 @@ public class AuthenticatedDispatcher implements Dispatcher { chiefController = (ChiefController)pbw; } else { chiefController = AuthHelper.createAuthHome(ureq); + LockResourceInfos lockInfos = windows.getLockResourceInfos(); + if(lockInfos != null) { + ((BaseFullWebappController)chiefController).hardLockResource(lockInfos); + } } Window window = chiefController.getWindow(); window.setUriPrefix(ureq.getUriPrefix()); -- GitLab