Skip to content
Snippets Groups Projects
Commit 81eeb850 authored by srosse's avatar srosse
Browse files

Merge branch 'OpenOLAT_15.1' of...

Merge branch 'OpenOLAT_15.1' of ssh://srosse@office.frentix.com/home/srosse/repositories/OpenOLAT.git into OpenOLAT_15.1
parents 61e36168 a8855e7a
No related branches found
No related tags found
No related merge requests found
...@@ -150,6 +150,16 @@ public class ClusterLocker implements Locker, GenericEventListener { ...@@ -150,6 +150,16 @@ public class ClusterLocker implements Locker, GenericEventListener {
final String asset = OresHelper.createStringRepresenting(ores, locksubkey); final String asset = OresHelper.createStringRepresenting(ores, locksubkey);
return clusterLockManager.isLocked(asset); return clusterLockManager.isLocked(asset);
} }
@Override
public LockEntry getLockEntry(OLATResourceable ores, String locksubkey) {
final String asset = OresHelper.createStringRepresenting(ores, locksubkey);
LockImpl li = clusterLockManager.findLock(asset);
if(li == null) {
return null;
}
return new LockEntry(li.getAsset(), li.getCreationDate().getTime(), li.getOwner(), li.getWindowId());
}
@Override @Override
public Identity getLockedBy(OLATResourceable ores, String locksubkey) { public Identity getLockedBy(OLATResourceable ores, String locksubkey) {
......
...@@ -37,6 +37,7 @@ import org.olat.core.logging.AssertException; ...@@ -37,6 +37,7 @@ import org.olat.core.logging.AssertException;
import org.olat.core.util.Formatter; import org.olat.core.util.Formatter;
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.coordinate.LockEntry;
import org.olat.core.util.coordinate.LockResult; import org.olat.core.util.coordinate.LockResult;
import org.olat.user.UserManager; import org.olat.user.UserManager;
...@@ -117,10 +118,7 @@ public class DialogBoxUIFactory { ...@@ -117,10 +118,7 @@ public class DialogBoxUIFactory {
if(lockEntry.isSuccess()){ if(lockEntry.isSuccess()){
throw new AssertException("do not create a 'is locked message' if lock was succesfull! concerns lock:"+lockEntry.getOwner()); throw new AssertException("do not create a 'is locked message' if lock was succesfull! concerns lock:"+lockEntry.getOwner());
} }
String fullName = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(lockEntry.getOwner()); String lockMsg = getLockedMessage(ureq, lockEntry.getLockEntry(), i18nLockMsgKey, translator);
String[] i18nParams = new String[] { StringHelper.escapeHtml(fullName),
Formatter.getInstance(ureq.getLocale()).formatTime(new Date(lockEntry.getLockAquiredTime())) };
String lockMsg = translator.translate(i18nLockMsgKey, i18nParams);
Translator trans = Util.createPackageTranslator(DialogBoxUIFactory.class, ureq.getLocale()); Translator trans = Util.createPackageTranslator(DialogBoxUIFactory.class, ureq.getLocale());
List<String> okButton = new ArrayList<>(); List<String> okButton = new ArrayList<>();
...@@ -131,6 +129,13 @@ public class DialogBoxUIFactory { ...@@ -131,6 +129,13 @@ public class DialogBoxUIFactory {
return ctrl; return ctrl;
} }
public static String getLockedMessage(UserRequest ureq, LockEntry lockEntry, String i18nLockMsgKey, Translator translator) {
String fullName = CoreSpringFactory.getImpl(UserManager.class).getUserDisplayName(lockEntry.getOwner());
String[] i18nParams = new String[] { StringHelper.escapeHtml(fullName),
Formatter.getInstance(ureq.getLocale()).formatTime(new Date(lockEntry.getLockAquiredTime())) };
return translator.translate(i18nLockMsgKey, i18nParams);
}
/** /**
* checks if this event from a OkCancel Dialog is an OK event. * checks if this event from a OkCancel Dialog is an OK event.
......
...@@ -75,7 +75,14 @@ public interface Locker { ...@@ -75,7 +75,14 @@ public interface Locker {
* @return The identity which lock the resource or null. * @return The identity which lock the resource or null.
*/ */
public Identity getLockedBy(OLATResourceable ores, String locksubkey); public Identity getLockedBy(OLATResourceable ores, String locksubkey);
/**
*
* @param ores
* @param locksubkey
* @return
*/
public LockEntry getLockEntry(OLATResourceable ores, String locksubkey);
/** /**
* *
......
...@@ -22,6 +22,7 @@ package org.olat.course.assessment.ui.tool; ...@@ -22,6 +22,7 @@ package org.olat.course.assessment.ui.tool;
import java.util.List; import java.util.List;
import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.IdentityRef;
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;
import org.olat.core.gui.components.stack.TooledStackedPanel; import org.olat.core.gui.components.stack.TooledStackedPanel;
...@@ -30,7 +31,6 @@ import org.olat.core.gui.control.Controller; ...@@ -30,7 +31,6 @@ 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.gui.control.generic.modal.DialogBoxController;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory; import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.IdentityEnvironment;
...@@ -75,7 +75,6 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl ...@@ -75,7 +75,6 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl
private Controller identityInfosCtrl; private Controller identityInfosCtrl;
private Controller subDetailsController; private Controller subDetailsController;
private Controller detailsEditController; private Controller detailsEditController;
private DialogBoxController alreadyLockedDialogController;
private LockResult lockEntry; private LockResult lockEntry;
private final CourseNode courseNode; private final CourseNode courseNode;
...@@ -109,19 +108,18 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl ...@@ -109,19 +108,18 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl
identityAssessmentVC = createVelocityContainer("identity_personal_node_infos"); identityAssessmentVC = createVelocityContainer("identity_personal_node_infos");
initDetails(); initDetails();
identityInfosCtrl = new AssessedIdentityLargeInfosController(ureq, wControl, assessedIdentity, course);
listenTo(identityInfosCtrl);
identityAssessmentVC.put("identityInfos", identityInfosCtrl.getInitialComponent());
//acquire lock and show dialog box on failure. //acquire lock and show dialog box on failure.
String lockSubKey = "AssessmentLock-NID::" + courseNode.getIdent() + "-IID::" + assessedIdentity.getKey(); String lockSubKey = lockKey(courseNode, assessedIdentity);
lockEntry = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(course, ureq.getIdentity(), lockSubKey, getWindow()); lockEntry = CoordinatorManager.getInstance().getCoordinator().getLocker().acquireLock(course, ureq.getIdentity(), lockSubKey, getWindow());
if(!lockEntry.isSuccess()) { if(!lockEntry.isSuccess()) {
alreadyLockedDialogController = DialogBoxUIFactory.createResourceLockedMessage(ureq, wControl, lockEntry, "assessmentLock", getTranslator()); String msg = DialogBoxUIFactory.getLockedMessage(ureq, lockEntry.getLockEntry(), "assessmentLock", getTranslator());
listenTo(alreadyLockedDialogController); getWindowControl().setWarning(msg);
alreadyLockedDialogController.activate();
} else { } else {
identityInfosCtrl = new AssessedIdentityLargeInfosController(ureq, wControl, assessedIdentity, course);
listenTo(identityInfosCtrl);
identityAssessmentVC.put("identityInfos", identityInfosCtrl.getInitialComponent());
// Add the users details controller // Add the users details controller
AssessmentConfig assessmentConfig = courseAssessmentService.getAssessmentConfig(courseNode); AssessmentConfig assessmentConfig = courseAssessmentService.getAssessmentConfig(courseNode);
if (assessmentConfig.hasEditableDetails() && courseNodeDetails) { if (assessmentConfig.hasEditableDetails() && courseNodeDetails) {
...@@ -143,6 +141,10 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl ...@@ -143,6 +141,10 @@ public class AssessmentIdentityCourseNodeController extends BasicController impl
putInitialPanel(identityAssessmentVC); putInitialPanel(identityAssessmentVC);
} }
public static String lockKey(CourseNode node, IdentityRef identity) {
return "AssessmentLock-NID::" + node.getIdent() + "-IID::" + identity.getKey();
}
public UserCourseEnvironment getCoachCourseEnvironment() { public UserCourseEnvironment getCoachCourseEnvironment() {
return coachCourseEnv; return coachCourseEnv;
} }
......
...@@ -60,6 +60,7 @@ import org.olat.core.gui.control.WindowControl; ...@@ -60,6 +60,7 @@ import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController; import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
import org.olat.core.gui.control.generic.dtabs.Activateable2; import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.id.IdentityEnvironment; import org.olat.core.id.IdentityEnvironment;
import org.olat.core.id.OLATResourceable; import org.olat.core.id.OLATResourceable;
...@@ -69,6 +70,7 @@ import org.olat.core.id.context.StateEntry; ...@@ -69,6 +70,7 @@ import org.olat.core.id.context.StateEntry;
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.coordinate.CoordinatorManager; import org.olat.core.util.coordinate.CoordinatorManager;
import org.olat.core.util.coordinate.LockEntry;
import org.olat.core.util.event.GenericEventListener; import org.olat.core.util.event.GenericEventListener;
import org.olat.core.util.mail.ContactList; import org.olat.core.util.mail.ContactList;
import org.olat.core.util.mail.ContactMessage; import org.olat.core.util.mail.ContactMessage;
...@@ -826,12 +828,42 @@ public class IdentityListCourseNodeController extends FormBasicController ...@@ -826,12 +828,42 @@ public class IdentityListCourseNodeController extends FormBasicController
private void doSelect(UserRequest ureq, Identity assessedIdentity) { private void doSelect(UserRequest ureq, Identity assessedIdentity) {
List<AssessedIdentityElementRow> rows = usersTableModel.getObjects(); List<AssessedIdentityElementRow> rows = usersTableModel.getObjects();
AssessedIdentityElementRow selectedRow = null;
for(AssessedIdentityElementRow row:rows) { for(AssessedIdentityElementRow row:rows) {
if(assessedIdentity.getKey().equals(row.getIdentityKey())) { if(assessedIdentity.getKey().equals(row.getIdentityKey())) {
doSelect(ureq, row); selectedRow = row;
break; break;
} }
} }
if(selectedRow != null && !isAssessedIdentityLocked(ureq, assessedIdentity)) {
doSelect(ureq, selectedRow);
}
}
/**
* Preventive check if the identity is already locked by an other
* user and show a warning message if needed.
*
* @param ureq The user request
* @param assessedIdentity The identity to assess
* @return
*/
private boolean isAssessedIdentityLocked(UserRequest ureq, Identity assessedIdentity) {
if(courseNode.getParent() == null) return false;
ICourse course = CourseFactory.loadCourse(courseEntry);
String locksubkey = AssessmentIdentityCourseNodeController.lockKey(courseNode, assessedIdentity);
if(CoordinatorManager.getInstance().getCoordinator().getLocker().isLocked(course, locksubkey)) {
LockEntry lock = CoordinatorManager.getInstance().getCoordinator().getLocker().getLockEntry(course, locksubkey);
if(lock != null && lock.getOwner() != null && !lock.getOwner().equals(getIdentity())) {
String msg = DialogBoxUIFactory.getLockedMessage(ureq, lock, "assessmentLock", getTranslator());
getWindowControl().setWarning(msg);
return true;
}
}
return false;
} }
private Controller doSelect(UserRequest ureq, AssessedIdentityElementRow row) { private Controller doSelect(UserRequest ureq, AssessedIdentityElementRow row) {
......
...@@ -126,8 +126,8 @@ public abstract class AbstractToolsController extends BasicController { ...@@ -126,8 +126,8 @@ public abstract class AbstractToolsController extends BasicController {
} }
lastLink = link; lastLink = link;
} }
if(links.size() > 0 && "-".equals(links.get(links.size() - 1))) { if(!links.isEmpty() && "-".equals(links.get(links.size() - 1))) {
links.remove(links.size() -1);//no trialing separator links.remove(links.size() -1);//no trailing separator
} }
mainVC.contextPut("links", links); mainVC.contextPut("links", links);
......
...@@ -540,12 +540,16 @@ public class OpenMeetingsManagerImpl implements OpenMeetingsManager, UserDataDel ...@@ -540,12 +540,16 @@ public class OpenMeetingsManagerImpl implements OpenMeetingsManager, UserDataDel
@Override @Override
public boolean deleteRoom(OpenMeetingsRoom room) { public boolean deleteRoom(OpenMeetingsRoom room) {
return deleteRoom(room, false);
}
private boolean deleteRoom(OpenMeetingsRoom room, boolean force) {
try { try {
String adminSID = adminLogin(); String adminSID = adminLogin();
RoomServicePortType roomWs = getRoomWebService(); RoomServicePortType roomWs = getRoomWebService();
long ret = roomWs.deleteRoom(adminSID, room.getRoomId()); long ret = roomWs.deleteRoom(adminSID, room.getRoomId());
boolean ok = ret > 0; boolean ok = ret > 0;
if(ok && room.getReference() != null) { if((ok || force) && room.getReference() != null) {
openMeetingsDao.delete(room.getReference()); openMeetingsDao.delete(room.getReference());
} }
return ok; return ok;
...@@ -715,7 +719,7 @@ public class OpenMeetingsManagerImpl implements OpenMeetingsManager, UserDataDel ...@@ -715,7 +719,7 @@ public class OpenMeetingsManagerImpl implements OpenMeetingsManager, UserDataDel
boolean allOk = true; boolean allOk = true;
OpenMeetingsRoom room = getLocalRoom(group, null, null); OpenMeetingsRoom room = getLocalRoom(group, null, null);
if(room != null) { if(room != null) {
allOk &= deleteRoom(room); allOk &= deleteRoom(room, true);
} }
return allOk; return allOk;
} }
......
...@@ -38,13 +38,13 @@ cmi.student_preference.speed=Geschwindigkeit ...@@ -38,13 +38,13 @@ cmi.student_preference.speed=Geschwindigkeit
cmi.student_preference.text=Texteinstellung cmi.student_preference.text=Texteinstellung
cmi.suspend_data=Zustandsdaten bei Unterbrechung cmi.suspend_data=Zustandsdaten bei Unterbrechung
cmis.column.header.itemId=Bausteine cmis.column.header.itemId=Bausteine
cmis.column.header.key=Schl\u00FCssel cmis.column.header.key=Schl\u00fcssel
cmis.column.header.translatedKey=Frage cmis.column.header.translatedKey=Frage
cmis.column.header.value=Wert cmis.column.header.value=Wert
summary.column.header.assesspoints=Punkte summary.column.header.assesspoints=Punkte
summary.column.header.date=Datum summary.column.header.date=Datum
summary.column.header.details=Details summary.column.header.details=Details
summary.column.header.duration=Dauer summary.column.header.duration=Dauer
reset=SCORM Resultaten zur\u00FCcksetzen reset=SCORM Resultate zur\u00fccksetzen
reset.title=SCORM Resultate zur\u00FCcksetzen reset.title=SCORM Resultate zur\u00fccksetzen
reset.text=Wollen Sie die SCORM Resultate von <b>{0}</b> wirklich zur\u00FCcksetzen? Dies beinhaltet alle Bewegungsdaten dieses SCORM Moduls inklusive allf\u00e4lliger Testdaten. Als abgeschlossen markierte SCORM Module k\u00f6nnen so erneut aufgerufen und durchgef\u00fchrt werden. Die beim letzten Versuch \u00fcbertragenen Punkte werden nicht ver\u00e4ndert. reset.text=Wollen Sie die SCORM Resultate von <b>{0}</b> wirklich zur\u00fccksetzen? Dies beinhaltet alle Bewegungsdaten dieses SCORM Moduls inklusive allf\u00e4lliger Testdaten. Als abgeschlossen markierte SCORM Module k\u00f6nnen so erneut aufgerufen und durchgef\u00fchrt werden. Die beim letzten Versuch \u00fcbertragenen Punkte werden nicht ver\u00e4ndert.
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