diff --git a/.hgtags b/.hgtags
index f9d3c165af3a98b81bd66331d74a9d4c7950a5d3..6a0e5499a704648d92be32c78177e04356d99982 100644
--- a/.hgtags
+++ b/.hgtags
@@ -134,3 +134,4 @@ bc8ce641a5620f5717e9a73e31028d41ab7cdc5d OpenOLAT 10.4.4
 d355c6357d0e5aeb25fc978b747824447a214b88 OpenOLAT 10.4.5
 fef7f6b2e2628d242e93f86d208f4cfb9c807d7c OpenOLAT 10.4.6
 b38ed621ea53507fbf41eb616648ebad2340e613 OpenOLAT 10.4.7
+273a6270a08460c07fdfbb53e31547b9c7e1c8c9 OpenOLAT 10.4.8
diff --git a/src/main/java/org/olat/commons/calendar/ICalServlet.java b/src/main/java/org/olat/commons/calendar/ICalServlet.java
index bde343b33759982fd8ba9831737a775418e879bb..8bd448aa93306dc0d2cd920a9b5a29e14ea5c9d3 100644
--- a/src/main/java/org/olat/commons/calendar/ICalServlet.java
+++ b/src/main/java/org/olat/commons/calendar/ICalServlet.java
@@ -141,7 +141,14 @@ public class ICalServlet extends HttpServlet {
 	private void getIcalDocument(String requestUrl, HttpServletResponse response)
 	throws ValidationException, IOException {
 		// get the individual path tokens
-		String pathInfo = requestUrl.replaceAll(".ics", "");
+		String pathInfo;
+		int icsIndex = requestUrl.indexOf(".ics");
+		if(icsIndex > 0) {
+			pathInfo = requestUrl.substring(0, icsIndex);
+		} else {
+			pathInfo = requestUrl;
+		}
+		
 		String[] pathInfoTokens = pathInfo.split("/");
 		if(pathInfoTokens.length < 4) {
 			response.sendError(HttpServletResponse.SC_BAD_REQUEST, requestUrl);
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
index 84dc0fcb2b3126980f0834de835c3b8c9bdbee03..d3a57dcf03009d69f05f5abed55eb9d7a9b2af92 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_de.properties
@@ -10,4 +10,4 @@ webdav.on=ein
 webdav.termsfolders=Kurse nach Semesterdaten gruppieren
 webdav.for.learners.participants=Zugriff für Studenten / Betreuer Kursen
 webdav.for.learners.bookmarks=Zugriff für Studenten / Betreuer Favoriten
-webdav.prepend.reference=Kursreferenz zu Titel voranstellen
\ No newline at end of file
+webdav.prepend.reference=Kennzeichen zu Titel voranstellen
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
index 9312c822f53a360c1086398fd475cf8a428c6e58..75ddad6c1c908002c56912dd6e8a608d562f6b9a 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_en.properties
@@ -10,4 +10,4 @@ webdav.on=enabled
 webdav.termsfolders=Group courses by semester terms
 webdav.for.learners.participants=Enable access for courses where user is participant or coach
 webdav.for.learners.bookmarks=Enable for courses that users marked as favorite
-webdav.prepend.reference=Prepend course reference to title
\ No newline at end of file
+webdav.prepend.reference=Prepend external course reference to title
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_fr.properties
index 4766cd4d51b7ea1da3b903886e09e78acfafe955..121d00a7deade1acf34d6e2897a0c6419d9cb329 100644
--- a/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/core/commons/services/webdav/ui/_i18n/LocalStrings_fr.properties
@@ -9,5 +9,5 @@ webdav.for.learners.participants=Acc\u00E8s aux cours pour les \u00E9tudiants et
 webdav.link=Montre les liens WebDAV
 webdav.module=Acc\u00E8s WebDAV
 webdav.on=on
-webdav.prepend.reference=Ajouter la r\u00E9f\u00E9rence au nom du cours
+webdav.prepend.reference=Ajouter la r\u00E9f\u00E9rence externe au nom du cours
 webdav.termsfolders=Grouper les cours par semestre
diff --git a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
index 9173659a3d656503ad3f9d17e873e534a4986c07..062e2f20d4c0aa933380d0f86771c4e1cb24f0be 100644
--- a/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
+++ b/src/main/java/org/olat/course/CoursefolderWebDAVMergeSource.java
@@ -112,8 +112,8 @@ class CoursefolderWebDAVMergeSource extends WebDAVMergeSource {
 			duplicates.add(re);
 			
 			String displayName = re.getDisplayname();
-			if(prependReference && StringHelper.containsNonWhitespace(re.getExternalId())) {
-				displayName = re.getExternalId() + " " + displayName;
+			if(prependReference && StringHelper.containsNonWhitespace(re.getExternalRef())) {
+				displayName = re.getExternalRef() + " " + displayName;
 			}
 			String courseTitle = RequestUtil.normalizeFilename(displayName);
 			NamedContainerImpl cfContainer = new CoursefolderWebDAVNamedContainer(courseTitle, re, editor ? null : identityEnv);
diff --git a/src/main/java/org/olat/course/nodes/ENCourseNode.java b/src/main/java/org/olat/course/nodes/ENCourseNode.java
index f91d50c08c29d62ca2d434da0541a8367158b1a6..c41f9c5fb4e0145fd00a47caf433b58f5962d714 100644
--- a/src/main/java/org/olat/course/nodes/ENCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ENCourseNode.java
@@ -27,8 +27,11 @@ package org.olat.course.nodes;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
+import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.control.Controller;
@@ -53,6 +56,10 @@ import org.olat.course.properties.PersistingCoursePropertyManager;
 import org.olat.course.run.navigation.NodeRunConstructionResult;
 import org.olat.course.run.userview.NodeEvaluation;
 import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.group.BusinessGroupService;
+import org.olat.group.BusinessGroupShort;
+import org.olat.group.area.BGArea;
+import org.olat.group.area.BGAreaManager;
 import org.olat.modules.ModuleConfiguration;
 import org.olat.repository.RepositoryEntry;
 
@@ -66,6 +73,7 @@ import org.olat.repository.RepositoryEntry;
  */
 public class ENCourseNode extends AbstractAccessableCourseNode {
 	private static final String PACKAGE = Util.getPackageName(ENCourseNode.class);
+	private static final String PACKAGE_COND = Util.getPackageName(ConditionEditController.class);
 
 	/**
 	 * property name for the initial enrollment date will be set only the first
@@ -186,44 +194,28 @@ public class ENCourseNode extends AbstractAccessableCourseNode {
 		oneClickStatusCache = null;
 		// only here we know which translator to take for translating condition
 		// error messages
-		String translatorStr = Util.getPackageName(ConditionEditController.class);
 
-		List<StatusDescription> condErrs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		List<StatusDescription> condErrs = isConfigValidWithTranslator(cev, PACKAGE_COND, getConditionExpressions());
 		List<StatusDescription> missingNames = new ArrayList<StatusDescription>();
 		/*
 		 * check group and area names for existence
 		 */
-		String nodeId = getIdent();
 		
 		ModuleConfiguration mc = getModuleConfiguration();
-		String areaStr = (String) mc.get(CONFIG_AREANAME);
-		if (areaStr != null) {
-			String[] areas = areaStr.split(",");
-			for (int i = 0; i < areas.length; i++) {
-				String trimmed = areas[i] != null ?
-						FilterFactory.getHtmlTagsFilter().filter(areas[i]).trim() : areas[i];
-				if (!trimmed.equals("") && !cev.existsArea(trimmed)) {
-					StatusDescription sd = new StatusDescription(StatusDescription.WARNING, "error.notfound.name", "solution.checkgroupmanagement",
-							new String[] { "NONE", trimmed }, translatorStr);
-					sd.setDescriptionForUnit(nodeId);
-					missingNames.add(sd);
-				}
-			}
+		String areaNames = (String) mc.get(CONFIG_AREANAME);
+		List<Long> areaKeys = mc.getList(ENCourseNode.CONFIG_AREA_IDS, Long.class);
+		List<String> missingAreas = getMissingAreas(areaKeys, areaNames, cev);
+		if(missingAreas.size() > 0) {
+			missingNames.add(addStatusErrorMissing(missingAreas));
 		}
-		String groupStr = (String) mc.get(CONFIG_GROUPNAME);
-		if (groupStr != null) {
-			String[] groups = groupStr.split(",");
-			for (int i = 0; i < groups.length; i++) {
-				String trimmed = groups[i] != null ?
-						FilterFactory.getHtmlTagsFilter().filter(groups[i]).trim() : groups[i];
-				if (!trimmed.equals("") && !cev.existsGroup(trimmed)) {
-					StatusDescription sd = new StatusDescription(StatusDescription.WARNING, "error.notfound.name", "solution.checkgroupmanagement",
-							new String[] { "NONE", trimmed }, translatorStr);
-					sd.setDescriptionForUnit(nodeId);
-					missingNames.add(sd);
-				}
-			}
+		
+		String groupNames = (String) mc.get(CONFIG_GROUPNAME);
+		List<Long> groupKeys = mc.getList(ENCourseNode.CONFIG_GROUP_IDS, Long.class);
+		List<String> missingGroups = getMissingBusinessGroups(groupKeys, groupNames, cev);
+		if(missingGroups.size() > 0) {
+			missingNames.add(addStatusErrorMissing(missingGroups));
 		}
+		
 		missingNames.addAll(condErrs);
 		/*
 		 * sort -> Errors > Warnings > Infos and remove NOERRORS, if
@@ -232,6 +224,122 @@ public class ENCourseNode extends AbstractAccessableCourseNode {
 		oneClickStatusCache = StatusDescriptionHelper.sort(missingNames);
 		return oneClickStatusCache;
 	}
+	
+	private StatusDescription addStatusErrorMissing(List<String> missingObjects) {
+		String labelKey = missingObjects.size() == 1 ? "error.notfound.name" : "error.notfound.names";
+		StringBuilder missing = new StringBuilder();
+		for(String missingObject:missingObjects) {
+			if(missing.length() > 0) missing.append(", ");
+			missing.append(missingObject);
+		}
+		
+		StatusDescription sd = new StatusDescription(StatusDescription.WARNING, labelKey, "solution.checkgroupmanagement",
+				new String[] { "NONE", missing.toString() }, PACKAGE_COND);
+		sd.setDescriptionForUnit(getIdent());
+		return sd;
+	}
+	
+	public List<String> getMissingAreas(List<Long> areaKeys, String areaNames, CourseEditorEnv cev) {
+		List<String> missingNames = new ArrayList<>();
+		if(areaKeys == null || areaKeys.isEmpty()) {
+			if (areaNames != null) {
+				String[] areas = areaNames.split(",");
+				for (int i = 0; i < areas.length; i++) {
+					String trimmed = areas[i] != null ?
+							FilterFactory.getHtmlTagsFilter().filter(areas[i]).trim() : areas[i];
+					if (!trimmed.equals("") && !cev.existsGroup(trimmed)) {
+						missingNames.add(trimmed);
+					}
+				}
+			}
+		} else {
+			Set<Long> missingAreas = new HashSet<Long>();
+			List<BGArea> existingAreas =  CoreSpringFactory.getImpl(BGAreaManager.class).loadAreas(areaKeys);
+			
+			List<String> knowNames = new ArrayList<>();
+			if (areaNames != null) {
+				String[] areas = areaNames.split(",");
+				for (int i = 0; i < areas.length; i++) {
+					String trimmed = areas[i] != null ? FilterFactory.getHtmlTagsFilter().filter(areas[i]).trim() : areas[i];
+					knowNames.add(trimmed);
+				}
+			}
+			
+			a_a:
+			for(Long areaKey:areaKeys) {
+				for(BGArea area:existingAreas) {
+					if(area.getKey().equals(areaKey)) {
+						String trimmed = area.getName() != null ? FilterFactory.getHtmlTagsFilter().filter(area.getName()).trim() : area.getName();
+						knowNames.remove(trimmed);
+						continue a_a;
+					}
+				}
+				missingAreas.add(areaKey);
+			}
+			
+			if(missingAreas.size() > 0 ) {
+				if(knowNames.size() > 0) {
+					missingNames.addAll(knowNames);
+				} else {
+					for(Long missingArea:missingAreas) {
+						missingNames.add(missingArea.toString());
+					}
+				}
+			}
+		}
+		return missingNames;
+	}
+	
+	public List<String> getMissingBusinessGroups(List<Long> groupKeys, String groupNames, CourseEditorEnv cev) {
+		List<String> missingNames = new ArrayList<>();
+		if(groupKeys == null || groupKeys.isEmpty()) {
+			if (groupNames != null) {
+				String[] groups = groupNames.split(",");
+				for (int i = 0; i < groups.length; i++) {
+					String trimmed = groups[i] != null ?
+							FilterFactory.getHtmlTagsFilter().filter(groups[i]).trim() : groups[i];
+					if (!trimmed.equals("") && !cev.existsGroup(trimmed)) {
+						missingNames.add(trimmed);
+					}
+				}
+			}
+		} else {
+			Set<Long> missingGroups = new HashSet<Long>();
+			List<BusinessGroupShort> existingGroups =  CoreSpringFactory.getImpl(BusinessGroupService.class).loadShortBusinessGroups(groupKeys);
+			
+			List<String> knowNames = new ArrayList<>();
+			if (groupNames != null) {
+				String[] groups = groupNames.split(",");
+				for (int i = 0; i < groups.length; i++) {
+					String trimmed = groups[i] != null ? FilterFactory.getHtmlTagsFilter().filter(groups[i]).trim() : groups[i];
+					knowNames.add(trimmed);
+				}
+			}
+			
+			a_a:
+			for(Long groupKey:groupKeys) {
+				for(BusinessGroupShort group:existingGroups) {
+					if(group.getKey().equals(groupKey)) {
+						String trimmed = group.getName() != null ? FilterFactory.getHtmlTagsFilter().filter(group.getName()).trim() : group.getName();
+						knowNames.remove(trimmed);
+						continue a_a;
+					}
+				}
+				missingGroups.add(groupKey);
+			}
+			
+			if(missingGroups.size() > 0 ) {
+				if(knowNames.size() > 0) {
+					missingNames.addAll(knowNames);
+				} else {
+					for(Long missingGroup:missingGroups) {
+						missingNames.add(missingGroup.toString());
+					}
+				}
+			}
+		}
+		return missingNames;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.CourseNode#getReferencedRepositoryEntry()
diff --git a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
index 6ae0b81f38f83ed23be05f89256b74ec0aee71f2..4d2478e4edf7560589204edac014c99f96c12277 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractMemberListController.java
@@ -450,29 +450,33 @@ public abstract class AbstractMemberListController extends FormBasicController i
 	}
 	
 	protected void confirmDelete(UserRequest ureq, List<MemberView> members) {
-		int numOfOwners =
-				repoEntry == null ? businessGroupService.countMembers(businessGroup, GroupRoles.coach.name())
-				: repositoryService.countMembers(repoEntry, GroupRoles.owner.name());
-		
-		int numOfRemovedOwner = 0;
-		List<Long> identityKeys = new ArrayList<Long>();
-		for(MemberView member:members) {
-			identityKeys.add(member.getIdentityKey());
-			if(member.getMembership().isOwner()) {
-				numOfRemovedOwner++;
-			}
-		}
-		if(numOfRemovedOwner == 0 || numOfOwners - numOfRemovedOwner > 0) {
-			List<Identity> ids = securityManager.loadIdentityByKeys(identityKeys);
-			leaveDialogBox = new MemberLeaveConfirmationController(ureq, getWindowControl(), ids);
-			listenTo(leaveDialogBox);
-			
-			cmc = new CloseableModalController(getWindowControl(), translate("close"), leaveDialogBox.getInitialComponent(),
-					true, translate("edit.member"));
-			cmc.activate();
-			listenTo(cmc);
+		if(members.isEmpty()) {
+			showWarning("error.select.one.user");
 		} else {
-			showWarning("error.atleastone");
+			int numOfOwners =
+					repoEntry == null ? businessGroupService.countMembers(businessGroup, GroupRoles.coach.name())
+					: repositoryService.countMembers(repoEntry, GroupRoles.owner.name());
+			
+			int numOfRemovedOwner = 0;
+			List<Long> identityKeys = new ArrayList<Long>();
+			for(MemberView member:members) {
+				identityKeys.add(member.getIdentityKey());
+				if(member.getMembership().isOwner()) {
+					numOfRemovedOwner++;
+				}
+			}
+			if(numOfRemovedOwner == 0 || numOfOwners - numOfRemovedOwner > 0) {
+				List<Identity> ids = securityManager.loadIdentityByKeys(identityKeys);
+				leaveDialogBox = new MemberLeaveConfirmationController(ureq, getWindowControl(), ids);
+				listenTo(leaveDialogBox);
+				
+				cmc = new CloseableModalController(getWindowControl(), translate("close"), leaveDialogBox.getInitialComponent(),
+						true, translate("edit.member"));
+				cmc.activate();
+				listenTo(cmc);
+			} else {
+				showWarning("error.atleastone");
+			}
 		}
 	}
 	
@@ -489,14 +493,18 @@ public abstract class AbstractMemberListController extends FormBasicController i
 	}
 	
 	protected void openEdit(UserRequest ureq, List<MemberView> members) {
-		List<Long> identityKeys = getMemberKeys(members);
-		List<Identity> identities = securityManager.loadIdentityByKeys(identityKeys);
-		editMembersCtrl = new EditMembershipController(ureq, getWindowControl(), identities, repoEntry, businessGroup);
-		listenTo(editMembersCtrl);
-		cmc = new CloseableModalController(getWindowControl(), translate("close"), editMembersCtrl.getInitialComponent(),
-				true, translate("edit.member"));
-		cmc.activate();
-		listenTo(cmc);
+		if(members.isEmpty()) {
+			showWarning("error.select.one.user");
+		} else {
+			List<Long> identityKeys = getMemberKeys(members);
+			List<Identity> identities = securityManager.loadIdentityByKeys(identityKeys);
+			editMembersCtrl = new EditMembershipController(ureq, getWindowControl(), identities, repoEntry, businessGroup);
+			listenTo(editMembersCtrl);
+			cmc = new CloseableModalController(getWindowControl(), translate("close"), editMembersCtrl.getInitialComponent(),
+					true, translate("edit.member"));
+			cmc.activate();
+			listenTo(cmc);
+		}
 	}
 	
 	protected void doSearch(String search) {
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
index 2d5e11100daa86c78ad6ce411d49f0a61c98c652..cf56f2dbbd5a0c46e87caea97dc0c3b4256f2e95 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
@@ -1,7 +1,7 @@
 #Mon Mar 02 09:54:04 CET 2009
 create.form.title=Neue Gruppe erstellen
 create.group=Gruppe erstellen
-create.group.description=Erzeugen Sie eine neue Gruppe mit der unten stehenden Schaltfläche. Als Betreuer dieser Gruppe können Sie danach die Gruppenwerkzeuge freischalten, Benutzer hinzufügen oder die Gruppe veröffentlichen.
+create.group.description=Erzeugen Sie eine neue Gruppe mit der unten stehenden Schaltfl\u00E4che. Als Betreuer dieser Gruppe k\u00F6nnen Sie danach die Gruppenwerkzeuge freischalten, Benutzer hinzuf\u00FCgen oder die Gruppe ver\u00F6ffentlichen.
 copy.group=Kopieren
 deup.members=Mitglieder bereinigen
 dedup.members.typ=Rolle
@@ -10,7 +10,7 @@ dedup.members.particpants=Teilnehmer
 dedup.members.info1=Wollen Sie die Mitglieder wirklich bereinigen?
 dedup.members.info2=Bei diesem Prozess werden jene Benutzer als Kursmitglieder ausgetragen, die sowohl Kurs- als auch Gruppenmitglied des Kurses sind (Duplikate).
 dedup.members.info3={0} Benutzer wurden gefunden die sowohl Kursmitglieder als auch Gruppenmitglieder des Kurses sind.
-dedup.members.info4=Wählen Sie ob die Bereinigung für Betreuer und/oder die Teilnehmer durchgeführt werden soll.
+dedup.members.info4=W\u00E4hlen Sie ob die Bereinigung f\u00FCr Betreuer und/oder die Teilnehmer durchgef\u00FChrt werden soll.
 dialog.modal.bg.delete.title=Gruppe l\u00F6schen?
 dialog.modal.bg.delete.text=Wollen Sie die Gruppe "{0}" wirklich l\u00F6schen?
 dialog.modal.bg.mail.text=Wollen Sie die Mitglieder per Mail benachrichtigen?
@@ -22,8 +22,9 @@ remove.send.mail=Benachrichtigung
 remove.send.mail.label=E-Mail versenden
 error.atleastone=Es muss mindestens einen Besitzer im Kurs geben.
 error.msg.send.no.rcps=$org.olat.modules.co\:error.msg.send.no.rcps
-error.managed.group=Die gewählte Gruppe "{0}" wird von einem externen System verwaltet. Die Operation kann nicht ausgeführt werden.
-error.select.one=Sie müssen mindestens eine Gruppe w\u00E4hlen.
+error.managed.group=Die gew\u00E4hlte Gruppe "{0}" wird von einem externen System verwaltet. Die Operation kann nicht ausgef\u00FChrt werden.
+error.select.one=Sie m\u00FCssen mindestens eine Gruppe w\u00E4hlen.
+error.select.one.user=Sie m\u00FCssen mindestens einen Benutzer w\u00E4hlen.
 mail.member=E-Mail
 main.menu.title=Gruppen
 main.menu.title.alt=Gruppen
@@ -32,7 +33,7 @@ index.intro=In der untenstehenden Liste finden Sie alle Gruppen, an denen Sie te
 index.table.nogroup=Sie sind in keiner Gruppe eingetragen.
 info.group.deleted=Die Gruppe wurde gel\u00F6scht.
 request.leaving.subject=Anfrage Gruppe "{0}" mit ID "{1}" zu verlassen
-request.leaving.body=Sehr geehrter Gruppenbetreuer<br /><br />Ich m\u00F6chte dieser Gruppe verlasse<br /><br />Mit freundliche Grüsse<br />{3} {4}<br />\Gruppename: {0}<br />Gruppe ID:{1}<br />Gruppekurse: {2}
+request.leaving.body=Sehr geehrter Gruppenbetreuer<br /><br />Ich m\u00F6chte dieser Gruppe verlasse<br /><br />Mit freundliche Gr\u00FCsse<br />{3} {4}<br />\Gruppename: {0}<br />Gruppe ID:{1}<br />Gruppekurse: {2}
 menu.group.admin=Gruppenverwaltung
 menu.group.admin.alt=Gruppenverwaltung
 menu.index=Gruppen
@@ -42,10 +43,10 @@ my.groups.alt=Arbeiten Sie mit Ihren Gruppen
 open.groups=Ver\u00F6ffentlichte Gruppen
 open.groups.alt=Arbeitsgruppen in die \u00F6ffentlich sind und an denen ich teilnehmen kann.
 msg.atleastone=Es muss mindestens ein Betreuer in der Gruppe eingetragen sein.
-msg.alleastone.editable.group=Sie m\u00FCssen mindestens eine Gruppe wählen, die Sie besitzen.
+msg.alleastone.editable.group=Sie m\u00FCssen mindestens eine Gruppe w\u00E4hlen, die Sie besitzen.
 user.notfound=Folgende Benutzer wurden nicht gefunden: {0}
 
-open.header=Öffentliche Gruppen
+open.header=\u00F6ffentliche Gruppen
 open.intro=In dieser Liste finden Sie alle ver\u00F6ffentlichten Gruppen denen Sie beitreten k\u00F6nnen.
 open.nogroup=Es wurden keine Gruppe gefunden die Ihren Kriterien entsprechen.
 opengroups.all=Alle Gruppen
@@ -64,7 +65,7 @@ search.waiting=Warteliste
 search.public=Public group
 search.all=Alle
 search.none=-
-search.open=Veröffentlicht
+search.open=Ver\u00F6ffentlicht
 search.roles=Rolle
 search.yes=Ja
 search.no=Nein
@@ -103,16 +104,16 @@ table.header.role=Rolle
 table.header.firstTime=Beitritt
 table.header.lastTime=Zuletzt besucht
 table.header.key=ID
-table.header.freePlaces=Plätze
+table.header.freePlaces=Pl\u00E4tze
 table.header.tutorsCount=Betreuer
 table.header.participantsCount=Belegt
 table.header.waitingListCount=Warteliste
 table.access=Beitreten
 table.access.waitingList=Warteliste eintragen
-table.delete=Löschen
+table.delete=L\u00F6schen
 table.email=E-Mail versenden
 table.duplicate=Duplizieren
-table.merge=Zusammenführen
+table.merge=Zusammenf\u00FChren
 table.users.management=Benutzer verwalten
 table.config=Konfigurieren
 table.leave=Verlassen
@@ -121,13 +122,13 @@ tools.add.header=Erstellen
 tools.delete.header=L\u00F6schen
 tools.delete.unusedgroup=Arbeitsgruppen
 action=Aktion
-merge.group=Zusammenführen
+merge.group=Zusammenf\u00FChren
 email.group=E-Mail versenden
 config.group=Konfigurieren
 users.group=Benutzer verwalten
 
 notification.mail.added.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\nSie wurden von {0} {1} ({2}) in eine Arbeitsgruppe eingeladen\: \n\nGruppenname\: $groupname\nBeschreibung\: $groupdescription\n\nSind Sie damit nicht einverstanden, so k\u00F6nnen Sie sich aus der Arbeitsgruppe wieder austragen.
-notification.mail.added.self.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\n Sie haben in OLAT eine Arbeitsgruppe eröffnet\: \n\nGruppenname\: $groupname\nBeschreibung\: $groupdescription\n\nSie k\u00F6nnen die Gruppe jederzeit wieder löschen.
+notification.mail.added.self.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\n Sie haben in OLAT eine Arbeitsgruppe er\u00F6ffnet\: \n\nGruppenname\: $groupname\nBeschreibung\: $groupdescription\n\nSie k\u00F6nnen die Gruppe jederzeit wieder l\u00F6schen.
 notification.mail.added.self.subject=Gruppe $groupname
 notification.mail.added.subject=Gruppe $groupname
 notification.mail.deleted.body=*** Das ist eine automatisch generierte Nachricht. Bitte antworten Sie nicht auf diese Nachricht *** \n\n Sie wurden von {0} {1} ({2}) aus der Arbeitsgruppe ausgetragen, da sie gel\u00F6scht wurde\: \n\nGruppenname\: $groupname\nBeschreibung\: $groupdescription\n\nBei Fragen kontaktieren Sie bitte {0} {1} ({2}).
@@ -138,18 +139,18 @@ notification.mail.removed.self.subject=Gruppe $groupname\: Sie haben sich ausget
 notification.mail.removed.subject=Gruppe $groupname\: Sie wurden ausgetragen.
 
 
-pending.reservations=<h4>Bestätigung Teilnahme in Gruppen und Kursen</h4>Sie wurden in die folgenden Gruppen oder Kurse eingeladen. Wählen Sie für alle aufgeführten Gruppe und Kurse die Schaltfläche "$:accept" oder "$:reject" und schliessen Sie mit "$org.olat.core:ok" ab. Sie können die Bestätigung auch zu einem späteren Zeitpunkt durchführen, wählen Sie in dem Fall "$org.olat.core:cancel".
+pending.reservations=<h4>Best\u00E4tigung Teilnahme in Gruppen und Kursen</h4>Sie wurden in die folgenden Gruppen oder Kurse eingeladen. W\u00E4hlen Sie f\u00FCr alle aufgef\u00FChrten Gruppe und Kurse die Schaltfl\u00E4che "$:accept" oder "$:reject" und schliessen Sie mit "$org.olat.core:ok" ab. Sie k\u00F6nnen die Best\u00E4tigung auch zu einem sp\u00E4teren Zeitpunkt durchf\u00FChren, w\u00E4hlen Sie in dem Fall "$org.olat.core:cancel".
 
 course.membership.creation=Kurs Beitritt
-course.lastTime=Zuletzt geöffnet
+course.lastTime=Zuletzt ge\u00F6ffnet
 course.numOfVisits=Anzahl Kursaufrufe
 home=Visitenkarte
 assessment=Bewertungswerkzeug
-add.member=Mitglied hinzufügen
+add.member=Mitglied hinzuf\u00FCgen
 edit.member=Mitglied bearbeiten
 edit.members=Bearbeiten
 edit.member.groups=Gruppenmitgliedschaften
-import.member=Mitglieder hinzufügen
+import.member=Mitglieder hinzuf\u00FCgen
 
 
 
@@ -159,7 +160,7 @@ role.group.waiting=Warteliste
 role.repo.owner=Besitzer
 role.repo.tutor=Betreuer
 role.repo.participant=Teilnehmer
-role.pending=Bestätigung ausstehend
+role.pending=Best\u00E4tigung ausstehend
 
 edit.member.title=Mitgliederrechte Kurs "{0}"
 
@@ -182,10 +183,10 @@ table.header.waitingList=Warteliste
 
 reservation.coach=als Betreuer
 group.used.in.course=Diese Gruppe wird verwendet in folgenden Kursen:
-accept=Bestätigen
+accept=Best\u00E4tigen
 reject=Ablehnen
 
-confirm.accept=Mitgliedschaft wird bestätigt
+confirm.accept=Mitgliedschaft wird best\u00E4tigt
 confirm.reject=Mitgliedschaft wird abgelehnt
 
 nomembers=Es wurden keine Mitglieder gefunden die Ihren Kriterien entsprechen.
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
index 1d1702cb6aca905313f967326a2240a73666a4cf..8d5c09397ae959f889e022a319915a1f5c9d879f 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_en.properties
@@ -45,6 +45,7 @@ error.atleastone=At least one owner is required in a course.
 error.managed.group=The selected group "{0}" is managed by an external system. The operation cannot be executed.
 error.msg.send.no.rcps=$org.olat.modules.co\:error.msg.send.no.rcps
 error.select.one=You need to select at least one group.
+error.select.one.user=You need to select at least one user.
 group.access.success=Access to group is successful
 group.used.in.course=This group is used in the following courses\:
 hide=Hide information
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_fr.properties
index 691a63a3626ac1008e9bbe8944cb9258f278d33d..e154ff9fb48dc419b64b051485aeda452acd75c8 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_fr.properties
@@ -45,6 +45,7 @@ error.atleastone=Le cours doit avoir au moins un propri\u00E9taire.
 error.managed.group=Les groupes s\u00E9lectionn\u00E9s "{0}" sont administr\u00E9s par un syst\u00E8me externe. L'op\u00E9ration ne peut pas \u00EAtre effectu\u00E9e.
 error.msg.send.no.rcps=$org.olat.modules.co\:error.msg.send.no.rcps
 error.select.one=Vous devez s\u00E9lectionner au moins un groupe.
+error.select.one.user=Vous devez s\u00E9lectionner au moins un utilisateur.
 group.access.success=L'acc\u00E8s au groupe a \u00E9t\u00E9 couronn\u00E9 de succ\u00E8s.
 group.used.in.course=Ce groupe est utilis\u00E9 par les cours suivants\:
 hide=Masquer les informations
diff --git a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
index 2bd44dfbc09ff12f1cd1ef2d970655ef47a19198..27df703bce9e0e5439c1c591d62a3b95a6ffc8ea 100644
--- a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
+++ b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
@@ -527,19 +527,38 @@ public class CoachingDAO {
 	
 	private boolean getCoursesStatisticsUserInfosForOwner(Identity coach, Map<Long,CourseStatEntry> map) {
 		NativeQueryBuilder sb = new NativeQueryBuilder(1024, dbInstance);
-		sb.append("select")
-		  .append("  sg_re.repositoryentry_id as re_id,")
-		  .append("  count(distinct sg_participant.fk_identity_id) as student_id,")
-		  .append("  count(distinct pg_initial_launch.id) as pg_id")
-		  .append(" from o_repositoryentry sg_re ")
-		  .append(" inner join o_re_to_group owngroup on (owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(")")
-		  .append(" inner join o_bs_group_member sg_coach on (sg_coach.fk_group_id=owngroup.fk_group_id and sg_coach.g_role = 'owner')")
-		  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
-		  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
-		  .append(" left join o_as_user_course_infos pg_initial_launch")
-		  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
-		  .append(" where sg_coach.fk_identity_id=:coachKey and sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS)
-		  .append(" group by sg_re.repositoryentry_id");
+		if(dbInstance.isMySQL()) {
+			sb.append("select")
+			  .append("  sg_re.repositoryentry_id as re_id,")
+			  .append("  count(distinct sg_participant.fk_identity_id) as student_id,")
+			  .append("  count(distinct pg_initial_launch.id) as pg_id")
+			  .append(" from o_repositoryentry sg_re ")
+			  .append(" inner join o_re_to_group owngroup on (owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(")")
+			  .append(" inner join o_bs_group_member sg_coach on (sg_coach.fk_group_id=owngroup.fk_group_id and sg_coach.g_role = 'owner')")
+			  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
+			  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
+			  .append(" left join o_as_user_course_infos pg_initial_launch")
+			  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
+			  .append(" where sg_coach.fk_identity_id=:coachKey and sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS)
+			  .append(" group by sg_re.repositoryentry_id");
+		} else {
+			sb.append("select")
+			  .append("  sg_re.repositoryentry_id as re_id,")
+			  .append("  count(distinct sg_participant.fk_identity_id) as student_id,")
+			  .append("  count(distinct pg_initial_launch.id) as pg_id")
+			  .append(" from o_repositoryentry sg_re ")
+			  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
+			  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
+			  .append(" left join o_as_user_course_infos pg_initial_launch")
+			  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
+			  .append(" where sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS).append(" and sg_re.fk_olatresource in (")
+			  .append("  select sg_res.resource_id from o_olatresource sg_res where sg_res.resname = 'CourseModule'")
+			  .append(" ) and exists (")
+			  .append("  select owngroup.id from o_re_to_group owngroup inner join o_bs_group_member sg_owner on (sg_owner.fk_group_id=owngroup.fk_group_id)")
+			  .append("  where owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(" and sg_owner.g_role='owner' and sg_owner.fk_identity_id=:coachKey")
+			  .append(" )")
+			  .append(" group by sg_re.repositoryentry_id");
+		}
 
 		List<?> rawList = dbInstance.getCurrentEntityManager()
 				.createNativeQuery(sb.toString())
@@ -669,20 +688,39 @@ public class CoachingDAO {
 	
 	private boolean getStudentsStastisticInfosForOwner(IdentityRef coach, Map<Long, StudentStatEntry> map) {
 		NativeQueryBuilder sb = new NativeQueryBuilder(1024, dbInstance);
-		sb.append("select")
-		  .append("  sg_participant.fk_identity_id as part_id,")
-		  .append("  ").appendToArray("sg_re.repositoryentry_id").append(" as re_ids,")
-		  .append("  ").appendToArray("pg_initial_launch.id").append(" as pg_ids")
-		  .append(" from o_repositoryentry sg_re")
-		  .append(" inner join o_olatresource sg_res on (sg_res.resource_id = sg_re.fk_olatresource and sg_res.resname = 'CourseModule')")
-		  .append(" inner join o_re_to_group owngroup on (owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(")")
-		  .append(" inner join o_bs_group_member sg_owner on (sg_owner.fk_group_id=owngroup.fk_group_id and sg_owner.g_role = 'owner')")
-		  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
-		  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
-		  .append(" left join o_as_user_course_infos pg_initial_launch")
-		  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
-		  .append(" where sg_owner.fk_identity_id=:coachKey and sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS)
-		  .append(" group by sg_participant.fk_identity_id");
+		if(dbInstance.isMySQL()) {
+			sb.append("select")
+			  .append("  sg_participant.fk_identity_id as part_id,")
+			  .append("  ").appendToArray("sg_re.repositoryentry_id").append(" as re_ids,")
+			  .append("  ").appendToArray("pg_initial_launch.id").append(" as pg_ids")
+			  .append(" from o_repositoryentry sg_re")
+			  .append(" inner join o_olatresource sg_res on (sg_res.resource_id = sg_re.fk_olatresource and sg_res.resname = 'CourseModule')")
+			  .append(" inner join o_re_to_group owngroup on (owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(")")
+			  .append(" inner join o_bs_group_member sg_owner on (sg_owner.fk_group_id=owngroup.fk_group_id and sg_owner.g_role = 'owner')")
+			  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
+			  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
+			  .append(" left join o_as_user_course_infos pg_initial_launch")
+			  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
+			  .append(" where sg_owner.fk_identity_id=:coachKey and sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS)
+			  .append(" group by sg_participant.fk_identity_id");
+		} else {
+			sb.append("select")
+			  .append("  sg_participant.fk_identity_id as part_id,")
+			  .append("  ").appendToArray("sg_re.repositoryentry_id").append(" as re_ids,")
+			  .append("  ").appendToArray("pg_initial_launch.id").append(" as pg_ids")
+			  .append(" from o_repositoryentry sg_re")
+			  .append(" inner join o_re_to_group togroup on (togroup.fk_entry_id = sg_re.repositoryentry_id)")
+			  .append(" inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=togroup.fk_group_id and sg_participant.g_role='participant')")
+			  .append(" left join o_as_user_course_infos pg_initial_launch")
+			  .append("   on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)")
+			  .append(" where sg_re.accesscode >= ").append(RepositoryEntry.ACC_OWNERS).append(" and sg_re.fk_olatresource in (")
+			  .append("  select sg_res.resource_id from o_olatresource sg_res where sg_res.resname = 'CourseModule'")
+			  .append(" ) and exists (")
+			  .append("  select owngroup.id from o_re_to_group owngroup inner join o_bs_group_member sg_owner on (sg_owner.fk_group_id=owngroup.fk_group_id)")
+			  .append("  where owngroup.fk_entry_id = sg_re.repositoryentry_id and owngroup.r_defgroup=").appendTrue().append(" and sg_owner.g_role='owner' and sg_owner.fk_identity_id=:coachKey")
+			  .append(" )")
+			  .append(" group by sg_participant.fk_identity_id");
+		}
 		
 		List<?> rawList = dbInstance.getCurrentEntityManager()
 				.createNativeQuery(sb.toString())
diff --git a/src/test/java/org/olat/selenium/page/course/EnrollmentConfigurationPage.java b/src/test/java/org/olat/selenium/page/course/EnrollmentConfigurationPage.java
index a3a95c92ebbcf9840187adcc0893549a147fbfd3..d9996f952aaaa5888d3e2fc5fe02d0f1094cb9e2 100644
--- a/src/test/java/org/olat/selenium/page/course/EnrollmentConfigurationPage.java
+++ b/src/test/java/org/olat/selenium/page/course/EnrollmentConfigurationPage.java
@@ -84,6 +84,7 @@ public class EnrollmentConfigurationPage {
 		By createGroupBy = By.cssSelector("div.o_button_group_right a");
 		browser.findElement(createGroupBy).click();
 		OOGraphene.waitBusy(browser);
+		OOGraphene.waitModalDialog(browser);
 		
 		//fill the form
 		By nameBy = By.cssSelector(".o_sel_group_edit_title input[type='text']");
diff --git a/src/test/java/org/olat/selenium/page/course/InfoMessageCEPage.java b/src/test/java/org/olat/selenium/page/course/InfoMessageCEPage.java
index 572e719a6738a12e8cf9c88fd6b05b0a7012f1f4..96d27ffe252c06d9878710a5d4137026e3d13f1a 100644
--- a/src/test/java/org/olat/selenium/page/course/InfoMessageCEPage.java
+++ b/src/test/java/org/olat/selenium/page/course/InfoMessageCEPage.java
@@ -57,6 +57,7 @@ public class InfoMessageCEPage {
 		By createBy = By.className("o_sel_course_info_create_msg");
 		browser.findElement(createBy).click();
 		OOGraphene.waitBusy(browser);
+		OOGraphene.waitModalDialog(browser);
 		return this;
 	}
 	
diff --git a/src/test/java/org/olat/selenium/page/forum/ForumPage.java b/src/test/java/org/olat/selenium/page/forum/ForumPage.java
index 96654244e9accac812e4878e4ed312908cfad295..63cabef405dece6864da9ffa391de9e12de636fb 100644
--- a/src/test/java/org/olat/selenium/page/forum/ForumPage.java
+++ b/src/test/java/org/olat/selenium/page/forum/ForumPage.java
@@ -102,6 +102,7 @@ public class ForumPage {
 		By newThreadBy = By.className("o_sel_forum_thread_new");
 		browser.findElement(newThreadBy).click();
 		OOGraphene.waitBusy(browser);
+		OOGraphene.waitModalDialog(browser);
 		
 		//fill the form
 		By titleBy = By.cssSelector("div.modal-content form div.o_sel_forum_message_title input[type='text']");
diff --git a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
index 8b6bf0549a32e14f578926f4b09570733a439ce6..0b5b18b4154bd1c7060dca3eb4cc85575e012342 100644
--- a/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
+++ b/src/test/java/org/olat/selenium/page/graphene/OOGraphene.java
@@ -49,6 +49,11 @@ public class OOGraphene {
 	private static final By closeBlueBoxButtonBy = By.cssSelector("div.o_alert_info div.o_sel_info_message i.o_icon.o_icon_close");
 	private static final By closeModalDialogButtonBy = By.cssSelector("div.modal-dialog div.modal-header button.close");
 	
+	public static void waitModalDialog(WebDriver browser) {
+		By modalBy = By.cssSelector("div.modal-dialog div.modal-body");
+		waitElement(modalBy, 5, browser);
+	}
+	
 	public static void waitBusy(WebDriver browser) {
 		Graphene.waitModel(browser).pollingEvery(poolingDuration, TimeUnit.MILLISECONDS).until(new BusyPredicate());
 	}
diff --git a/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java b/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
index ae53a7a8dd286ca4975d07cc07a3e217df011bb8..a72884ce978ec8670483fb6da6d3ada837319719 100644
--- a/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
+++ b/src/test/java/org/olat/selenium/page/portfolio/PortfolioPage.java
@@ -274,14 +274,9 @@ public class PortfolioPage {
 	 * @return
 	 */
 	public PortfolioPage selectMapInEditor(String mapTitle) {
-		By mapNodeBy = By.cssSelector("div.o_ep_toc_editor span.o_tree_level_label_open.o_tree_l1>a");
-		WebElement selectedNode = null;
-		List<WebElement> level1Nodes = browser.findElements(mapNodeBy);
-		for(WebElement level1Node:level1Nodes) {
-			if(level1Node.getText().contains(mapTitle)) {
-				selectedNode = level1Node;
-			}
-		}
+		By mapNodeBy = By.xpath("//div[contains(@class,'o_ep_toc_editor')]//span[contains(@class,'o_tree_level_label_open')][contains(@class,'o_tree_l1')]//a//span[text()[contains(.,'" + mapTitle + "')]]");
+		OOGraphene.waitElement(mapNodeBy, 5, browser);
+		WebElement selectedNode = browser.findElement(mapNodeBy);
 		Assert.assertNotNull(selectedNode);
 		selectedNode.click();
 		OOGraphene.waitBusy(browser);
@@ -290,9 +285,8 @@ public class PortfolioPage {
 	
 	public PortfolioPage selectMapInEditor() {
 		By mapNodeBy = By.cssSelector("div.o_ep_toc_editor span.o_tree_link.o_tree_l1.o_tree_l1>a");
-		List<WebElement> level1Nodes = browser.findElements(mapNodeBy);
-		Assert.assertFalse(level1Nodes.isEmpty());
-		level1Nodes.get(0).click();
+		OOGraphene.waitElement(mapNodeBy, 5, browser);
+		browser.findElement(mapNodeBy).click();
 		OOGraphene.waitBusy(browser);
 		return this;
 	}
@@ -320,9 +314,8 @@ public class PortfolioPage {
 	 */
 	public PortfolioPage selectFirstPageInEditor() {
 		By pageNodeBy = By.cssSelector("div.o_ep_toc_editor span.o_tree_level_label_leaf.o_tree_l2>a");
-		List<WebElement> level2Nodes = browser.findElements(pageNodeBy);
-		Assert.assertFalse(level2Nodes.isEmpty());
-		level2Nodes.get(0).click();
+		OOGraphene.waitElement(pageNodeBy, 5, browser);
+		browser.findElement(pageNodeBy).click();
 		OOGraphene.waitBusy(browser);
 		return this;
 	}