diff --git a/pom.xml b/pom.xml
index d39983fb3cecb1ae57af71f557b0bef0e160b568..f9822ea424c3c9196440563de550e3c061ff2933 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1350,7 +1350,15 @@
 					</execution>
 				</executions>
 			</plugin>
-		</plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>10</source>
+                    <target>10</target>
+                </configuration>
+            </plugin>
+        </plugins>
 		<pluginManagement>
 			<plugins>
 				<!-- OLAT requires JDK 1.8 or later ! -->
diff --git a/src/main/java/org/olat/admin/user/UserShortDescription.java b/src/main/java/org/olat/admin/user/UserShortDescription.java
index 9bf49ef1f358d612525ac7f7e7200df75296300a..88525271a4c086afa2bb6158ad652543c9f99955 100644
--- a/src/main/java/org/olat/admin/user/UserShortDescription.java
+++ b/src/main/java/org/olat/admin/user/UserShortDescription.java
@@ -38,7 +38,7 @@ import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
 import org.olat.core.id.UserConstants;
-import org.olat.modules.coach.ui.UserRelationOverviewController;
+import org.olat.modules.coach.ui.UserOverviewController;
 import org.olat.user.UserManager;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -79,7 +79,7 @@ public class UserShortDescription extends BasicController {
 	public UserShortDescription(UserRequest ureq, WindowControl wControl, Identity identity, boolean isAdministrativeUser) {
 		super(ureq, wControl);
 
-		initProperties(UserRelationOverviewController.usageIdentifier, identity, isAdministrativeUser, true, null);
+		initProperties(UserOverviewController.usageIdentifier, identity, isAdministrativeUser, true, null);
 	}
 
 	private void initProperties(String identifier, Identity identity, boolean isAdministrativeUser, boolean usernameOnTop, Rows additionalRows) {
diff --git a/src/main/java/org/olat/admin/user/_content/userShortDescription.html b/src/main/java/org/olat/admin/user/_content/userShortDescription.html
index e609ce260c73f9475bec13d08628e635394d9231..51d34dafa2efa9b63dfe4431b7ce8948a143af0e 100644
--- a/src/main/java/org/olat/admin/user/_content/userShortDescription.html
+++ b/src/main/java/org/olat/admin/user/_content/userShortDescription.html
@@ -1,6 +1,6 @@
 <div class="o_userShortDescription" id="$r.getCId()">
 <table class="table table-bordered table-condensed table-striped">
-	#if($r.isNotNull($usernamePosition) && $usernamePosition == "top")
+	#if($r.isNotNull($identityKey) && $r.isNotNull($usernamePosition) && $usernamePosition == "top")
 		#if($r.isNotNull($username))
 		<tr class="o_prop o_username">
 			<th scope="row">$usernameLabel</th>
@@ -20,7 +20,7 @@
 		</tr>
 		#end
 	#end
-	#if($r.isNotNull($usernamePosition) && $usernamePosition == "bottom")
+	#if($r.isNotNull($identityKey) && $r.isNotNull($usernamePosition) && $usernamePosition == "bottom")
 		#if($r.isNotNull($username))
 		<tr class="o_prop o_username">
 			<th scope="row">$usernameLabel</th>
diff --git a/src/main/java/org/olat/basesecurity/IdentityRelationshipService.java b/src/main/java/org/olat/basesecurity/IdentityRelationshipService.java
index a5f3509c97c1208fe8be6d871288df9dd5a259c4..b774b17845c37760e56d16ae9bd75f180ce67acd 100644
--- a/src/main/java/org/olat/basesecurity/IdentityRelationshipService.java
+++ b/src/main/java/org/olat/basesecurity/IdentityRelationshipService.java
@@ -50,7 +50,9 @@ public interface IdentityRelationshipService {
 	
 	public List<RelationRight> getAvailableRights();
 	
-	public RelationRightProvider getRelationRightProvider(RelationRight right);
+	public RightProvider getRelationRightProvider(RelationRight right);
+
+	public List<RightProvider> getAvailableRightProviders();
 	
 	public boolean isInUse(RelationRole relationRole);
 	
diff --git a/src/main/java/org/olat/basesecurity/RelationRight.java b/src/main/java/org/olat/basesecurity/RelationRight.java
index af49991d30e7bd2162ee7def96fa97ab432dbf32..e32720bf178c67ace549c230b1c0e36182ac4722 100644
--- a/src/main/java/org/olat/basesecurity/RelationRight.java
+++ b/src/main/java/org/olat/basesecurity/RelationRight.java
@@ -32,5 +32,4 @@ public interface RelationRight extends CreateInfo {
 	public Long getKey();
 	
 	public String getRight();
-
 }
diff --git a/src/main/java/org/olat/basesecurity/manager/IdentityRelationshipServiceImpl.java b/src/main/java/org/olat/basesecurity/manager/IdentityRelationshipServiceImpl.java
index d07057ee72293eec94fc18f6c79fd49cadb1d5d7..25ec20d6fd2120ff9f544683c2425a7c08c6c8a7 100644
--- a/src/main/java/org/olat/basesecurity/manager/IdentityRelationshipServiceImpl.java
+++ b/src/main/java/org/olat/basesecurity/manager/IdentityRelationshipServiceImpl.java
@@ -20,7 +20,10 @@
 package org.olat.basesecurity.manager;
 
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 import javax.annotation.PostConstruct;
 
@@ -29,7 +32,7 @@ import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.IdentityToIdentityRelation;
 import org.olat.basesecurity.IdentityToIdentityRelationManagedFlag;
 import org.olat.basesecurity.RelationRight;
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.basesecurity.RelationRole;
 import org.olat.basesecurity.RelationRoleManagedFlag;
 import org.olat.basesecurity.RelationSearchParams;
@@ -54,11 +57,11 @@ public class IdentityRelationshipServiceImpl implements IdentityRelationshipServ
 	private IdentityToIdentityRelationDAO identityRelationshipDao;
 	
 	@Autowired
-	private List<RelationRightProvider> relationRightProviders;
+	private List<RightProvider> allRights;
 	
 	@PostConstruct
 	void ensureRightsExists() {
-		for (RelationRightProvider relationRightProvider : relationRightProviders) {
+		for (RightProvider relationRightProvider : allRights) {
 			relationRightDao.ensureRightExists(relationRightProvider.getRight());
 		}
 	}
@@ -70,7 +73,7 @@ public class IdentityRelationshipServiceImpl implements IdentityRelationshipServ
 	
 	@Override
 	public RelationRole createRole(String role, List<RelationRight> rights) {
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		if(rights != null && !rights.isEmpty()) {
 			relationRoleDao.setRights(relationRole, rights);
 		}
@@ -80,7 +83,7 @@ public class IdentityRelationshipServiceImpl implements IdentityRelationshipServ
 	@Override
 	public RelationRole createRole(String role, String externalId, String externalRef,
 			RelationRoleManagedFlag[] managedFlags, List<RelationRight> rights) {
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, externalId, externalRef, managedFlags);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, externalId, externalRef, managedFlags, true);
 		if(rights != null && !rights.isEmpty()) {
 			relationRoleDao.setRights(relationRole, rights);
 		}
@@ -112,12 +115,15 @@ public class IdentityRelationshipServiceImpl implements IdentityRelationshipServ
 
 	@Override
 	public List<RelationRight> getAvailableRights() {
-		return relationRightDao.loadRelationRights();
+		List<RelationRight> relationRights = relationRightDao.loadRelationRights();
+		List<String> relationRightStrings = allRights.stream().filter(RightProvider::isUserRelationsRight).map(RightProvider::getRight).collect(Collectors.toList());
+
+		return relationRights.stream().filter(right -> relationRightStrings.contains(right.getRight())).collect(Collectors.toList());
 	}
 
 	@Override
-	public RelationRightProvider getRelationRightProvider(RelationRight right) {
-		for (RelationRightProvider provider : relationRightProviders) {
+	public RightProvider getRelationRightProvider(RelationRight right) {
+		for (RightProvider provider : allRights) {
 			if (provider.getRight().equals(right.getRight())) {
 				return provider;
 			}
@@ -125,6 +131,14 @@ public class IdentityRelationshipServiceImpl implements IdentityRelationshipServ
 		return null;
 	}
 
+	@Override
+	public List<RightProvider> getAvailableRightProviders() {
+		return getAvailableRights().stream().map(this::getRelationRightProvider)
+				.filter(Objects::nonNull)
+				.sorted(Comparator.comparing(RightProvider::getUserRelationsPosition))
+				.collect(Collectors.toList());
+	}
+
 	@Override
 	public boolean isInUse(RelationRole relationRole) {
 		return identityRelationshipDao.isUsed(relationRole);
diff --git a/src/main/java/org/olat/basesecurity/manager/RelationRightDAO.java b/src/main/java/org/olat/basesecurity/manager/RelationRightDAO.java
index 3736d0fb5d56b9826f28ba9b05bde719cd8d29cf..4ecb404be53b4a32676664291fc222d21dbbcf7e 100644
--- a/src/main/java/org/olat/basesecurity/manager/RelationRightDAO.java
+++ b/src/main/java/org/olat/basesecurity/manager/RelationRightDAO.java
@@ -89,5 +89,4 @@ public class RelationRightDAO {
 
 		dbInstance.commitAndCloseSession();
 	}
-
 }
diff --git a/src/main/java/org/olat/basesecurity/manager/RelationRoleDAO.java b/src/main/java/org/olat/basesecurity/manager/RelationRoleDAO.java
index 7deb2be55642570f76f6b06eeb739b792aefef9e..99728433f6b07dd02f388feae49ba9932d831011 100644
--- a/src/main/java/org/olat/basesecurity/manager/RelationRoleDAO.java
+++ b/src/main/java/org/olat/basesecurity/manager/RelationRoleDAO.java
@@ -47,7 +47,7 @@ public class RelationRoleDAO {
 	@Autowired
 	private DB dbInstance;
 	
-	public RelationRole createRelationRole(String role, String externalId, String externalRef, RelationRoleManagedFlag[] flags) {
+	public RelationRole createRelationRole(String role, String externalId, String externalRef, RelationRoleManagedFlag[] flags, boolean userToUserRoleOnly) {
 		RelationRoleImpl relationRole = new RelationRoleImpl();
 		relationRole.setCreationDate(new Date());
 		relationRole.setLastModified(relationRole.getCreationDate());
diff --git a/src/main/java/org/olat/course/certificate/CertificateEmailRightProvider.java b/src/main/java/org/olat/course/certificate/CertificateEmailRightProvider.java
index 46d572f41b9334292e10a9a35ae56defa892108a..65e0c23ce36ef772776bd6eff34db3253ae3e9fa 100644
--- a/src/main/java/org/olat/course/certificate/CertificateEmailRightProvider.java
+++ b/src/main/java/org/olat/course/certificate/CertificateEmailRightProvider.java
@@ -19,9 +19,12 @@
  */
 package org.olat.course.certificate;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.course.certificate.ui.CertificateController;
@@ -34,7 +37,7 @@ import org.springframework.stereotype.Component;
  *
  */
 @Component
-public class CertificateEmailRightProvider implements RelationRightProvider {
+public class CertificateEmailRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "certificateEmail";
 
@@ -44,13 +47,28 @@ public class CertificateEmailRightProvider implements RelationRightProvider {
 	}
 
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.CertificateEmailRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
+	}
+
+	@Override
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.CertificateEmailRight.ordinal();
+	}
+
+	@Override
+	public Collection<OrganisationRoles> getOrganisationRoles() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return -1;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
index 3835740f88578fadf23fac122ebb1d1ae6bbf53e..9802dd02c7b49b377e651f896a44baacbbc04074 100644
--- a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
+++ b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
@@ -49,6 +49,7 @@ import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 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.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.gui.render.Renderer;
@@ -56,6 +57,8 @@ import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.render.URLBuilder;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.core.util.coordinate.CoordinatorManager;
@@ -87,14 +90,13 @@ import org.springframework.beans.factory.annotation.Autowired;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class CertificateAndEfficiencyStatementListController extends FormBasicController
-		implements BreadcrumbPanelAware, GenericEventListener {
+public class CertificateAndEfficiencyStatementListController extends FormBasicController implements BreadcrumbPanelAware, GenericEventListener, Activateable2 {
 	
 	private static final String CMD_SHOW = "cmd.show";
 	private static final String CMD_LAUNCH_COURSE = "cmd.launch.course";
 	private static final String CMD_DELETE = "cmd.delete";
 	private static final String CMD_MEDIA = "cmd.MEDIA";
-	
+
 	private FlexiTableElement tableEl;
 	private BreadcrumbPanel stackPanel;
 	private FormLink coachingToolButton;
@@ -128,27 +130,35 @@ public class CertificateAndEfficiencyStatementListController extends FormBasicCo
 		this(ureq, wControl, ureq.getUserSession().getIdentity(), false, true, true);
 	}
 	
-	public CertificateAndEfficiencyStatementListController(UserRequest ureq, WindowControl wControl,
-			Identity assessedIdentity, boolean linkToCoachingTool, boolean canModify, boolean canLaunchCourse) {
+	public CertificateAndEfficiencyStatementListController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity, boolean linkToCoachingTool, boolean canModify, boolean canLaunchCourse) {
 		super(ureq, wControl, "cert_statement_list");
 		setTranslator(Util.createPackageTranslator(AssessmentModule.class, getLocale(), getTranslator()));
 		this.canModify = canModify;
 		this.assessedIdentity = assessedIdentity;
 		this.linkToCoachingTool = linkToCoachingTool;
 		this.canLaunchCourse = canLaunchCourse;
+
+		// Show heading
+		flc.contextPut("showHeading", true);
 		
 		initForm(ureq);
 		
 		CoordinatorManager.getInstance().getCoordinator().getEventBus()
 			.registerFor(this, getIdentity(), CertificatesManager.ORES_CERTIFICATE_EVENT);
 	}
+
+	public CertificateAndEfficiencyStatementListController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity, boolean linkToCoachingTool, boolean canModify, boolean canLaunchCourse, boolean showHeading) {
+		this(ureq, wControl, assessedIdentity, linkToCoachingTool, canModify, canLaunchCourse);
+
+		// Set visibility of heading
+		flc.contextPut("showHeading", showHeading);
+	}
 	
-	public CertificateAndEfficiencyStatementListController(UserRequest ureq, WindowControl wControl,
-			Identity assessedIdentity, boolean useFieldSet) {
-		this(ureq, wControl, assessedIdentity, false, false, false);
+	public CertificateAndEfficiencyStatementListController(UserRequest ureq, WindowControl wControl, Identity assessedIdentity, boolean withFieldSet) {
+		this(ureq, wControl, assessedIdentity, false, false, true);
 		
-		// Show different header in user relations
-		flc.contextPut("withFieldSet", useFieldSet);
+		// Show different header in user management
+		flc.contextPut("withFieldSet", withFieldSet);
 	}
 	
 	@Override
@@ -226,6 +236,7 @@ public class CertificateAndEfficiencyStatementListController extends FormBasicCo
 		loadModel();
 		tableEl = uifactory.addTableElement(getWindowControl(), "certificates", tableModel, getTranslator(), formLayout);
 		tableEl.setElementCssClass("o_sel_certificates_table");
+		tableEl.setEmtpyTableMessageKey("table.statements.empty");
 	}
 	
 	private void loadModel() {
@@ -406,6 +417,11 @@ public class CertificateAndEfficiencyStatementListController extends FormBasicCo
 		cmc.activate();
 	}
 
+	@Override
+	public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+
+	}
+
 	public class AsArtefactCellRenderer implements FlexiCellRenderer {
 		
 		@Override
diff --git a/src/main/java/org/olat/course/certificate/ui/_content/cert_statement_list.html b/src/main/java/org/olat/course/certificate/ui/_content/cert_statement_list.html
index c8ef2cc50d0f533e13924899e9cf002c8c19f08b..9512505f70c5657fcd107471704248a54a970934 100644
--- a/src/main/java/org/olat/course/certificate/ui/_content/cert_statement_list.html
+++ b/src/main/java/org/olat/course/certificate/ui/_content/cert_statement_list.html
@@ -14,6 +14,8 @@
 </fieldset>
 #else
 ## in users home
-<h2 ><i class="o_icon o_icon o_icon-fw o_icon_certificate"> </i>$r.translate("certificates.and.statements.title")</h2>
-$r.render("certificates")
+	#if($showHeading)
+	<h2 ><i class="o_icon o_icon o_icon-fw o_icon_certificate"> </i>$r.translate("certificates.and.statements.title")</h2>
+	#end
+	$r.render("certificates")
 #end
diff --git a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties
index 6110cbf6578423df74b493138bb2111b1610f825..f480834870a4a851f45c45d58ba85a08da5eb8c4 100644
--- a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_de.properties
@@ -19,6 +19,7 @@ completion=$org.olat.modules.assessment.ui\:learning.progress
 confirm.delete.title=Zertifikate l\u00F6schen
 confirm.delete.text=Wollen Sie dieses Zertifikat wirklich l\u00F6schen?
 table.header.certificate=Zertifikat
+table.statements.empty=Keine Leistungsnachweise oder Zertifikate vorhanden
 choose.title=Vorlage ausw\u00E4hlen
 default.template=Standardvorlage
 details.certificate=Zertifikat
@@ -73,4 +74,4 @@ confirm.certificate.deleted=Das Zertifikat vom {0} wurde gel\u00F6scht.
 certificates.wizard.title=Zertifikate erstellen
 certificates.wizard.select=Benutzer ausw\u00E4hlen
 certificates.wizard.overview=\u00DCbersicht
-msg.certificate.pending=Das Zertifikat wird in ein paar Sekunden erstellt.
\ No newline at end of file
+msg.certificate.pending=Das Zertifikat wird in ein paar Sekunden erstellt.
diff --git a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties
index 8af006992d2ee1ca797eba2daca4a13d9c7f92a0..3519f38d1ebda8a01e42c6d0e897e897beff2659 100644
--- a/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/certificate/ui/_i18n/LocalStrings_en.properties
@@ -64,6 +64,7 @@ recertification.week=Week
 recertification.year=Year
 replace=Replace
 relation.right.email=Copy of certificates per E-Mail
+table.statements.empty=No statements or certificates available
 table.header.certificate=Certificate
 template.file=File
 template.name=Name
diff --git a/src/main/java/org/olat/course/groupsandrights/ViewCourseCalendarRightProvider.java b/src/main/java/org/olat/course/groupsandrights/ViewCourseCalendarRightProvider.java
index f23efb1570e27608c0d36031a6666282631f5a44..d5eaffca4f0f21a5097c585c5c27dd5f078b46a1 100644
--- a/src/main/java/org/olat/course/groupsandrights/ViewCourseCalendarRightProvider.java
+++ b/src/main/java/org/olat/course/groupsandrights/ViewCourseCalendarRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.course.groupsandrights;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.springframework.stereotype.Component;
@@ -33,23 +33,33 @@ import org.springframework.stereotype.Component;
  *
  */
 @Component
-public class ViewCourseCalendarRightProvider implements RelationRightProvider {
+public class ViewCourseCalendarRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = CourseRightsEnum.viewCourseCalendar.name();
 
 	@Override
-	public RelationRightProvider getParent() {
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
+	@Override
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ViewCourseCalendarRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
 
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ViewCourseCalendarRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ViewCourseCalendarRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/groupsandrights/ViewEfficiencyStatementRightProvider.java b/src/main/java/org/olat/course/groupsandrights/ViewEfficiencyStatementRightProvider.java
index c96f32c705c26afda982160044e4d73fe841f9f2..93504300c22b0de3d83e7311d46187ea73084c53 100644
--- a/src/main/java/org/olat/course/groupsandrights/ViewEfficiencyStatementRightProvider.java
+++ b/src/main/java/org/olat/course/groupsandrights/ViewEfficiencyStatementRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.course.groupsandrights;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.security.CoursesAndCurriculumRightProvider;
@@ -35,7 +35,7 @@ import org.springframework.stereotype.Component;
  *
  */
 @Component
-public class ViewEfficiencyStatementRightProvider implements RelationRightProvider {
+public class ViewEfficiencyStatementRightProvider implements RightProvider {
 
 	@Autowired
 	private CoursesAndCurriculumRightProvider parentRight;
@@ -43,18 +43,28 @@ public class ViewEfficiencyStatementRightProvider implements RelationRightProvid
 	public static final String RELATION_RIGHT = CourseRightsEnum.viewEfficiencyStatement.name();
 
 	@Override
-	public RelationRightProvider getParent() {
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
+	@Override
+	public RightProvider getParent() {
 		return parentRight;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ViewEfficiencyStatementRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
 
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ViewEfficiencyStatementRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ViewEfficiencyStatementRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/AdministrativePropertiesRightProvider.java b/src/main/java/org/olat/modules/coach/security/AdministrativePropertiesRightProvider.java
index 6bfcc013a2d669abaed0c259d0a0d7ac4a6d4d20..d2c56b56ba0482a0b569176cafeb7fa20cc9e7e7 100644
--- a/src/main/java/org/olat/modules/coach/security/AdministrativePropertiesRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/AdministrativePropertiesRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class AdministrativePropertiesRightProvider implements RelationRightProvider {
+public class AdministrativePropertiesRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "showAdministrativeProperties";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.AdministrativePropertiesRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.AdministrativePropertiesRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.AdministrativePropertiesRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/ContactFormRightProvider.java b/src/main/java/org/olat/modules/coach/security/ContactFormRightProvider.java
index 50bc0db872f5b8465b799d149a2fd2da5ed44c31..912c94ebdf3c65ecdd5bd78fa3b2b4a025deeca9 100644
--- a/src/main/java/org/olat/modules/coach/security/ContactFormRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/ContactFormRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class ContactFormRightProvider implements RelationRightProvider {
+public class ContactFormRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "showContactform";
 	
@@ -42,13 +42,23 @@ public class ContactFormRightProvider implements RelationRightProvider {
 	}
 	
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ContactFormRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
+	}
+
+	@Override
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ContactFormRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ContactFormRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/CourseProgressAndStatusRightProvider.java b/src/main/java/org/olat/modules/coach/security/CourseProgressAndStatusRightProvider.java
index 4993acac66f01c5cd8c6399df64804df4e1d8d43..fcefcca2fcbc99261c1b35d0e4a5df9034624ff9 100644
--- a/src/main/java/org/olat/modules/coach/security/CourseProgressAndStatusRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/CourseProgressAndStatusRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -33,26 +33,36 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class CourseProgressAndStatusRightProvider implements RelationRightProvider {
+public class CourseProgressAndStatusRightProvider implements RightProvider {
 
 	@Autowired
 	private CoursesAndCurriculumRightProvider parentRight;
 
 	public static final String RELATION_RIGHT = "showCourseProgressAndStatus";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return parentRight;
 	}
-	
+
 	@Override
-	public int getPosition() {
-		return Order.CourseProgressAndStatusRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
 
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.CourseProgressAndStatusRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.CourseProgressAndStatusRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/CoursesAndCurriculumRightProvider.java b/src/main/java/org/olat/modules/coach/security/CoursesAndCurriculumRightProvider.java
index 7b82212fafbd4c71421a35924a3476bb2a1685ec..4e96510dc074febd10dc5f1b1079749ac59a4a38 100644
--- a/src/main/java/org/olat/modules/coach/security/CoursesAndCurriculumRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/CoursesAndCurriculumRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class CoursesAndCurriculumRightProvider implements RelationRightProvider{
+public class CoursesAndCurriculumRightProvider implements RightProvider {
 	
 	public static final String RELATION_RIGHT = "showCoursesAndCurriculum";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.CourseAndCurriculumRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.CourseAndCurriculumRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.CourseAndCurriculumRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/LecturesAndAbsencesRightProvider.java b/src/main/java/org/olat/modules/coach/security/LecturesAndAbsencesRightProvider.java
index 942b43b0be21c583a0953576b6871555405bc6a3..a353446e12d3380c9b910d4248ed4198402d6516 100644
--- a/src/main/java/org/olat/modules/coach/security/LecturesAndAbsencesRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/LecturesAndAbsencesRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -33,26 +33,36 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class LecturesAndAbsencesRightProvider implements RelationRightProvider {
+public class LecturesAndAbsencesRightProvider implements RightProvider {
 
 	@Autowired
 	private CoursesAndCurriculumRightProvider parentRight;
 
 	public static final String RELATION_RIGHT = "showLecturesAndAbsences";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return parentRight;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.LecturesAndAbsencesRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.LecturesAndAbsencesRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.LecturesAndAbsencesRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/ResetPasswordRightProvider.java b/src/main/java/org/olat/modules/coach/security/ResetPasswordRightProvider.java
index fbb340f23a5882f5403f1833951c545fb2c08284..9b3beff8a8bc8e0db31518eab2b066ff0ae35fce 100644
--- a/src/main/java/org/olat/modules/coach/security/ResetPasswordRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/ResetPasswordRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class ResetPasswordRightProvider implements RelationRightProvider {
+public class ResetPasswordRightProvider implements RightProvider {
 	
 	public static final String RELATION_RIGHT = "resetPassword";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ResetPasswordRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ResetPasswordRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ResetPasswordRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/ResourcesAndBookingsRightProvider.java b/src/main/java/org/olat/modules/coach/security/ResourcesAndBookingsRightProvider.java
index 2ac034f4f5f6946770e04549fc8e7a4c3ce5cc54..7054393bcf996bb73ddf158e9546a703ac792494 100644
--- a/src/main/java/org/olat/modules/coach/security/ResourcesAndBookingsRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/ResourcesAndBookingsRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class ResourcesAndBookingsRightProvider implements RelationRightProvider {
+public class ResourcesAndBookingsRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "showResourcesAndBookings";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ResourceAndBookinsRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ResourceAndBookinsRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ResourceAndBookinsRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/ViewAndEditProfileRightProvider.java b/src/main/java/org/olat/modules/coach/security/ViewAndEditProfileRightProvider.java
index 14063d0a62e95f6d3167a8139f8f2e6117b299cc..58ea916e2f5a2d8d22ee113f3dc8c1ebea767fdb 100644
--- a/src/main/java/org/olat/modules/coach/security/ViewAndEditProfileRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/ViewAndEditProfileRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class ViewAndEditProfileRightProvider implements RelationRightProvider {
+public class ViewAndEditProfileRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "viewAndEditProfile";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ViewAndEditProfileRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
 
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ViewAndEditProfileRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ViewAndEditProfileRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/security/ViewGroupMembershipsRightProvider.java b/src/main/java/org/olat/modules/coach/security/ViewGroupMembershipsRightProvider.java
index ce83521b542f9a1c53f04902917e86eb4bd6e14c..da596d594508b4ed28880cb773df261058ee8dc7 100644
--- a/src/main/java/org/olat/modules/coach/security/ViewGroupMembershipsRightProvider.java
+++ b/src/main/java/org/olat/modules/coach/security/ViewGroupMembershipsRightProvider.java
@@ -21,7 +21,7 @@ package org.olat.modules.coach.security;
 
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.coach.ui.CoachMainController;
@@ -32,23 +32,33 @@ import org.springframework.stereotype.Component;
  * @author aboeckle, alexander.boeckle@frentix.com
  */
 @Component
-public class ViewGroupMembershipsRightProvider implements RelationRightProvider {
+public class ViewGroupMembershipsRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "showGroupMemberships";
-	
+
+	@Override
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
 	@Override
-	public RelationRightProvider getParent() {
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.ViewGroupMemebershipsRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.ViewGroupMemebershipsRight.ordinal();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return OrganisationRightsOrder.ViewGroupMemebershipsRight.ordinal();
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/coach/ui/CoachMainController.java b/src/main/java/org/olat/modules/coach/ui/CoachMainController.java
index 3625992e411720f7879e0546eb48feb2dee080a9..4c1dcfe18705f6778a177b09068aa56c070ce96d 100644
--- a/src/main/java/org/olat/modules/coach/ui/CoachMainController.java
+++ b/src/main/java/org/olat/modules/coach/ui/CoachMainController.java
@@ -19,17 +19,24 @@
  */
 package org.olat.modules.coach.ui;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
+import org.olat.admin.privacy.PrivacyAdminController;
 import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.IdentityToIdentityRelation;
+import org.olat.basesecurity.OrganisationModule;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.basesecurity.OrganisationService;
 import org.olat.basesecurity.RelationRole;
 import org.olat.core.commons.fullWebApp.LayoutMain3ColsController;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.stack.PopEvent;
 import org.olat.core.gui.components.stack.TooledStackedPanel;
 import org.olat.core.gui.components.tree.GenericTreeModel;
 import org.olat.core.gui.components.tree.GenericTreeNode;
@@ -42,11 +49,13 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.MainLayoutBasicController;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Organisation;
 import org.olat.core.id.Roles;
 import org.olat.core.id.context.BusinessControlFactory;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
+import org.olat.core.util.Util;
 import org.olat.core.util.nodes.INode;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.core.util.tree.TreeHelper;
@@ -80,6 +89,7 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 	private final TooledStackedPanel content;
 
 	private final boolean userSearchAllowed;
+	private final boolean showLineManagerView;
 	private final GradingSecurity gradingSec;
 	private final CoachingSecurity coachingSec;
 
@@ -93,6 +103,8 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 	private LecturesCoachingController lecturesMasterCoachCtrl;
 
 	private Map<String, RelationRole> userRelationRolesMap;
+	private Map<String, Organisation> organisationMap;
+	private List<Organisation> organisations;
 
 	@Autowired
 	private GradingModule gradingModule;
@@ -102,15 +114,26 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 	private BaseSecurityModule securityModule;
 	@Autowired
 	private IdentityRelationshipService identityRelationsService;
+	@Autowired
+	private OrganisationService organisationService;
+	@Autowired
+	private OrganisationModule organisationModule;
 
 	public CoachMainController(UserRequest ureq, WindowControl control, CoachingSecurity coachingSec, GradingSecurity gradingSec) {
 		super(ureq, control);
+		setTranslator(Util.createPackageTranslator(PrivacyAdminController.class, getLocale(), getTranslator()));
+
 		this.gradingSec = gradingSec;
 		this.coachingSec = coachingSec;
 		this.userRelationRolesMap = listAvailableRoles(identityRelationsService.getRelationsAsSource(ureq.getIdentity()));
 
 		Roles roles = ureq.getUserSession().getRoles();
 		userSearchAllowed = roles.isAdministrator() || roles.isLearnResourceManager() || roles.isPrincipal();
+		showLineManagerView = organisationModule.isEnabled() && roles.isLineManager();
+		if (showLineManagerView) {
+			organisations = organisationService.getOrganisations(getIdentity(), OrganisationRoles.linemanager);
+			organisationMap = organisations.stream().collect(Collectors.toMap(org -> org.getKey().toString(), org -> org));
+		}
 
 		menu = new MenuTree(null, "coachMenu", this);
 		menu.setExpandSelectedNode(false);
@@ -141,17 +164,45 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 			if (event.getCommand().equals(MenuTree.COMMAND_TREENODE_CLICKED)) {
 				TreeNode selTreeNode = menu.getSelectedNode();
 
-				if (selTreeNode.getDelegate() != null) {
-					String cmd = (String) selTreeNode.getDelegate().getUserObject();
-					selectMenuItem(ureq,cmd);
-				} else if (selTreeNode.getUserObject() instanceof String) {
-					String cmd = (String)selTreeNode.getUserObject();
-					selectMenuItem(ureq, cmd);
+				selectMenuItem(ureq, selTreeNode);
+			}
+		} else if (source == content) {
+			if (event instanceof PopEvent) {
+				PopEvent popEvent = (PopEvent) event;
+
+				if (popEvent.getController() instanceof AbstactCoachListController) {
+					TreeNode selTreeNode = menu.getSelectedNode();
+					selectMenuItem(ureq, selTreeNode);
+					if (selTreeNode.getUserObject() instanceof Organisation) {
+						selectMenuItem(ureq, selTreeNode);
+					} else if (selTreeNode.getUserObject() instanceof RelationRole) {
+						selectMenuItem(ureq, selTreeNode);
+					}
 				}
 			}
 		}
 	}
 
+	private Activateable2 selectMenuItem(UserRequest ureq, TreeNode treeNode) {
+		if (treeNode.getDelegate() != null) {
+			return selectMenuItem(ureq, treeNode.getDelegate());
+		} else if (treeNode.getUserObject() instanceof String) {
+			String cmd = (String) treeNode.getUserObject();
+			return selectMenuItem(ureq, cmd);
+		} else if (treeNode.getUserObject() instanceof Long) {
+			Long cmd = (Long) treeNode.getUserObject();
+			return selectMenuItem(ureq, treeNode.toString());
+		} else if (treeNode.getUserObject() instanceof Organisation) {
+			Organisation organisation = (Organisation) treeNode.getUserObject();
+			return selectMenuItem(ureq, organisation);
+		} else if (treeNode.getUserObject() instanceof RelationRole) {
+			RelationRole relationRole = (RelationRole) treeNode.getUserObject();
+			return selectMenuItem(ureq, relationRole);
+		}
+
+		return null;
+	}
+
 	@Override
 	protected void doDispose() {
 		//
@@ -196,6 +247,9 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 		if (coachingSec.isUserRelationSource()) {
 			return userRelationRolesMap.keySet().stream().findFirst().get();
 		}
+		if (organisationModule.isEnabled()) {
+			return organisationMap.keySet().stream().findFirst().get();
+		}
 		return "Members";
 	}
 
@@ -267,16 +321,7 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 				listenTo(gradingCtrl);
 			}
 			selectedCtrl = gradingCtrl;
-		} else if(userRelationRolesMap.containsKey(cmd) && securityModule.isRelationRoleEnabled()) {
-			OLATResourceable ores = OresHelper.createOLATResourceableInstance(cmd, 0l);
-			ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
-			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
-			UserRelationListController userRelationsListController = new UserRelationListController(ureq, bwControl, content, userRelationRolesMap.get(cmd));
-			listenTo(userRelationsListController);
-
-			selectedCtrl = userRelationsListController;
 		}
-
 		if(selectedCtrl != null) {
 			String title = "Root";
 			TreeNode selTreeNode = TreeHelper.findNodeByUserObject(cmd, menu.getTreeModel().getRootNode());
@@ -287,11 +332,72 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 				}
 			}
 			content.rootController(title, selectedCtrl);
+			content.setInvisibleCrumb(1);
 			addToHistory(ureq, selectedCtrl);
 		}
 		return (Activateable2)selectedCtrl;
 	}
 
+	private Activateable2 selectMenuItem(UserRequest ureq, Organisation organisation) {
+		Controller selectedController = null;
+
+		if (organisationModule.isEnabled()) {
+			OLATResourceable ores = OresHelper.createOLATResourceableInstance("Organisation", organisation.getKey());
+			ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
+			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
+			AbstactCoachListController organisationListController = new OrganisationListController(ureq, bwControl, content, organisation, OrganisationRoles.linemanager);
+			listenTo(organisationListController);
+
+			String rootTitle = translate("admin.props.linemanagers");
+			String title = "Organisation";
+			TreeNode selTreeNode = TreeHelper.findNodeByUserObject(organisation, menu.getTreeModel().getRootNode());
+			if (selTreeNode != null) {
+				title = selTreeNode.getTitle();
+				if (!selTreeNode.getIdent().equals(menu.getSelectedNodeId())) {
+					menu.setSelectedNodeId(selTreeNode.getIdent());
+				}
+			}
+			content.rootController(rootTitle, null);
+			content.pushController(title, null, organisationListController);
+			content.setInvisibleCrumb(0);
+			addToHistory(ureq, organisationListController);
+
+			selectedController = organisationListController;
+		}
+
+		return (Activateable2) selectedController;
+	}
+
+	private Activateable2 selectMenuItem(UserRequest ureq, RelationRole relationRole) {
+		Controller selectedController = null;
+
+		if (securityModule.isRelationRoleEnabled()) {
+			OLATResourceable ores = OresHelper.createOLATResourceableInstance("Relations", relationRole.getKey());
+			ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
+			WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
+			AbstactCoachListController userRelationsListController = new UserRelationListController(ureq, bwControl, content, relationRole);
+			listenTo(userRelationsListController);
+
+			String rootTitle = translate("relations.menu.title");
+			String title = "Relation";
+			TreeNode selTreeNode = TreeHelper.findNodeByUserObject(relationRole, menu.getTreeModel().getRootNode());
+			if (selTreeNode != null) {
+				title = selTreeNode.getTitle();
+				if (!selTreeNode.getIdent().equals(menu.getSelectedNodeId())) {
+					menu.setSelectedNodeId(selTreeNode.getIdent());
+				}
+			}
+			content.rootController(rootTitle, null);
+			content.pushController(title, null, userRelationsListController);
+			content.setInvisibleCrumb(0);
+			addToHistory(ureq, userRelationsListController);
+
+			selectedController = userRelationsListController;
+		}
+
+		return (Activateable2) selectedController;
+	}
+
 	private TreeModel buildTreeModel() {
 		GenericTreeModel gtm = new GenericTreeModel();
 		GenericTreeNode root = new GenericTreeNode();
@@ -334,16 +440,17 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 			root.addChild(courses);
 		}
 
+		// Add user relations
 		// Add menu entry with sub entries
 		if (isUserRelationAvailable() == 2) {
 			GenericTreeNode relations = new GenericTreeNode();
-			relations.setUserObject("UserRelationsNode");
+			relations.setUserObject("Relations");
 			relations.setTitle(translate("relations.menu.title"));
 			relations.setAltText("relations.menu.title");
 
 			for (RelationRole relationRole : userRelationRolesMap.values()) {
 				GenericTreeNode relationRoleNode = new GenericTreeNode();
-				relationRoleNode.setUserObject(relationRole.getRole());
+				relationRoleNode.setUserObject(relationRole);
 				relationRoleNode.setTitle(RelationRolesAndRightsUIFactory.getTranslatedContraRole(relationRole, getLocale()));
 				relationRoleNode.setAltText(RelationRolesAndRightsUIFactory.getTranslatedContraDescription(relationRole, getLocale()));
 				relations.addChild(relationRoleNode);
@@ -356,13 +463,50 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 		else if (isUserRelationAvailable() == 1) {
 			for (RelationRole relationRole : userRelationRolesMap.values()) {
 				GenericTreeNode relationRoleNode = new GenericTreeNode();
-				relationRoleNode.setUserObject(relationRole.getRole());
+				relationRoleNode.setUserObject(relationRole);
 				relationRoleNode.setTitle(RelationRolesAndRightsUIFactory.getTranslatedContraRole(relationRole, getLocale()));
 				relationRoleNode.setAltText(RelationRolesAndRightsUIFactory.getTranslatedContraDescription(relationRole, getLocale()));
 				root.addChild(relationRoleNode);
 			}
 		}
 
+		// Add line manager view
+		// Add menu entry with sub entries
+		if (isLineManagerViewAvailable() == 2) {
+			GenericTreeNode organisationsNode = new GenericTreeNode();
+			organisationsNode.setUserObject("Organisations");
+			organisationsNode.setTitle(translate("line.manager.title"));
+			organisationsNode.setAltText(translate("line.manager.title"));
+
+			List<Organisation> topLevelOrganisations = new ArrayList<>();
+
+			for (Organisation organisation : organisations) {
+				if (organisation.getParent() == null && !topLevelOrganisations.contains(organisation)) {
+					topLevelOrganisations.add(organisation);
+				} else if (!organisations.contains(organisation.getParent())){
+					topLevelOrganisations.add(organisation);
+				}
+			}
+
+			if (!topLevelOrganisations.isEmpty()) {
+				for (Organisation topLevelOrganisation : topLevelOrganisations) {
+					addOrganisationToTree(topLevelOrganisation, organisationsNode);
+				}
+
+				setFirstChildAsDelegate(organisationsNode);
+				root.addChild(organisationsNode);
+			}
+		}
+		// Add only one main entry
+		else if (isLineManagerViewAvailable() == 1) {
+			GenericTreeNode organisationsNode = new GenericTreeNode();
+			organisationsNode.setUserObject(organisations.get(0));
+			organisationsNode.setTitle(translate(organisations.get(0).getDisplayName()));
+			organisationsNode.setAltText(translate(organisations.get(0).getDisplayName()));
+
+			root.addChild(organisationsNode);
+		}
+
 		if(gradingModule.isEnabled() && (gradingSec.isGrader() || gradingSec.isGradedResourcesManager())) {
 			GenericTreeNode courses = new GenericTreeNode();
 			courses.setUserObject("Grading");
@@ -381,6 +525,21 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 		return gtm;
 	}
 
+	private void addOrganisationToTree(Organisation organisation, GenericTreeNode parentNode) {
+		GenericTreeNode organisationNode = new GenericTreeNode();
+		organisationNode.setUserObject(organisation);
+		organisationNode.setTitle(organisation.getDisplayName());
+		organisationNode.setAltText(organisation.getDisplayName());
+
+		if (!organisation.getChildren().isEmpty()) {
+			for (Organisation child : organisation.getChildren()) {
+				addOrganisationToTree(child, organisationNode);
+			}
+		}
+
+		parentNode.addChild(organisationNode);
+	}
+
 	/**
 	 * Returns 0 if nothing is available
 	 * Returns 1 if exactly one role is available
@@ -399,6 +558,25 @@ public class CoachMainController extends MainLayoutBasicController implements Ac
 		return 0;
 	}
 
+	/**
+	 * Returns 0 if nothing is available
+	 * Returns 1 if exactly one organisation is available
+	 * Returns 2 if more than one organisation is available
+	 *
+	 * @return
+	 */
+	private int isLineManagerViewAvailable() {
+		if (showLineManagerView) {
+			if (organisations.size() > 1) {
+				return 2;
+			} else if (organisations.size() > 0) {
+				return 1;
+			}
+		}
+
+		return 0;
+	}
+
 	/**
 	 * Returns different roles for a given list of relations
 	 *
diff --git a/src/main/java/org/olat/modules/coach/ui/UserRelationEnrollmentListController.java b/src/main/java/org/olat/modules/coach/ui/EnrollmentListController.java
similarity index 91%
rename from src/main/java/org/olat/modules/coach/ui/UserRelationEnrollmentListController.java
rename to src/main/java/org/olat/modules/coach/ui/EnrollmentListController.java
index 58e959e00daf05eea573afe509e9cdc1c5c2380a..1178fbfe13ecf2300b41d0a138ab500885e5b6f9 100644
--- a/src/main/java/org/olat/modules/coach/ui/UserRelationEnrollmentListController.java
+++ b/src/main/java/org/olat/modules/coach/ui/EnrollmentListController.java
@@ -62,7 +62,7 @@ import org.olat.modules.assessment.ui.ScoreCellRenderer;
 import org.olat.modules.assessment.ui.component.LearningProgressCompletionCellRenderer;
 import org.olat.modules.co.ContactFormController;
 import org.olat.modules.coach.CoachingService;
-import org.olat.modules.coach.UserRelationSecurityCallback;
+import org.olat.modules.coach.RoleSecurityCallback;
 import org.olat.modules.coach.model.EfficiencyStatementEntry;
 import org.olat.modules.coach.model.IdentityRepositoryEntryKey;
 import org.olat.modules.coach.model.IdentityResourceKey;
@@ -87,12 +87,12 @@ import org.springframework.beans.factory.annotation.Autowired;
  *
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
-public class UserRelationEnrollmentListController extends FormBasicController implements Activateable2, GenericEventListener {
+public class EnrollmentListController extends FormBasicController implements Activateable2, GenericEventListener {
 
 	private final TooledStackedPanel stackedPanel;
 	private final Identity student;
 	private final StudentStatEntry statEntry;
-	private final UserRelationSecurityCallback userRelationSecurityCallback;
+	private final RoleSecurityCallback roleSecurityCallback;
 
 	private final List<UserPropertyHandler> userPropertyHandlers;
 
@@ -120,8 +120,8 @@ public class UserRelationEnrollmentListController extends FormBasicController im
 	@Autowired
 	private AssessmentService assessmentService;
 
-	public UserRelationEnrollmentListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackedPanel,
-												StudentStatEntry statEntry, Identity student, UserRelationSecurityCallback userRelationSecurityCallback) {
+	public EnrollmentListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackedPanel,
+									StudentStatEntry statEntry, Identity student, RoleSecurityCallback roleSecurityCallback) {
 		super(ureq, wControl, "user_relation_enrollments");
 		
 		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
@@ -131,7 +131,7 @@ public class UserRelationEnrollmentListController extends FormBasicController im
 		this.student = student;
 		this.statEntry = statEntry;
 		this.stackedPanel = stackedPanel;
-		this.userRelationSecurityCallback = userRelationSecurityCallback;
+		this.roleSecurityCallback = roleSecurityCallback;
 		
 		initForm(ureq);
 		loadModel();
@@ -144,32 +144,25 @@ public class UserRelationEnrollmentListController extends FormBasicController im
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
 		// Add the table
 		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
-
-		int colIndex = UserListController.USER_PROPS_OFFSET;
-		for (int i = 0; i < userPropertyHandlers.size(); i++) {
-			UserPropertyHandler userPropertyHandler	= userPropertyHandlers.get(i);
-			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex++, "select",
-					true, userPropertyHandler.i18nColumnDescriptorLabelKey()));
-		}
 		
 		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.repoName, "select"));
-		if (userRelationSecurityCallback.canViewCourseProgressAndStatus()) {
+		if (roleSecurityCallback.canViewCourseProgressAndStatus()) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.completion, new LearningProgressCompletionCellRenderer()));
 		}
-		if (userRelationSecurityCallback.canViewEfficiencyStatements()) {
+		if (roleSecurityCallback.canViewEfficiencyStatements()) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.passed, new PassedCellRenderer()));
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.score, new ScoreCellRenderer()));
 		}
-		if (userRelationSecurityCallback.canReceiveCertificatesMail()) {
+		if (roleSecurityCallback.canReceiveCertificatesMail()) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.certificate, new DownloadCertificateCellRenderer(getLocale())));
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.recertification, new DateFlexiCellRenderer(getLocale())));
 		}
 
-		if (userRelationSecurityCallback.canViewEfficiencyStatements()) {
+		if (roleSecurityCallback.canViewEfficiencyStatements()) {
 			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.numberAssessments, new ProgressOfCellRenderer()));
 		}
 		if(lectureModule.isEnabled()) {
-			if (userRelationSecurityCallback.canViewLecturesAndAbsences()) {
+			if (roleSecurityCallback.canViewLecturesAndAbsences()) {
 				columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.plannedLectures));
 				columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.attendedLectures));
 				if (lectureModule.isAuthorizedAbsenceEnabled()) {
diff --git a/src/main/java/org/olat/modules/coach/ui/UserRelationOverviewController.java b/src/main/java/org/olat/modules/coach/ui/UserOverviewController.java
similarity index 86%
rename from src/main/java/org/olat/modules/coach/ui/UserRelationOverviewController.java
rename to src/main/java/org/olat/modules/coach/ui/UserOverviewController.java
index 39ca41f590d1ab827eac424eb2b0dd601a1d7d56..aa4e09a2c21e4acd0fda3ad84279d327da2ef2be 100644
--- a/src/main/java/org/olat/modules/coach/ui/UserRelationOverviewController.java
+++ b/src/main/java/org/olat/modules/coach/ui/UserOverviewController.java
@@ -26,7 +26,6 @@ import org.olat.admin.user.UserChangePasswordController;
 import org.olat.admin.user.UserShortDescription;
 import org.olat.admin.user.groups.GroupOverviewController;
 import org.olat.basesecurity.BaseSecurityManager;
-import org.olat.basesecurity.RelationRole;
 import org.olat.commons.calendar.CalendarManager;
 import org.olat.commons.calendar.model.CalendarUserConfiguration;
 import org.olat.commons.calendar.ui.CalendarController;
@@ -63,9 +62,10 @@ import org.olat.core.util.resource.OresHelper;
 import org.olat.course.certificate.CertificatesManager;
 import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListController;
 import org.olat.modules.co.ContactFormController;
-import org.olat.modules.coach.UserRelationSecurityCallback;
+import org.olat.modules.coach.RoleSecurityCallback;
 import org.olat.modules.coach.model.StudentStatEntry;
-import org.olat.modules.coach.ui.curriculum.CourseListWrapperController;
+import org.olat.modules.coach.ui.curriculum.certificate.CertificateAndEfficiencyStatementWrapperController;
+import org.olat.modules.coach.ui.curriculum.course.CourseListWrapperController;
 import org.olat.modules.curriculum.CurriculumRef;
 import org.olat.modules.curriculum.CurriculumSecurityCallback;
 import org.olat.modules.curriculum.CurriculumSecurityCallbackFactory;
@@ -79,7 +79,6 @@ import org.olat.user.HomePageConfigManager;
 import org.olat.user.HomePageDisplayController;
 import org.olat.user.ProfileAndHomePageEditController;
 import org.olat.user.UserManager;
-import org.olat.user.ui.role.RelationRolesAndRightsUIFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -89,9 +88,9 @@ import org.springframework.beans.factory.annotation.Autowired;
  *
  * @author aboeckle, alexander.boeckle@frentix.com, http://www.frentix.com
  */
-public class UserRelationOverviewController extends BasicController implements Activateable2, GenericEventListener, TooledController {
+public class UserOverviewController extends BasicController implements Activateable2, GenericEventListener, TooledController {
 
-	public static final String usageIdentifier = UserRelationOverviewController.class.getCanonicalName();
+	public static final String usageIdentifier = UserOverviewController.class.getCanonicalName();
 
 	private static final String CMD_CALENDAR = "Calendar";
 	private static final String CMD_BOOKINGS = "Bookings";
@@ -130,6 +129,7 @@ public class UserRelationOverviewController extends BasicController implements A
 	private CertificateAndEfficiencyStatementListController efficiencyStatementListController;
 	private WeeklyCalendarController calendarController;
 	private CourseListWrapperController courseListWrapperController;
+	private CertificateAndEfficiencyStatementWrapperController certificateAndEfficiencyStatementWrapperController;
 
 	private TabbedPane functionsTabbedPane;
 
@@ -137,9 +137,9 @@ public class UserRelationOverviewController extends BasicController implements A
 	private final int numOfStudents;
 	private final Identity mentee;
 	private final StudentStatEntry statEntry;
-	private final RelationRole relationRole;
+	private final String role;
 
-	private final UserRelationSecurityCallback userRelationSecurityCallback;
+	private final RoleSecurityCallback roleSecurityCallback;
 
 	@Autowired
 	private UserManager userManager;
@@ -154,8 +154,8 @@ public class UserRelationOverviewController extends BasicController implements A
 	@Autowired
 	private CurriculumService curriculumService;
 
-	public UserRelationOverviewController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
-										  StudentStatEntry statEntry, Identity mentee, int index, int numOfStudents, RelationRole relationRole, UserRelationSecurityCallback userRelationSecurityCallback) {
+	public UserOverviewController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
+								  StudentStatEntry statEntry, Identity mentee, int index, int numOfStudents, String role, RoleSecurityCallback roleSecurityCallback) {
 		super(ureq, wControl);
 		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
 
@@ -164,8 +164,8 @@ public class UserRelationOverviewController extends BasicController implements A
 		this.statEntry = statEntry;
 		this.stackPanel = stackPanel;
 		this.numOfStudents = numOfStudents;
-		this.userRelationSecurityCallback = userRelationSecurityCallback;
-		this.relationRole = relationRole;
+		this.roleSecurityCallback = roleSecurityCallback;
+		this.role = role;
 
 		mainVC = createVelocityContainer("user_relation_overview");
 
@@ -177,7 +177,7 @@ public class UserRelationOverviewController extends BasicController implements A
 
 	@Override
 	public void initTools() {
-		if (userRelationSecurityCallback.canContact()) {
+		if (roleSecurityCallback.canContact()) {
 			contactLink = LinkFactory.createToolLink("contact.link", translate("contact.link"), this);
 			contactLink.setIconLeftCSS("o_icon o_icon_mail");
 			stackPanel.addTool(contactLink, Align.left, true);
@@ -187,7 +187,7 @@ public class UserRelationOverviewController extends BasicController implements A
 		homeLink.setIconLeftCSS("o_icon o_icon_home");
 		stackPanel.addTool(homeLink, Align.left, true);
 
-		if (userRelationSecurityCallback.canResetPassword()) {
+		if (roleSecurityCallback.canResetPassword()) {
 			Roles roles = securityManager.getRoles(mentee);
 			if (!(roles.isAuthor() || roles.isManager() || roles.isAdministrator() || roles.isSystemAdmin() || roles.isPrincipal())) {
 				resetLink = LinkFactory.createToolLink("reset.link", translate("reset.link"), this);
@@ -219,7 +219,7 @@ public class UserRelationOverviewController extends BasicController implements A
 	private void initUserDetails(UserRequest ureq, Identity identity) {
 		// Add user's name and relation
 		StringBuilder relationAndName = new StringBuilder(256);
-		relationAndName.append(RelationRolesAndRightsUIFactory.getTranslatedContraRole(relationRole, getLocale())).append(" ");
+		relationAndName.append(role != null ? role + " " : "");
 		relationAndName.append(mentee.getUser().getFirstName()).append(" ");
 		relationAndName.append(mentee.getUser().getLastName());
 		mainVC.contextPut("relationAndName", relationAndName);
@@ -237,7 +237,7 @@ public class UserRelationOverviewController extends BasicController implements A
 		userDetails.put("portrait", displayPortraitController.getInitialComponent());
 
 		removeAsListenerAndDispose(userShortDescriptionController);
-		userShortDescriptionController = new UserShortDescription(ureq, getWindowControl(), identity, userRelationSecurityCallback.isAdministrativeUser());
+		userShortDescriptionController = new UserShortDescription(ureq, getWindowControl(), identity, roleSecurityCallback.isAdministrativeUser());
 		userDetails.put("userShortDescription", userShortDescriptionController.getInitialComponent());
 	}
 	
@@ -247,19 +247,19 @@ public class UserRelationOverviewController extends BasicController implements A
 		functionsTabbedPane = new TabbedPane("functionsTabbedPane", ureq.getLocale());
 		functionsTabbedPane.addListener(this);
 
-		if (userRelationSecurityCallback.canViewCoursesAndCurriculum()) {
+		if (roleSecurityCallback.canViewCoursesAndCurriculum()) {
 			List<CurriculumRef> curriculumRefs = curriculumService.getMyActiveCurriculumRefs(mentee);
 			CurriculumSecurityCallback curriculumSecurityCallback = CurriculumSecurityCallbackFactory.createDefaultCallback();
 
 			courseTabIndex = functionsTabbedPane.addTabControllerCreator(ureq, translate("enrollments"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_ENROLLMENTS), null);
-				courseListWrapperController = new CourseListWrapperController(uureq, bwControl, stackPanel, mentee, curriculumSecurityCallback, userRelationSecurityCallback, curriculumRefs, statEntry);
+				courseListWrapperController = new CourseListWrapperController(uureq, bwControl, stackPanel, mentee, curriculumSecurityCallback, roleSecurityCallback, curriculumRefs, statEntry);
 				listenTo(courseListWrapperController);
 				return courseListWrapperController;
 			});
 		}
 
-		if (userRelationSecurityCallback.canViewResourcesAndBookings()) {
+		if (roleSecurityCallback.canViewResourcesAndBookings()) {
 			orderTabIndex = functionsTabbedPane.addTabControllerCreator(ureq, translate("bookings"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_BOOKINGS), null);
 				userOrderController = new UserOrderController(uureq, bwControl, mentee);
@@ -268,7 +268,7 @@ public class UserRelationOverviewController extends BasicController implements A
 			});
 		}
 
-		if (lectureModule.isEnabled() && userRelationSecurityCallback.canViewLecturesAndAbsences()) {
+		if (lectureModule.isEnabled() && roleSecurityCallback.canViewLecturesAndAbsences()) {
 			lecturesTabIndex = functionsTabbedPane.addTabControllerCreator(ureq, translate("lectures"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_LECTURES), null);
 				lecturesController = new ParticipantLecturesOverviewController(uureq, bwControl, mentee, null, true, true, true, true, false, true);
@@ -278,17 +278,19 @@ public class UserRelationOverviewController extends BasicController implements A
 			});
 		}
 
-		if (userRelationSecurityCallback.canViewEfficiencyStatements()) {
+		if (roleSecurityCallback.canViewEfficiencyStatements()) {
+			List<CurriculumRef> curriculumRefs = curriculumService.getMyActiveCurriculumRefs(mentee);
+			CurriculumSecurityCallback curriculumSecurityCallback = CurriculumSecurityCallbackFactory.createDefaultCallback();
+
 			certificatesTabIndex = functionsTabbedPane.addTabControllerCreator(ureq, translate("statements"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_STATEMENTS), null);
-				efficiencyStatementListController = new CertificateAndEfficiencyStatementListController(ureq, bwControl, mentee, true);
-				efficiencyStatementListController.setBreadcrumbPanel(stackPanel);
-				listenTo(efficiencyStatementListController);
-				return efficiencyStatementListController;
+				certificateAndEfficiencyStatementWrapperController = new CertificateAndEfficiencyStatementWrapperController(uureq, bwControl, stackPanel, mentee, curriculumSecurityCallback, roleSecurityCallback, curriculumRefs, statEntry);
+				listenTo(certificateAndEfficiencyStatementWrapperController);
+				return certificateAndEfficiencyStatementWrapperController;
 			});
 		}
 
-		if (userRelationSecurityCallback.canViewGroupMemberships()) {
+		if (roleSecurityCallback.canViewGroupMemberships()) {
 			groupTabIndex = functionsTabbedPane.addTab(ureq, translate("groups.menu.title"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_GROUPS), null);
 				groupOverviewController = new GroupOverviewController(ureq, bwControl, mentee, false, false);
@@ -297,14 +299,14 @@ public class UserRelationOverviewController extends BasicController implements A
 			});
 		}
 
-		if (userRelationSecurityCallback.canViewCalendar()) {
+		if (roleSecurityCallback.canViewCalendar()) {
 			calendarTabIndex = functionsTabbedPane.addTab(ureq, translate("calendar"), uureq -> doOpenCalendar(uureq).getInitialComponent());
 		}
 
-		if (userRelationSecurityCallback.canViewAndEditProfile()) {
+		if (roleSecurityCallback.canViewAndEditProfile()) {
 			profileTabIndex = functionsTabbedPane.addTab(ureq, translate("profile"), uureq -> {
 				WindowControl bwControl = addToHistory(uureq, OresHelper.createOLATResourceableType(CMD_PROFILE), null);
-				profileAndHomePageEditController =  new ProfileAndHomePageEditController(ureq, bwControl, mentee, userRelationSecurityCallback.isAdministrativeUser());
+				profileAndHomePageEditController =  new ProfileAndHomePageEditController(ureq, bwControl, mentee, roleSecurityCallback.isAdministrativeUser());
 				listenTo(profileAndHomePageEditController);
 				return profileAndHomePageEditController.getInitialComponent();
 			});
@@ -398,6 +400,9 @@ public class UserRelationOverviewController extends BasicController implements A
 			}
 		} else if(CMD_STATEMENTS.equalsIgnoreCase(type) && certificatesTabIndex >= 0) {
 			functionsTabbedPane.setSelectedPane(ureq, certificatesTabIndex);
+			if (certificateAndEfficiencyStatementWrapperController != null) {
+				certificateAndEfficiencyStatementWrapperController.activate(ureq, entries.subList(1, entries.size()), null);
+			}
 		} else if(CMD_GROUPS.equalsIgnoreCase(type) && groupTabIndex >= 0) {
 			functionsTabbedPane.setSelectedPane(ureq, groupTabIndex);
 		} else if(CMD_PROFILE.equalsIgnoreCase(type) && profileTabIndex >= 0) {
@@ -432,12 +437,14 @@ public class UserRelationOverviewController extends BasicController implements A
 	}
 
 	private void openHome(UserRequest ureq) {
-		HomePageConfig homePageConfig = homePageConfigManager.loadConfigFor(mentee);
-		removeAsListenerAndDispose(homePageDisplayController);
-		homePageDisplayController = new HomePageDisplayController(ureq, getWindowControl(), mentee, homePageConfig);
-		listenTo(homePageDisplayController);
+		if (stackPanel.getLastController() != homePageDisplayController) {
+			HomePageConfig homePageConfig = homePageConfigManager.loadConfigFor(mentee);
+			removeAsListenerAndDispose(homePageDisplayController);
+			homePageDisplayController = new HomePageDisplayController(ureq, getWindowControl(), mentee, homePageConfig);
+			listenTo(homePageDisplayController);
 
-		stackPanel.pushController("Visiting card", homePageDisplayController);
+			stackPanel.pushController("Visiting card", homePageDisplayController);
+		}
 	}
 
 	private WeeklyCalendarController doOpenCalendar(UserRequest ureq) {
diff --git a/src/main/java/org/olat/modules/coach/ui/UserRelationListController.java b/src/main/java/org/olat/modules/coach/ui/UserRelationListController.java
index f8abfec6e0f511ab860a6b0d52342e66b97cfaf3..f6d2808df1fbc8fc1aed9e801611c58ee11f1525 100644
--- a/src/main/java/org/olat/modules/coach/ui/UserRelationListController.java
+++ b/src/main/java/org/olat/modules/coach/ui/UserRelationListController.java
@@ -21,244 +21,62 @@ package org.olat.modules.coach.ui;
 
 import java.util.List;
 
-import org.olat.basesecurity.BaseSecurity;
-import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.RelationRole;
 import org.olat.core.gui.UserRequest;
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.form.flexible.FormItem;
-import org.olat.core.gui.components.form.flexible.FormItemContainer;
-import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
-import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
-import org.olat.core.gui.components.form.flexible.impl.FormEvent;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.*;
-import org.olat.core.gui.components.stack.PopEvent;
 import org.olat.core.gui.components.stack.TooledStackedPanel;
-import org.olat.core.gui.control.Controller;
-import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
-import org.olat.core.id.context.ContextEntry;
-import org.olat.core.id.context.StateEntry;
-import org.olat.core.util.UserSession;
 import org.olat.core.util.resource.OresHelper;
-import org.olat.modules.assessment.ui.component.LearningProgressCompletionCellRenderer;
 import org.olat.modules.coach.CoachingService;
-import org.olat.modules.coach.UserRelationSecurityCallback;
 import org.olat.modules.coach.model.StudentStatEntry;
-import org.olat.modules.coach.security.UserRelationSecurityCallbackFactory;
-import org.olat.modules.coach.ui.StudentsTableDataModel.Columns;
-import org.olat.user.UserManager;
-import org.olat.user.propertyhandlers.UserPropertyHandler;
+import org.olat.modules.coach.security.RoleSecurityCallbackFactory;
+import org.olat.user.ui.role.RelationRolesAndRightsUIFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * Initial date: 25 May 2020<br>
  * @author aboeckle, alexander.boeckle@frentix.com
  */
-public class UserRelationListController extends FormBasicController implements Activateable2 {
+public class UserRelationListController extends AbstactCoachListController implements Activateable2 {
 
-    private final boolean isAdministrativeUser;
-    private final List<UserPropertyHandler> userPropertyHandlers;
-
-    private final TooledStackedPanel stackPanel;
-    private final RelationRole relationRole;
-    private final UserRelationSecurityCallback securityCallback;
-
-    private boolean hasChanged;
-
-    private FlexiTableElement tableEl;
-    private StudentsTableDataModel model;
-
-    private UserRelationOverviewController userCtrl;
-
-    @Autowired
-    private UserManager userManager;
-    @Autowired
-    private BaseSecurity securityManager;
-    @Autowired
-    private BaseSecurityModule securityModule;
     @Autowired
     private CoachingService coachingService;
     @Autowired
     private IdentityRelationshipService identityRelationshipService;
 
-    public UserRelationListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, RelationRole relationRole) {
-        super(ureq, wControl, LAYOUT_BAREBONE);
+    private RelationRole relationRole;
 
-        setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
-        isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
-        userPropertyHandlers = userManager.getUserPropertyHandlersFor(UserListController.usageIdentifyer, isAdministrativeUser);
+    public UserRelationListController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, RelationRole relationRole) {
+        super(ureq, wControl, stackPanel);
 
-        this.stackPanel = stackPanel;
-        this.stackPanel.setInvisibleCrumb(0);
-        stackPanel.addListener(this);
         this.relationRole = identityRelationshipService.getRole(relationRole.getKey());
-        this.securityCallback = UserRelationSecurityCallbackFactory.create(this.relationRole.getRights());
+        this.securityCallback = RoleSecurityCallbackFactory.create(this.relationRole.getRights());
 
-        initForm(ureq);
+        super.initForm(ureq);
         loadModel();
     }
 
     @Override
-    protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-        //add the table
-        FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
-
-        int colIndex = UserListController.USER_PROPS_OFFSET;
-        for (int i = 0; i < userPropertyHandlers.size(); i++) {
-            UserPropertyHandler userPropertyHandler = userPropertyHandlers.get(i);
-            boolean visible = userManager.isMandatoryUserProperty(UserListController.usageIdentifyer, userPropertyHandler);
-            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colIndex++, "select",
-                    true, userPropertyHandler.i18nColumnDescriptorLabelKey()));
-        }
-
-        if (securityCallback.canViewCoursesAndCurriculum()) {
-            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.countCourse));
-            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.initialLaunch, new LightIconRenderer()));
-        }
-
-        if (securityCallback.canViewCourseProgressAndStatus()) {
-            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.completion, new LearningProgressCompletionCellRenderer()));
-            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(Columns.countPassed, new ProgressOfCellRenderer()));
-        }
-
-        model = new StudentsTableDataModel(columnsModel);
-        tableEl = uifactory.addTableElement(getWindowControl(), "table", model, 20, false, getTranslator(), formLayout);
-        tableEl.setExportEnabled(true);
-        tableEl.setEmtpyTableMessageKey("error.no.found");
-        tableEl.setAndLoadPersistedPreferences(ureq, "UserRelationsListController");
-
-        UserSession usess = ureq.getUserSession();
-        boolean autoCompleteAllowed = securityModule.isUserAllowedAutoComplete(usess.getRoles());
-        if (autoCompleteAllowed) {
-            tableEl.setSearchEnabled(new StudentListProvider(model, userManager), usess);
-        }
-    }
-
-    @Override
-    protected void doDispose() {
-        stackPanel.removeListener(this);
-    }
-
-    @Override
-    protected void formOK(UserRequest ureq) {
-        //
-    }
-
-    @Override
-    protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
-        if (tableEl == source) {
-            if (event instanceof SelectionEvent) {
-                SelectionEvent se = (SelectionEvent) event;
-                String cmd = se.getCommand();
-                StudentStatEntry selectedRow = model.getObject(se.getIndex());
-                if ("select".equals(cmd)) {
-                    selectStudent(ureq, selectedRow);
-                }
-            } else if (event instanceof FlexiTableSearchEvent) {
-                FlexiTableSearchEvent ftse = (FlexiTableSearchEvent) event;
-                String searchString = ftse.getSearch();
-                model.search(searchString);
-                tableEl.reset();
-                tableEl.reloadData();
-            }
-        }
-        super.formInnerEvent(ureq, source, event);
-    }
-
-    private void loadModel() {
+    protected void loadModel() {
         List<StudentStatEntry> students = coachingService.getUserStatistics(getIdentity(), relationRole, userPropertyHandlers, getLocale());
         model.setObjects(students);
         tableEl.reset();
         tableEl.reloadData();
     }
 
-    private void reloadModel() {
-        if (hasChanged) {
-            loadModel();
-            hasChanged = false;
-        }
-    }
-
-    @Override
-    protected void event(UserRequest ureq, Controller source, Event event) {
-        if (source == userCtrl) {
-            if (event == Event.CHANGED_EVENT) {
-                hasChanged = true;
-            } else if ("next.student".equals(event.getCommand())) {
-                nextStudent(ureq);
-            } else if ("previous.student".equals(event.getCommand())) {
-                previousStudent(ureq);
-            }
-        }
-        super.event(ureq, source, event);
-    }
-
-    @Override
-    public void event(UserRequest ureq, Component source, Event event) {
-        if (stackPanel == source) {
-            if (event instanceof PopEvent) {
-                PopEvent pe = (PopEvent) event;
-                if (pe.getController() == this.userCtrl && hasChanged) {
-                    reloadModel();
-                }
-            }
-        }
-        super.event(ureq, source, event);
-    }
-
-    @Override
-    public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
-        if (entries == null || entries.isEmpty()) return;
-
-        ContextEntry ce = entries.get(0);
-        OLATResourceable ores = ce.getOLATResourceable();
-        if ("Identity".equals(ores.getResourceableTypeName())) {
-            Long identityKey = ores.getResourceableId();
-            for (StudentStatEntry entry : model.getObjects()) {
-                if (identityKey.equals(entry.getIdentityKey())) {
-                    Activateable2 selectedCtrl = selectStudent(ureq, entry);
-                    selectedCtrl.activate(ureq, entries.subList(1, entries.size()), ce.getTransientState());
-                    break;
-                }
-            }
-        }
-    }
-
-    protected void previousStudent(UserRequest ureq) {
-        StudentStatEntry currentEntry = userCtrl.getEntry();
-        int previousIndex = model.getObjects().indexOf(currentEntry) - 1;
-        if (previousIndex < 0 || previousIndex >= model.getRowCount()) {
-            previousIndex = model.getRowCount() - 1;
-        }
-        StudentStatEntry previousEntry = model.getObject(previousIndex);
-        selectStudent(ureq, previousEntry);
-    }
-
-    protected void nextStudent(UserRequest ureq) {
-        StudentStatEntry currentEntry = userCtrl.getEntry();
-        int nextIndex = model.getObjects().indexOf(currentEntry) + 1;
-        if (nextIndex < 0 || nextIndex >= model.getRowCount()) {
-            nextIndex = 0;
-        }
-        StudentStatEntry nextEntry = model.getObject(nextIndex);
-        selectStudent(ureq, nextEntry);
-    }
-
-    protected UserRelationOverviewController selectStudent(UserRequest ureq, StudentStatEntry studentStat) {
+    protected UserOverviewController selectStudent(UserRequest ureq, StudentStatEntry studentStat) {
         Identity student = securityManager.loadIdentityByKey(studentStat.getIdentityKey());
         OLATResourceable ores = OresHelper.createOLATResourceableInstance(Identity.class, student.getKey());
         WindowControl bwControl = addToHistory(ureq, ores, null);
 
         int index = model.getObjects().indexOf(studentStat);
-        userCtrl = new UserRelationOverviewController(ureq, bwControl, stackPanel, studentStat, student, index, model.getRowCount(), relationRole, securityCallback);
+        String roleTranslation = RelationRolesAndRightsUIFactory.getTranslatedContraRole(relationRole, getLocale());
+        userCtrl = new UserOverviewController(ureq, bwControl, stackPanel, studentStat, student, index, model.getRowCount(), roleTranslation, securityCallback);
         listenTo(userCtrl);
 
-        stackPanel.popUpToRootController(ureq);
         String displayName = userManager.getUserDisplayName(student);
         stackPanel.pushController(displayName, userCtrl);
         return userCtrl;
diff --git a/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_de.properties
index 2416d91cced22c3b9152f2e99fa6b98659020e80..752ccc07b60789017b73a94fd89e0d5b0d8ed22f 100644
--- a/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_de.properties
@@ -27,6 +27,7 @@ lectures.teacher.menu.title=Lektionen
 lectures.teacher.menu.title.alt=Lektionen und Absenzmanagement
 home.link=Visitenkarte
 lectures=Lektionen \uFF06 Abwesenheiten
+line.manager.title=$org.olat.admin.user\:role.linemanager
 main.menu.title.alt=\$:site.title.alt
 main.menu.title=\$:site.title
 menu.coaching.alt=\$:site.title.alt
diff --git a/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_en.properties
index 4c41afe4c892b92616020620acc72cc740c52397..f4da3e3a1e103ed981fe5ce7529ceefca8408dc8 100644
--- a/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/coach/ui/_i18n/LocalStrings_en.properties
@@ -27,6 +27,7 @@ lectures.mastercoach.menu.title=Classes
 lectures.mastercoach.menu.title.alt=Management of absences and lectures in classes
 lectures.teacher.menu.title=Lectures
 lectures.teacher.menu.title.alt=Lectures and absences management
+line.manager.title=$org.olat.admin.user\:roles.linemanager
 main.menu.title=$\:site.title
 main.menu.title.alt=$\:site.title.alt
 menu.coaching=$\:site.title
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsDataModel.java b/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsDataModel.java
deleted file mode 100644
index cee9015ab2644895dd55c2cbe6a936d87e324948..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsDataModel.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
- * <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.modules.coach.ui.curriculum;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTreeTableDataModel;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiBusinessPathModel;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
-import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
-import org.olat.modules.curriculum.CurriculumElementStatus;
-
-/**
- * 
- * Initial date: 11 mai 2018<br>
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- *
- */
-public class CurriculumElementWithViewsDataModel extends DefaultFlexiTreeTableDataModel<CurriculumElementWithViewsRow> implements FlexiBusinessPathModel {
-	
-	public CurriculumElementWithViewsDataModel(FlexiTableColumnModel columnsModel) {
-		super(columnsModel);
-	}
-	
-	@Override
-	public void filter(String searchString, List<FlexiTableFilter> filters) {
-		if(filters != null && !filters.isEmpty() && filters.get(0) != null) {
-			FlexiTableFilter filter = filters.get(0);
-			if(filter == null || filter.isShowAll()) {
-				setUnfilteredObjects();
-			} else {
-				List<CurriculumElementWithViewsRow> filteredRows = new ArrayList<>(backupRows.size());
-				// curriculum element inactive -> all repo are inactives
-				// parent inactive, child is active -> parent is forced active
-				for(CurriculumElementWithViewsRow row:backupRows) {
-					boolean accept = active(row);
-					if(accept) {
-						filteredRows.add(row);
-					}
-				}
-				setFilteredObjects(filteredRows);
-			}
-		} else {
-			setUnfilteredObjects();
-		}
-	}
-	
-	private boolean active(CurriculumElementWithViewsRow row) {
-		boolean active = true;
-		if(row.isCurriculumElementOnly() || row.isCurriculumElementWithEntry()) {
-			active = row.getCurriculumElementStatus() == CurriculumElementStatus.active;
-		}
-		if(active) {
-			for(CurriculumElementWithViewsRow parent = row.getParent(); parent != null; parent=parent.getParent()) {
-				if(parent.isCurriculumElementOnly() || parent.isCurriculumElementWithEntry()) {
-					active &= row.getCurriculumElementStatus() == CurriculumElementStatus.active;
-				}
-			}
-		}
-		return active;
-	}
-	
-	@Override
-	public boolean hasChildren(int row) {
-		CurriculumElementWithViewsRow element = getObject(row);
-		return element.hasChildren();
-	}
-
-	@Override
-	public Object getValueAt(int row, int col) {
-		CurriculumElementWithViewsRow curriculum = getObject(row);
-		switch(ElementViewCols.values()[col]) {
-			case key: return curriculum.getKey();
-			case displayName: {
-				String displayName;
-				if(curriculum.isRepositoryEntryOnly()) {
-					displayName = curriculum.getRepositoryEntryDisplayName();
-				} else {
-					displayName = curriculum.getCurriculumElementDisplayName();
-				}
-				return displayName;
-			}
-			case identifier: {
-				String identifier;
-				if(curriculum.isRepositoryEntryOnly()) {
-					identifier = curriculum.getRepositoryEntryExternalRef();
-				} else {
-					identifier = curriculum.getCurriculumElementIdentifier();
-				}
-				return identifier;
-			}
-			case mark: return curriculum.getMarkLink();
-			case select: return curriculum.getSelectLink();
-			case details: return curriculum.getDetailsLink();
-			case start: return curriculum.getStartLink();
-			case calendars: return curriculum.getCalendarsLink();
-			case completion: return curriculum.getCompletionItem();
-			default: return "ERROR";
-		}
-	}
-
-	@Override
-	public CurriculumElementWithViewsDataModel createCopyWithEmptyList() {
-		return new CurriculumElementWithViewsDataModel(getTableColumnModel());
-	}
-
-	public enum ElementViewCols implements FlexiSortableColumnDef {
-		key("table.header.key"),
-		displayName("table.header.curriculum.element.displayName"),
-		identifier("table.header.curriculum.element.identifier"),
-		mark("table.header.mark"),
-		select("table.header.displayName"),
-		completion("table.header.completion"),
-		details("table.header.details"),
-		start("table.header.start"),
-		calendars("table.header.calendars");
-		
-		private final String i18nHeaderKey;
-		
-		private ElementViewCols(String i18nHeaderKey) {
-			this.i18nHeaderKey = i18nHeaderKey;
-		}
-
-		@Override
-		public boolean sortable() {
-			return false;
-		}
-
-		@Override
-		public String sortKey() {
-			return name();
-		}
-
-		@Override
-		public String i18nHeaderKey() {
-			return i18nHeaderKey;
-		}
-	}
-
-	@Override
-	public String getUrl(Component source, Object object, String action) {
-		if("select".equals(action) && object instanceof CurriculumElementWithViewsRow) {
-			CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow)object;
-			if(row.getStartUrl() != null) {
-				return row.getStartUrl();
-			}
-			if(row.getDetailsUrl() != null) {
-				return row.getDetailsUrl();
-			}
-		}
-		return null;
-	}
-}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementCurriculumListController.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementCurriculumListController.java
new file mode 100644
index 0000000000000000000000000000000000000000..47dd35c979488c2b357c6ce16493dbbee83e26b8
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementCurriculumListController.java
@@ -0,0 +1,901 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.olat.NewControllerFactory;
+import org.olat.basesecurity.BaseSecurity;
+import org.olat.core.commons.services.mark.Mark;
+import org.olat.core.commons.services.mark.MarkManager;
+import org.olat.core.dispatcher.mapper.MapperService;
+import org.olat.core.dispatcher.mapper.manager.MapperKey;
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.FormItemContainer;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.BooleanCellRenderer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponentDelegate;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableCssDelegate;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableRendererType;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.TreeNodeFlexiCellRenderer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.progressbar.ProgressBar.BarColor;
+import org.olat.core.gui.components.progressbar.ProgressBar.LabelAlignment;
+import org.olat.core.gui.components.progressbar.ProgressBar.RenderSize;
+import org.olat.core.gui.components.progressbar.ProgressBar.RenderStyle;
+import org.olat.core.gui.components.progressbar.ProgressBarItem;
+import org.olat.core.gui.components.stack.BreadcrumbPanel;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.id.Roles;
+import org.olat.core.id.context.BusinessControlFactory;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.Util;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.core.util.vfs.VFSLeaf;
+import org.olat.course.CorruptedCourseException;
+import org.olat.course.assessment.AssessmentModule;
+import org.olat.course.assessment.manager.EfficiencyStatementManager;
+import org.olat.course.assessment.model.UserEfficiencyStatementLight;
+import org.olat.course.certificate.CertificateLight;
+import org.olat.course.certificate.CertificatesManager;
+import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListController;
+import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListModel;
+import org.olat.modules.assessment.AssessmentEntryCompletion;
+import org.olat.modules.assessment.AssessmentService;
+import org.olat.modules.coach.RoleSecurityCallback;
+import org.olat.modules.coach.ui.curriculum.certificate.CurriculumElementWithViewsDataModel.ElementViewCols;
+import org.olat.modules.curriculum.Curriculum;
+import org.olat.modules.curriculum.CurriculumElement;
+import org.olat.modules.curriculum.CurriculumElementMembership;
+import org.olat.modules.curriculum.CurriculumSecurityCallback;
+import org.olat.modules.curriculum.CurriculumService;
+import org.olat.modules.curriculum.model.CurriculumElementRefImpl;
+import org.olat.modules.curriculum.model.CurriculumElementRepositoryEntryViews;
+import org.olat.modules.curriculum.ui.CurriculumElementCalendarController;
+import org.olat.modules.curriculum.ui.CurriculumListController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryMyView;
+import org.olat.repository.RepositoryEntryRef;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.controllers.EntryChangedEvent;
+import org.olat.repository.controllers.EntryChangedEvent.Change;
+import org.olat.repository.model.RepositoryEntryRefImpl;
+import org.olat.repository.model.SearchMyRepositoryEntryViewParams;
+import org.olat.repository.ui.PriceMethod;
+import org.olat.repository.ui.RepositoryEntryImageMapper;
+import org.olat.repository.ui.list.RepositoryEntryDetailsController;
+import org.olat.resource.OLATResource;
+import org.olat.resource.accesscontrol.ACService;
+import org.olat.resource.accesscontrol.AccessControlModule;
+import org.olat.resource.accesscontrol.method.AccessMethodHandler;
+import org.olat.resource.accesscontrol.model.OLATResourceAccess;
+import org.olat.resource.accesscontrol.model.PriceMethodBundle;
+import org.olat.resource.accesscontrol.ui.PriceFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * This is a list of curriculum elements and repository entries
+ * aimed to participants. The repository entries permissions
+ * follow the same rules as {@link org.olat.repository.ui.list.RepositoryEntryListController}<br>
+ * <p>
+ * <p>
+ * Initial date: 11 mai 2018<br>
+ *
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class CertificateAndEfficiencyStatementCurriculumListController extends FormBasicController implements FlexiTableCssDelegate, FlexiTableComponentDelegate, Activateable2 {
+
+    private FlexiTableElement tableEl;
+    private CurriculumElementWithViewsDataModel tableModel;
+    private final BreadcrumbPanel stackPanel;
+
+    private int counter;
+    private final boolean guestOnly;
+    private final List<Curriculum> curriculumList;
+
+    private final MapperKey mapperThumbnailKey;
+    private final Identity assessedIdentity;
+    private final CurriculumSecurityCallback curriculumSecurityCallback;
+    private final RoleSecurityCallback roleSecurityCallback;
+
+    private RepositoryEntryDetailsController detailsCtrl;
+    private CurriculumElementCalendarController calendarsCtrl;
+
+    @Autowired
+    private ACService acService;
+    @Autowired
+    private MarkManager markManager;
+    @Autowired
+    private MapperService mapperService;
+    @Autowired
+    private AccessControlModule acModule;
+    @Autowired
+    private RepositoryService repositoryService;
+    @Autowired
+    private CurriculumService curriculumService;
+    @Autowired
+    private RepositoryManager repositoryManager;
+    @Autowired
+    private AssessmentService assessmentService;
+    @Autowired
+    private BaseSecurity securityManager;
+    @Autowired
+    private EfficiencyStatementManager esm;
+    @Autowired
+    private CertificatesManager certificatesManager;
+
+    public CertificateAndEfficiencyStatementCurriculumListController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
+                                                                     Identity assessedIdentity, CurriculumSecurityCallback curriculumSecurityCallback, RoleSecurityCallback roleSecurityCallback) {
+        super(ureq, wControl, "curriculum_element_list");
+        setTranslator(Util.createPackageTranslator(AssessmentModule.class, getLocale(), getTranslator()));
+        setTranslator(Util.createPackageTranslator(CertificateAndEfficiencyStatementListController.class, getLocale(), getTranslator()));
+        setTranslator(Util.createPackageTranslator(CurriculumListController.class, getLocale(), getTranslator()));
+        setTranslator(Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator()));
+
+        this.stackPanel = stackPanel;
+        this.curriculumSecurityCallback = curriculumSecurityCallback;
+        this.roleSecurityCallback = roleSecurityCallback;
+        this.assessedIdentity = assessedIdentity;
+        this.curriculumList = curriculumService.getMyCurriculums(assessedIdentity);
+        guestOnly = ureq.getUserSession().getRoles().isGuestOnly();
+        mapperThumbnailKey = mapperService.register(null, "repositoryentryImage", new RepositoryEntryImageMapper());
+
+        initForm(ureq);
+        loadModel(ureq);
+    }
+
+    @Override
+    public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+
+    }
+
+    @Override
+    protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+        FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+
+        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.key));
+
+        TreeNodeFlexiCellRenderer treeNodeRenderer = new TreeNodeFlexiCellRenderer("select");
+        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.displayName, treeNodeRenderer));
+
+        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.details));
+
+        DefaultFlexiColumnModel elementIdentifierCol = new DefaultFlexiColumnModel(ElementViewCols.identifier, "select");
+        elementIdentifierCol.setCellRenderer(new CurriculumElementCompositeRenderer("select", new TextFlexiCellRenderer()));
+        columnsModel.addFlexiColumnModel(elementIdentifierCol);
+
+        // Name column
+        // columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.select));
+
+        if (roleSecurityCallback.canViewCourseProgressAndStatus()) {
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.passed));
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.completion));
+        }
+        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.lastModification));
+        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.lastUserModified));
+        if (roleSecurityCallback.canViewEfficiencyStatements()) {
+            BooleanCellRenderer efficiencyStatementRenderer = new BooleanCellRenderer(new StaticFlexiCellRenderer("openStatement", translate("table.header.show")), null);
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.efficiencyStatement, efficiencyStatementRenderer));
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.certificate));
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.recertification));
+        }
+        if (roleSecurityCallback.canViewCalendar()) {
+            columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.calendars));
+        }
+
+        tableModel = new CurriculumElementWithViewsDataModel(columnsModel);
+        tableEl = uifactory.addTableElement(getWindowControl(), "table", tableModel, 50, false, getTranslator(), formLayout);
+        tableEl.setElementCssClass("o_curriculumtable");
+        tableEl.setCustomizeColumns(true);
+        tableEl.setEmtpyTableMessageKey("table.curriculum.empty");
+        tableEl.setCssDelegate(this);
+        tableEl.setFilters("activity", getFilters(), false);
+        tableEl.setSelectedFilterKey(CurriculumElementWithViewsDataModel.FilterKeys.withStatementOnly.name());
+
+        VelocityContainer row = createVelocityContainer("curriculum_element_row");
+        row.setDomReplacementWrapperRequired(false); // sets its own DOM id in velocity container
+        tableEl.setRowRenderer(row, this);
+
+        tableEl.setAndLoadPersistedPreferences(ureq, "c123oach-mentor-curriculum-"
+                + (assessedIdentity.equals(getIdentity()) ? "" : "look-"));
+    }
+
+    private List<FlexiTableFilter> getFilters() {
+        List<FlexiTableFilter> filters = new ArrayList<>(5);
+        filters.add(new FlexiTableFilter(translate(CurriculumElementWithViewsDataModel.FilterKeys.activ.i18nHeaderKey()), CurriculumElementWithViewsDataModel.FilterKeys.activ.name()));
+        filters.add(new FlexiTableFilter(translate(CurriculumElementWithViewsDataModel.FilterKeys.withStatementOnly.i18nHeaderKey()), CurriculumElementWithViewsDataModel.FilterKeys.withStatementOnly.name()));
+        filters.add(FlexiTableFilter.SPACER);
+        filters.add(new FlexiTableFilter(translate(CurriculumElementWithViewsDataModel.FilterKeys.showAll.i18nHeaderKey()), CurriculumElementWithViewsDataModel.FilterKeys.showAll.name(), true));
+        return filters;
+    }
+
+    @Override
+    public String getWrapperCssClass(FlexiTableRendererType type) {
+        return null;
+    }
+
+    @Override
+    public String getTableCssClass(FlexiTableRendererType type) {
+        return null;
+    }
+
+    @Override
+    public String getRowCssClass(FlexiTableRendererType type, int pos) {
+        StringBuilder sb = new StringBuilder(64);
+        CurriculumTreeWithViewsRow rowWithView = tableModel.getObject(pos);
+        if (type == FlexiTableRendererType.custom) {
+            sb.append("o_table_row ");
+
+            if (rowWithView.isCurriculumElementOnly()) {
+                sb.append("o_curriculum_element");
+                if (rowWithView.getCurriculumElementRepositoryEntryCount() > 1) {
+                    sb.append(" o_with_multi_repository_entries");
+                }
+            } else if (rowWithView.isRepositoryEntryOnly()) {
+                sb.append("o_repository_entry");
+            } else if (rowWithView.isCurriculumElementWithEntry()) {
+                sb.append("o_mixed_element");
+            }
+        }
+
+        if (rowWithView.isCurriculum() || rowWithView.getLevel() == -1) {
+            sb.append(" o_curriculum");
+        } else {
+            int count = 0;
+            for (CurriculumTreeWithViewsRow parent = rowWithView.getParent(); parent != null; parent = parent.getParent()) {
+                count++;
+            }
+
+            // Substract one level for the curriculum parent
+            if (count > 0) {
+                count -= 1;
+            }
+
+            sb.append(" o_curriculum_element_l").append(count);
+            if (!rowWithView.isRepositoryEntryOnly() && rowWithView.getCurriculumElementTypeCssClass() != null) {
+                sb.append(" ").append(rowWithView.getCurriculumElementTypeCssClass());
+            }
+            if (rowWithView.getEntryStatus() != null) {
+                sb.append(" repo_status_").append(rowWithView.getEntryStatus());
+            }
+        }
+        return sb.toString();
+    }
+
+    @Override
+    public Iterable<Component> getComponents(int row, Object rowObject) {
+        return null;
+    }
+
+    private void loadModel(UserRequest ureq) {
+        // Load efficiency statements
+        Map<Long, CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement> resourceKeyToStatments = new HashMap<>();
+        List<CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement> statements = new ArrayList<>();
+        List<UserEfficiencyStatementLight> efficiencyStatementsList = esm.findEfficiencyStatementsLight(assessedIdentity);
+
+        List<Long> courseEntryKeys = efficiencyStatementsList.stream()
+                .map(UserEfficiencyStatementLight::getCourseRepoKey)
+                .filter(key -> key != null)
+                .collect(Collectors.toList());
+        Map<Long, Double> courseEntryKeysToCompletion = assessmentService
+                .loadRootAssessmentEntriesByAssessedIdentity(assessedIdentity, courseEntryKeys).stream()
+                .filter(ae -> ae.getCompletion() != null)
+                .collect(Collectors.toMap(
+                        ae -> ae.getRepositoryEntryKey(),
+                        ae -> ae.getCompletion()
+                ));
+
+        for(UserEfficiencyStatementLight efficiencyStatement:efficiencyStatementsList) {
+            CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement wrapper = new CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement();
+            wrapper.setDisplayName(efficiencyStatement.getShortTitle());
+            wrapper.setPassed(efficiencyStatement.getPassed());
+            wrapper.setScore(efficiencyStatement.getScore());
+            wrapper.setEfficiencyStatementKey(efficiencyStatement.getKey());
+            wrapper.setResourceKey(efficiencyStatement.getArchivedResourceKey());
+            wrapper.setLastModified(efficiencyStatement.getLastModified());
+            wrapper.setLastUserModified(efficiencyStatement.getLastUserModified());
+            Double completion = courseEntryKeysToCompletion.get(efficiencyStatement.getCourseRepoKey());
+            wrapper.setCompletion(completion);
+            statements.add(wrapper);
+            resourceKeyToStatments.put(efficiencyStatement.getArchivedResourceKey(), wrapper);
+        }
+
+        List<CertificateLight> certificates = certificatesManager.getLastCertificates(assessedIdentity);
+        for(CertificateLight certificate:certificates) {
+            Long resourceKey = certificate.getOlatResourceKey();
+            CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement wrapper = resourceKeyToStatments.get(resourceKey);
+            if(wrapper == null) {
+                wrapper = new CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement();
+                wrapper.setDisplayName(certificate.getCourseTitle());
+                resourceKeyToStatments.put(resourceKey, wrapper);
+                statements.add(wrapper);
+            } else {
+                if(!StringHelper.containsNonWhitespace(wrapper.getDisplayName())) {
+                    wrapper.setDisplayName(certificate.getCourseTitle());
+                }
+                wrapper.setResourceKey(resourceKey);
+            }
+            if(resourceKey != null && wrapper.getResourceKey() == null) {
+                wrapper.setResourceKey(resourceKey);
+            }
+            wrapper.setCertificate(certificate);
+        }
+
+        for(CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement statment:statements) {
+            if(!StringHelper.containsNonWhitespace(statment.getDisplayName()) && statment.getResourceKey() != null) {
+                String displayName = repositoryManager.lookupDisplayNameByResourceKey(statment.getResourceKey());
+                statment.setDisplayName(displayName);
+            }
+        }
+
+        // Set of Olat resources with statements
+        Set<Long> statementEntries = statements.stream().map(CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement::getResourceKey).collect(Collectors.toSet());
+        // Set of entries, which will be added in the next step
+        Set<Long> alreadyAdded = new HashSet<>();
+
+        // Load Curricula
+        Roles roles = ureq.getUserSession().getRoles();
+        List<CurriculumTreeWithViewsRow> allRows = new ArrayList<>();
+        List<CurriculumElementRepositoryEntryViews> elementsWithViewsForAll = curriculumService.getCurriculumElements(assessedIdentity, roles, curriculumList);
+        Map<Curriculum, List<CurriculumElementRepositoryEntryViews>> elementsMap = elementsWithViewsForAll.stream().collect(Collectors.groupingBy(row -> row.getCurriculumElement().getCurriculum(), Collectors.toList()));
+
+        for (Curriculum curriculum : curriculumList) {
+            CurriculumTreeWithViewsRow curriculumRow = new CurriculumTreeWithViewsRow(curriculum);
+            List<CurriculumElementRepositoryEntryViews> elementsWithViews = elementsMap.get(curriculum);
+
+            if (elementsWithViews != null && !elementsWithViews.isEmpty()) {
+                List<CurriculumTreeWithViewsRow> rows = new ArrayList<>();
+
+                Set<Long> repoKeys = new HashSet<>();
+                List<OLATResource> resourcesWithAC = new ArrayList<>();
+                for (CurriculumElementRepositoryEntryViews elementWithViews : elementsWithViews) {
+                    for (RepositoryEntryMyView entry : elementWithViews.getEntries()) {
+                        repoKeys.add(entry.getKey());
+                        if (entry.isValidOfferAvailable()) {
+                            resourcesWithAC.add(entry.getOlatResource());
+                        }
+                    }
+                }
+                List<OLATResourceAccess> resourcesWithOffer = acService.filterResourceWithAC(resourcesWithAC);
+                repositoryService.filterMembership(assessedIdentity, repoKeys);
+
+                for (CurriculumElementRepositoryEntryViews elementWithViews : elementsWithViews) {
+                    CurriculumElement element = elementWithViews.getCurriculumElement();
+                    CurriculumElementMembership elementMembership = elementWithViews.getCurriculumMembership();
+
+                    List<RepositoryEntryMyView> repositoryEntryMyViews = new ArrayList<>();
+                    if (elementWithViews.getEntries() != null && !elementWithViews.getEntries().isEmpty()) {
+                        for (RepositoryEntryMyView entry : elementWithViews.getEntries()) {
+                           // if (statementEntries.contains(entry.getOlatResource().getKey())) {
+                                repositoryEntryMyViews.add(entry);
+                           // }
+                        }
+                    }
+
+
+                    if (repositoryEntryMyViews == null || repositoryEntryMyViews.isEmpty()) {
+                        CurriculumTreeWithViewsRow row = new CurriculumTreeWithViewsRow(curriculum, element, elementMembership, 0);
+                        forgeCalendarsLink(row);
+                        rows.add(row);
+                    } else if (repositoryEntryMyViews.size() == 1) {
+                        CurriculumTreeWithViewsRow row = new CurriculumTreeWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().get(0), true);
+                        forge(row, repoKeys, resourcesWithOffer);
+                        forgeCalendarsLink(row);
+                        rows.add(row);
+                    } else {
+                        CurriculumTreeWithViewsRow elementRow = new CurriculumTreeWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().size());
+                        forgeCalendarsLink(elementRow);
+                        rows.add(elementRow);
+                        for (RepositoryEntryMyView entry : repositoryEntryMyViews) {
+                            CurriculumTreeWithViewsRow row = new CurriculumTreeWithViewsRow(curriculum, element, elementMembership, entry, false);
+                            forge(row, repoKeys, resourcesWithOffer);
+                            rows.add(row);
+                        }
+                    }
+                }
+
+
+                Map<CurriculumKey, CurriculumTreeWithViewsRow> keyToRow = rows.stream()
+                        .collect(Collectors.toMap(CurriculumTreeWithViewsRow::getKey, row -> row, (row1, row2) -> row1));
+                rows.forEach(row -> {
+                    row.setParent(keyToRow.get(row.getParentKey()));
+                    if (row.getOlatResource() != null) {
+                        alreadyAdded.add(row.getOlatResource().getKey());
+                        if (statementEntries.contains(row.getOlatResource().getKey())){
+                            row.setHasStatement(true);
+                        }
+
+                        VFSLeaf image = repositoryManager.getImage(row.getRepositoryEntryResourceable().getResourceableId(), row.getOlatResource());
+                        if (image != null) {
+                            row.setThumbnailRelPath(mapperThumbnailKey.getUrl() + "/" + image.getName());
+                        }
+                    }
+                });
+
+                removeByPermissions(rows);
+                forgeCurriculumCompletions(rows);
+                addRoot(rows, curriculumRow);
+
+                allRows.add(curriculumRow);
+                allRows.addAll(rows);
+            }
+        }
+
+
+
+        // Filter for entries which are already in a curriculum
+        Roles assessedRoles = securityManager.getRoles(assessedIdentity);
+        SearchMyRepositoryEntryViewParams params = new SearchMyRepositoryEntryViewParams(assessedIdentity, assessedRoles);
+        params.setMembershipMandatory(true);
+        List<RepositoryEntryMyView> courses = repositoryService.searchMyView(params, 0, 0);
+
+//        // Filter for entries which have a efficiency statement
+//        Set<Long> alreadyAdded = new HashSet<>();
+//        for (CurriculumTreeWithViewsRow row : allRows) {
+//            for (RepositoryEntryMyView entry : row.getEntries()) {
+//                alreadyAdded.add(entry.getOlatResource().getKey());
+//            }
+//        }
+
+        courses.removeIf(course -> alreadyAdded.contains(course.getOlatResource().getKey()));
+
+        // Filter for entries which are without curriculum
+        CurriculumTreeWithViewsRow foreignEntryParent = new CurriculumTreeWithViewsRow(translate("curriculum.foreign.entries"));
+
+        if (!courses.isEmpty()) {
+            allRows.add(foreignEntryParent);
+
+            courses.forEach(course -> {
+                CurriculumTreeWithViewsRow row = new CurriculumTreeWithViewsRow(course);
+                forgeSelectLink(row);
+                forgeCompletion(row,row.getRepositoryEntryCompletion());
+                forgeDetails(row);
+                row.setParent(foreignEntryParent);
+                row.setHasStatement(true);
+                allRows.add(row);
+                alreadyAdded.add(course.getOlatResource().getKey());
+            });
+        }
+
+        // Add Statements which don't belong to any course
+        Set<Long> orphanCertificates = statementEntries.stream().filter(certificateResourceKey -> !alreadyAdded.contains(certificateResourceKey)).collect(Collectors.toSet());
+
+        if (!orphanCertificates.isEmpty()) {
+            if (!allRows.contains(foreignEntryParent)) {
+                allRows.add(foreignEntryParent);
+            }
+
+            orphanCertificates.forEach(orphan -> {
+                CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement statement = statements.stream().filter(certStatement -> certStatement.getResourceKey().equals(orphan)).findFirst().get();
+                CurriculumTreeWithViewsRow row = new CurriculumTreeWithViewsRow(statement);
+                row.setParent(foreignEntryParent);
+                row.setHasStatement(true);
+                allRows.add(row);
+            });
+        }
+
+
+        Collections.sort(allRows, new CurriculumElementViewsRowComparator(getLocale()));
+
+
+        tableModel.setObjects(allRows);
+        tableEl.reset(true, true, true);
+    }
+
+    private void removeByPermissions(List<CurriculumTreeWithViewsRow> rows) {
+        // propagate the member marker along the parent line
+        for (CurriculumTreeWithViewsRow row : rows) {
+            if (row.isCurriculumMember()) {
+                for (CurriculumTreeWithViewsRow parentRow = row.getParent(); parentRow != null; parentRow = parentRow.getParent()) {
+                    parentRow.setCurriculumMember(true);
+                }
+            }
+        }
+
+        // trim part of the tree without member flag
+        rows.removeIf(curriculumTreeWithViewsRow -> !curriculumTreeWithViewsRow.isCurriculumMember());
+    }
+
+    private void forge(CurriculumTreeWithViewsRow row, Collection<Long> repoKeys, List<OLATResourceAccess> resourcesWithOffer) {
+        if (row.getRepositoryEntryKey() == null || guestOnly) return;// nothing for guests
+
+        boolean isMember = repoKeys.contains(row.getRepositoryEntryKey());
+        row.setMember(isMember);
+
+        FormLink startLink = null;
+        List<PriceMethod> types = new ArrayList<>();
+        if (row.isAllUsers() || isMember) {
+            startLink = uifactory.addFormLink("start_" + (++counter), "start", "start", null, null, Link.LINK);
+            startLink.setElementCssClass("o_start btn-block");
+            startLink.setCustomEnabledLinkCSS("o_start btn-block");
+            startLink.setIconRightCSS("o_icon o_icon_start");
+        } else if (row.isBookable()) {
+            // collect access control method icons
+            OLATResource resource = row.getOlatResource();
+            for (OLATResourceAccess resourceAccess : resourcesWithOffer) {
+                if (resource.getKey().equals(resourceAccess.getResource().getKey())) {
+                    for (PriceMethodBundle bundle : resourceAccess.getMethods()) {
+                        String type = (bundle.getMethod().getMethodCssClass() + "_icon").intern();
+                        String price = bundle.getPrice() == null || bundle.getPrice().isEmpty() ? "" : PriceFormat.fullFormat(bundle.getPrice());
+                        AccessMethodHandler amh = acModule.getAccessMethodHandler(bundle.getMethod().getType());
+                        String displayName = amh.getMethodName(getLocale());
+                        types.add(new PriceMethod(price, type, displayName));
+                    }
+                }
+            }
+
+            startLink = uifactory.addFormLink("start_" + (++counter), "start", "book", null, null, Link.LINK);
+            startLink.setElementCssClass("o_start btn-block");
+            startLink.setCustomEnabledLinkCSS("o_book btn-block");
+            startLink.setIconRightCSS("o_icon o_icon_start");
+        }
+
+        if(startLink != null) {
+            startLink.setUserObject(row);
+            String businessPath = "[RepositoryEntry:" + row.getRepositoryEntryKey() + "]";
+            String startUrl = BusinessControlFactory.getInstance().getAuthenticatedURLFromBusinessPathString(businessPath);
+            startLink.setUrl(startUrl);
+            row.setStartLink(startLink, startUrl);
+        }
+
+
+        if (!row.isAllUsers() && !row.isGuests()) {
+            // members only always show lock icon
+            types.add(new PriceMethod("", "o_ac_membersonly_icon", translate("cif.access.membersonly.short")));
+        }
+        if (!types.isEmpty()) {
+            row.setAccessTypes(types);
+        }
+
+        forgeDetails(row);
+        forgeMarkLink(row);
+        forgeSelectLink(row);
+        forgeCompletion(row, row.getRepositoryEntryCompletion());
+    }
+
+    private void forgeDetails(CurriculumTreeWithViewsRow row) {
+        FormLink detailsLink = uifactory.addFormLink("details_" + (++counter), "details", "details", null, null, Link.LINK);
+        detailsLink.setCustomEnabledLinkCSS("o_details");
+        detailsLink.setUserObject(row);
+        Long repoEntryKey = row.getRepositoryEntryKey();
+        String detailsUrl = null;
+        if(repoEntryKey != null) {
+            String businessPath = "[RepositoryEntry:" + repoEntryKey + "][Infos:0]";
+            detailsUrl = BusinessControlFactory.getInstance()
+                    .getAuthenticatedURLFromBusinessPathString(businessPath);
+            detailsLink.setUrl(detailsUrl);
+        }
+        row.setDetailsLink(detailsLink, detailsUrl);
+    }
+
+    private void forgeMarkLink(CurriculumTreeWithViewsRow row) {
+        if (!guestOnly) {
+            FormLink markLink = uifactory.addFormLink("mark_" + (++counter), "mark", "", null, null, Link.NONTRANSLATED);
+            markLink.setIconLeftCSS(row.isMarked() ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE);
+            markLink.setTitle(translate(row.isMarked() ? "details.bookmark.remove" : "details.bookmark"));
+            markLink.setUserObject(row);
+            row.setMarkLink(markLink);
+        }
+    }
+
+    private void forgeSelectLink(CurriculumTreeWithViewsRow row) {
+        if (row.isCurriculumElementOnly()) return;
+
+        String displayName = StringHelper.escapeHtml(row.getRepositoryEntryDisplayName());
+        FormLink selectLink = uifactory.addFormLink("select_" + (++counter), "select", displayName, null, null, Link.NONTRANSLATED);
+        if (row.isClosed()) {
+            selectLink.setIconLeftCSS("o_icon o_CourseModule_icon_closed");
+        }
+        Long repoEntryKey = row.getRepositoryEntryKey();
+        if (repoEntryKey != null) {
+            String businessPath = "[RepositoryEntry:" + repoEntryKey + "]";
+            selectLink.setUrl(BusinessControlFactory.getInstance()
+                    .getAuthenticatedURLFromBusinessPathString(businessPath));
+        }
+        selectLink.setUserObject(row);
+        row.setSelectLink(selectLink);
+    }
+
+    private void forgeCalendarsLink(CurriculumTreeWithViewsRow row) {
+        if (row.isCalendarsEnabled()) {
+            FormLink calendarLink = uifactory.addFormLink("cals_" + (++counter), "calendars", "calendars", null, null, Link.LINK);
+            calendarLink.setIconLeftCSS("o_icon o_icon-fw o_icon_timetable");
+            calendarLink.setUserObject(row);
+            row.setCalendarsLink(calendarLink);
+        }
+    }
+
+    private void forgeCurriculumCompletions(List<CurriculumTreeWithViewsRow> rows) {
+        Map<Long, Double> completions = loadCurriculumElementCompletions(rows);
+
+        for (CurriculumTreeWithViewsRow row : rows) {
+            if (row.getCompletionItem() == null) { // does not show completion of the child entry
+                forgeCompletion(row, completions.get(row.getKey()));
+            }
+        }
+    }
+
+    private void forgeCompletion(CurriculumTreeWithViewsRow row, Double completion) {
+        if (completion != null) {
+            ProgressBarItem completionItem = new ProgressBarItem("completion_" + row.getKey(), 100,
+                    completion.floatValue(), Float.valueOf(1), null);
+            completionItem.setWidthInPercent(true);
+            completionItem.setLabelAlignment(LabelAlignment.none);
+            completionItem.setRenderStyle(RenderStyle.radial);
+            completionItem.setRenderSize(RenderSize.inline);
+            completionItem.setBarColor(BarColor.success);
+            row.setCompletionItem(completionItem);
+        }
+    }
+
+    private void addRoot(List<CurriculumTreeWithViewsRow> rows, CurriculumTreeWithViewsRow parent) {
+        rows.stream().filter(row -> row.getParent() == null).forEach(row -> {
+            row.setParent(parent);
+            if (row.hasStatement()) {
+                parent.setHasStatement(true);
+            }
+        });
+    }
+
+    private Map<Long, Double> loadCurriculumElementCompletions(List<CurriculumTreeWithViewsRow> rows) {
+        List<Long> curEleLearningProgressKeys = rows.stream()
+                .filter(CurriculumTreeWithViewsRow::isLearningProgressEnabled)
+                .map(CurriculumTreeWithViewsRow::getKey)
+                .map(CurriculumKey::getCurriculumElement)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        List<AssessmentEntryCompletion> loadAvgCompletionsByCurriculumElements = assessmentService
+                .loadAvgCompletionsByCurriculumElements(assessedIdentity, curEleLearningProgressKeys);
+        Map<Long, Double> completions = new HashMap<>();
+        for (AssessmentEntryCompletion completion : loadAvgCompletionsByCurriculumElements) {
+            if (completion.getCompletion() != null) {
+                completions.put(completion.getKey(), completion.getCompletion());
+            }
+        }
+        return completions;
+    }
+
+    @Override
+    protected void doDispose() {
+        //
+    }
+
+    @Override
+    protected void propagateDirtinessToContainer(FormItem fiSrc, FormEvent event) {
+        //do not update the
+    }
+
+    @Override
+    public void event(UserRequest ureq, Component source, Event event) {
+        if (source == mainForm.getInitialComponent()) {
+            if ("ONCLICK".equals(event.getCommand())) {
+                String rowKeyStr = ureq.getParameter("select_row");
+                if (StringHelper.isLong(rowKeyStr)) {
+                    try {
+                        Long rowKey = Long.valueOf(rowKeyStr);
+                        List<CurriculumTreeWithViewsRow> rows = tableModel.getObjects();
+                        for (CurriculumTreeWithViewsRow row : rows) {
+                            if (row != null && row.getRepositoryEntryKey() != null && row.getRepositoryEntryKey().equals(rowKey)) {
+                                if (row.isMember()) {
+                                    doOpen(ureq, row, null);
+                                } else {
+                                    doOpenDetails(ureq, row);
+                                }
+                            }
+                        }
+                    } catch (NumberFormatException e) {
+                        logWarn("Not a valid long: " + rowKeyStr, e);
+                    }
+                }
+            }
+        }
+        super.event(ureq, source, event);
+    }
+
+    @Override
+    protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+        if (source instanceof FormLink) {
+            FormLink link = (FormLink) source;
+            if ("start".equals(link.getCmd())) {
+                CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow) link.getUserObject();
+                doOpen(ureq, row, null);
+            } else if ("details".equals(link.getCmd())) {
+                CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow) link.getUserObject();
+                doOpenDetails(ureq, row);
+            } else if ("select".equals(link.getCmd())) {
+                CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow) link.getUserObject();
+                if (row.isMember()) {
+                    doOpen(ureq, row, null);
+                } else {
+                    doOpenDetails(ureq, row);
+                }
+            } else if ("mark".equals(link.getCmd())) {
+                CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow) link.getUserObject();
+                boolean marked = doMark(ureq, row);
+                link.setIconLeftCSS(marked ? "o_icon o_icon_bookmark o_icon-lg" : "o_icon o_icon_bookmark_add o_icon-lg");
+                link.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
+                link.getComponent().setDirty(true);
+                row.setMarked(marked);
+            } else if ("calendars".equals(link.getCmd())) {
+                CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow) link.getUserObject();
+                doOpenCalendars(ureq, row);
+            }
+        } else if (source == tableEl) {
+            if (event instanceof SelectionEvent) {
+                SelectionEvent se = (SelectionEvent) event;
+                CurriculumTreeWithViewsRow row = tableModel.getObject(se.getIndex());
+                if (row.isMember()) {
+                    doOpen(ureq, row, null);
+                } else {
+                    doOpenDetails(ureq, row);
+                }
+            }
+        }
+        super.formInnerEvent(ureq, source, event);
+    }
+
+    @Override
+    protected void formOK(UserRequest ureq) {
+        //
+    }
+
+    private void doOpen(UserRequest ureq, CurriculumTreeWithViewsRow row, String subPath) {
+        try {
+            String businessPath = "[RepositoryEntry:" + row.getRepositoryEntryKey() + "]";
+            if (subPath != null) {
+                businessPath += subPath;
+            }
+            NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
+        } catch (CorruptedCourseException e) {
+            logError("Course corrupted: " + row.getKey() + " (" + row.getOlatResource().getResourceableId() + ")", e);
+            showError("cif.error.corrupted");
+        }
+    }
+
+    private void doOpenDetails(UserRequest ureq, CurriculumTreeWithViewsRow row) {
+        // to be more consistent: course members see info page within the course, non-course members see it outside the course
+        if (row.isMember()) {
+            doOpen(ureq, row, "[Infos:0]");
+        } else {
+            removeAsListenerAndDispose(detailsCtrl);
+
+            OLATResourceable ores = OresHelper.createOLATResourceableInstance("Infos", 0l);
+            WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
+
+            Long repoEntryKey = row.getRepositoryEntryKey();
+            RepositoryEntry entry = repositoryService.loadByKey(repoEntryKey);
+            if (repoEntryKey == null) {
+                showInfo("curriculum.element.empty");
+            } else if (entry == null) {
+                showWarning("repositoryentry.not.existing");
+            } else {
+                detailsCtrl = new RepositoryEntryDetailsController(ureq, bwControl, entry, false);
+                listenTo(detailsCtrl);
+                addToHistory(ureq, detailsCtrl);
+
+                String displayName = row.getRepositoryEntryDisplayName();
+                stackPanel.pushController(displayName, detailsCtrl);
+            }
+        }
+    }
+
+    private void doOpenCalendars(UserRequest ureq, CurriculumTreeWithViewsRow row) {
+        removeAsListenerAndDispose(calendarsCtrl);
+
+        OLATResourceable ores = OresHelper.createOLATResourceableInstance("Calendars", row.getCurriculumElementKey());
+        WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
+        CurriculumElement element = curriculumService
+                .getCurriculumElement(new CurriculumElementRefImpl(row.getCurriculumElementKey()));
+        List<CurriculumTreeWithViewsRow> rows = tableModel.getObjects();
+
+        Set<Long> entryKeys = new HashSet<>();
+        for (CurriculumTreeWithView elementWithView : rows) {
+            if (elementWithView.isCurriculumMember()
+                    && !elementWithView.getEntries().isEmpty()
+                    && elementWithView.isParentOrSelf(row)) {
+                for (RepositoryEntryMyView view : elementWithView.getEntries()) {
+                    if ("CourseModule".equals(view.getOlatResource().getResourceableTypeName())) {
+                        entryKeys.add(view.getKey());
+                    }
+                }
+            }
+        }
+
+
+        List<RepositoryEntry> entries = repositoryService.loadByKeys(entryKeys);
+        calendarsCtrl = new CurriculumElementCalendarController(ureq, bwControl, element, entries, curriculumSecurityCallback);
+        listenTo(calendarsCtrl);
+        stackPanel.pushController(translate("calendars"), calendarsCtrl);
+    }
+
+    private boolean doMark(UserRequest ureq, CurriculumTreeWithViewsRow row) {
+        OLATResourceable item = OresHelper.createOLATResourceableInstance("RepositoryEntry", row.getRepositoryEntryKey());
+        RepositoryEntryRef ref = new RepositoryEntryRefImpl(row.getRepositoryEntryKey());
+        if (markManager.isMarked(item, getIdentity(), null)) {
+            markManager.removeMark(item, getIdentity(), null);
+
+            EntryChangedEvent e = new EntryChangedEvent(ref, getIdentity(), Change.removeBookmark, "curriculum");
+            ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
+            return false;
+        } else {
+            String businessPath = "[RepositoryEntry:" + item.getResourceableId() + "]";
+            markManager.setMark(item, getIdentity(), null, businessPath);
+
+            EntryChangedEvent e = new EntryChangedEvent(ref, getIdentity(), Change.addBookmark, "curriculum");
+            ureq.getUserSession().getSingleUserEventCenter().fireEventToListenersOf(e, RepositoryService.REPOSITORY_EVENT_ORES);
+            return true;
+        }
+    }
+
+    private List<CurriculumTreeWithViewsRow> sortCurriculumRows(List<CurriculumTreeWithViewsRow> rows) {
+        List<CurriculumTreeWithViewsRow> sortedRows = rows.stream().filter(row -> row.   getLevel() == 0).collect(Collectors.toList());
+
+        for (CurriculumTreeWithViewsRow parent : sortedRows) {
+            if (parent.hasChildren()) {
+                sortedRows.addAll(sortedRows.indexOf(parent) + 1, sortCurriculumRows(rows, parent));
+            }
+        }
+
+        return sortedRows;
+    }
+
+    private List<CurriculumTreeWithViewsRow> sortCurriculumRows(List<CurriculumTreeWithViewsRow> rows, CurriculumTreeWithViewsRow parent) {
+        List<CurriculumTreeWithViewsRow> filteredRows = rows.stream().filter(row -> row.getParent() != null && row.getParent().equals(parent)).collect(Collectors.toList());
+        List<CurriculumTreeWithViewsRow> sortedRows = new ArrayList<>(filteredRows);
+
+        for (CurriculumTreeWithViewsRow child : filteredRows) {
+            if (child.hasChildren()) {
+                sortedRows.addAll(filteredRows.indexOf(child) + 1, sortCurriculumRows(rows, parent));
+            }
+        }
+
+        return filteredRows;
+    }
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementWrapperController.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementWrapperController.java
new file mode 100644
index 0000000000000000000000000000000000000000..44cffc8ccafc3121a39af55ffba1fc7f5a34a362
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CertificateAndEfficiencyStatementWrapperController.java
@@ -0,0 +1,172 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.util.List;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.stack.TooledStackedPanel;
+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.gui.control.generic.dtabs.Activateable2;
+import org.olat.core.id.Identity;
+import org.olat.core.id.context.ContextEntry;
+import org.olat.core.id.context.StateEntry;
+import org.olat.core.util.event.GenericEventListener;
+import org.olat.core.util.resource.OresHelper;
+import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListController;
+import org.olat.modules.coach.RoleSecurityCallback;
+import org.olat.modules.coach.model.StudentStatEntry;
+import org.olat.modules.curriculum.CurriculumModule;
+import org.olat.modules.curriculum.CurriculumRef;
+import org.olat.modules.curriculum.CurriculumSecurityCallback;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class CertificateAndEfficiencyStatementWrapperController extends BasicController implements Activateable2, GenericEventListener {
+
+    private static final String WITH_CURRICULUM = "Curriculum";
+    private static final String WITHOUT_CURRICULM = "List";
+
+    private final TooledStackedPanel stackPanel;
+    private final Identity mentee;
+    private final StudentStatEntry statEntry;
+    private final CurriculumSecurityCallback curriculumSecurityCallback;
+    private final RoleSecurityCallback roleSecurityCallback;
+    private final List<CurriculumRef> curriculumRefs;
+
+    private CertificateAndEfficiencyStatementCurriculumListController certificateCurriculumListController;
+    private CertificateAndEfficiencyStatementListController certificateListController;
+
+    private Link curriculumShow;
+    private Link curriculumHide;
+    private boolean showCurriculum;
+    private String activeCSS = "o_button_toggle o_on";
+    private String inactiveCSS = "o_button_toggle";
+    private VelocityContainer content;
+
+    @Autowired
+    CurriculumModule curriculumModule;
+
+    public CertificateAndEfficiencyStatementWrapperController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, Identity mentee, CurriculumSecurityCallback curriculumSecurityCallback, RoleSecurityCallback roleSecurityCallback, List<CurriculumRef> curriculumRefs, StudentStatEntry statEntry) {
+        super(ureq, wControl);
+
+        this.stackPanel = stackPanel;
+        this.mentee = mentee;
+        this.curriculumSecurityCallback = curriculumSecurityCallback;
+        this.roleSecurityCallback = roleSecurityCallback;
+        this.curriculumRefs = curriculumRefs;
+        this.statEntry = statEntry;
+
+        content = createVelocityContainer("certificate_list_wrapper");
+        showCurriculum = curriculumModule.isEnabled() && roleSecurityCallback.canViewCoursesAndCurriculum();
+
+        if (showCurriculum) {
+            curriculumShow = LinkFactory.createLink("off", content, this);
+            curriculumShow.setCustomEnabledLinkCSS(inactiveCSS);
+            curriculumShow.setIconLeftCSS("o_icon o_icon_toggle");
+            curriculumShow.setIconRightCSS(null);
+
+            curriculumHide = LinkFactory.createLink("on", content, this);
+            curriculumHide.setCustomEnabledLinkCSS(activeCSS);
+            curriculumHide.setIconLeftCSS(null);
+            curriculumHide.setIconRightCSS("o_icon o_icon_toggle");
+
+            showCurriculumStructure(ureq);
+        } else {
+            hideCurriculumStructure(ureq);
+        }
+
+        putInitialPanel(content);
+    }
+
+    @Override
+    public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
+        if(entries != null && !entries.isEmpty()) {
+            ContextEntry currentEntry = entries.get(0);
+            String cmd = currentEntry.getOLATResourceable().getResourceableTypeName();
+
+            Activateable2 selectedCtrl;
+
+            if (cmd.equals(WITHOUT_CURRICULM)) {
+                selectedCtrl = hideCurriculumStructure(ureq);
+            } else {
+                selectedCtrl = showCurriculumStructure(ureq);
+            }
+
+            List<ContextEntry> subEntries = entries.subList(1, entries.size());
+            selectedCtrl.activate(ureq, subEntries, currentEntry.getTransientState());
+        }
+    }
+
+    @Override
+    protected void event(UserRequest ureq, Component source, Event event) {
+        if (source == curriculumHide) {
+            hideCurriculumStructure(ureq);
+        } else if (source == curriculumShow) {
+            showCurriculumStructure(ureq);
+        }
+    }
+
+    @Override
+    public void event(Event event) {
+    	//
+    }
+
+    @Override
+    protected void doDispose() {
+    	//
+    }
+
+    public Activateable2 showCurriculumStructure(UserRequest ureq) {
+        showCurriculum = true;
+
+        if (certificateCurriculumListController == null) {
+            WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType(WITH_CURRICULUM), null);
+            certificateCurriculumListController = new CertificateAndEfficiencyStatementCurriculumListController(ureq, bwControl, stackPanel, mentee, curriculumSecurityCallback, roleSecurityCallback);
+            listenTo(certificateCurriculumListController);
+        }
+
+        content.contextPut("showCurriculum", showCurriculum);
+        content.put("content", certificateCurriculumListController.getInitialComponent());
+    	addToHistory(ureq, certificateCurriculumListController);
+        return certificateCurriculumListController;
+    }
+
+    public Activateable2 hideCurriculumStructure(UserRequest ureq) {
+        showCurriculum = false;
+
+        if (certificateListController == null) {
+            WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType(WITHOUT_CURRICULM), null);
+            certificateListController = new CertificateAndEfficiencyStatementListController(ureq, bwControl, mentee, false, false, false, false);
+            certificateListController.setBreadcrumbPanel(stackPanel);
+            listenTo(certificateListController);
+        }
+
+        content.contextPut("showCurriculum", showCurriculum);
+        content.put("content", certificateListController.getInitialComponent());
+    	addToHistory(ureq, certificateListController);
+        return certificateListController;
+    }
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementCompositeRenderer.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementCompositeRenderer.java
similarity index 91%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementCompositeRenderer.java
rename to src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementCompositeRenderer.java
index faa5c548d66e32b362092f4bdd9eecdb0b1a1e4c..0eb0d0b469eeaa009362140b4a1a1d6346eef9e1 100644
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementCompositeRenderer.java
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementCompositeRenderer.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.modules.coach.ui.curriculum;
+package org.olat.modules.coach.ui.curriculum.certificate;
 
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent;
@@ -42,7 +42,7 @@ public class CurriculumElementCompositeRenderer extends StaticFlexiCellRenderer
 	@Override
 	public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source,
 			URLBuilder ubu, Translator translator) {
-		CurriculumElementWithViewsRow view = (CurriculumElementWithViewsRow)source.getFlexiTableElement().getTableDataModel().getObject(row);
+		CurriculumTreeWithViewsRow view = (CurriculumTreeWithViewsRow)source.getFlexiTableElement().getTableDataModel().getObject(row);
 		if(view.isCurriculumElementOnly()) {
 			getLabelDelegate().render(renderer, target, cellValue, row, source, ubu, translator);
 		} else {
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementViewsRowComparator.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementViewsRowComparator.java
new file mode 100644
index 0000000000000000000000000000000000000000..49c16a44a8b08c7edbc1d1ef04c22132899ffec4
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementViewsRowComparator.java
@@ -0,0 +1,227 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.text.Collator;
+import java.util.Locale;
+
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeNodeComparator;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeTableNode;
+
+/**
+ * Compare and reorder a tree like structure by compare the
+ * rows and their parents.
+ *
+ * Initial date: 26 juin 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ * @author aboeckle, alexander.boeckle@frentix.com
+ *
+ */
+public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator {
+
+	private final Collator collator;
+
+	public CurriculumElementViewsRowComparator(Locale locale) {
+		collator = Collator.getInstance(locale);
+	}
+
+	@Override
+	protected int compareNodes(FlexiTreeTableNode o1, FlexiTreeTableNode o2) {
+		if(o1 == null || o2 == null) {
+			return compareNullObjects(o1, o2);
+		}
+
+		CurriculumTreeWithViewsRow c1 = (CurriculumTreeWithViewsRow)o1;
+		CurriculumTreeWithViewsRow c2 = (CurriculumTreeWithViewsRow)o2;
+		CurriculumKey parentKey1 = c1.getParentKey();
+		CurriculumKey parentKey2 = c2.getParentKey();
+
+		int c = 0;
+		if(parentKey1 == null && parentKey2 == null) {
+			c = compareCurricula(c1, c2);
+		} else if(parentKey1 != null && parentKey1.equals(parentKey2)) {
+			c = compareSameParent(c1, c2);
+		} else if(parentKey1 != null && !parentKey1.equals(parentKey2)) {
+			System.out.println(parentKey1 + " " + parentKey2);
+			c = compareCurricula(c1, c2);
+		} else if(parentKey1 != null && parentKey2 != null) {
+			// This case is usually not possible
+			CurriculumTreeWithViewsRow p1 = c1.getParent();
+			CurriculumTreeWithViewsRow p2 = c2.getParent();
+			if(p1 == null || p2 == null) {
+				// reversed because no parent at the top, higher in the hierarchy
+				c = -compareNullObjects(p1, p2);
+			} else {
+				c = compareCurriculumElements(p1, p2);
+			}
+		} else {
+			// This case is usually not possible
+			c = compareDisplayName(c1, c2);
+		}
+
+		if(c == 0) {
+			c = Integer.compare(c1.getKey().hashCode(), c2.getKey().hashCode());
+		}
+		return c;
+	}
+
+	private int compareCurricula(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		int c = 0;
+
+		if(c1.getCurriculumElementDisplayName() == null || c2.getCurriculumElementDisplayName() == null) {
+			c = compareNullObjects(c1.getCurriculumElementDisplayName(), c2.getCurriculumElementDisplayName());
+		} else {
+			c = collator.compare(c1.getCurriculumElementDisplayName(), c2.getCurriculumElementDisplayName());
+		}
+
+		if(c == 0) {
+			if(c1.getCurriculumElementIdentifier() == null || c2.getCurriculumElementIdentifier() == null) {
+				c = compareNullObjects(c1.getCurriculumElementIdentifier(), c2.getCurriculumElementIdentifier());
+			} else {
+				c = collator.compare(c1.getCurriculumElementIdentifier(), c2.getCurriculumElementIdentifier());
+			}
+		}
+
+		if (c == 0) {
+			if (c1.getKey().isWithoutCurriculum() && !c2.getKey().isWithoutCurriculum()) {
+				c = -1;
+			} else if (c1.getKey().isWithoutCurriculum() && c2.getKey().isWithoutCurriculum()) {
+				c = collator.compare(c1.getRepositoryEntryDisplayName(), c2.getRepositoryEntryDisplayName());
+			}
+		}
+
+		if (c == 0) {
+			if (c1.getKey().isWithoutCurriculum() && c2.getKey().isWithoutCurriculum()) {
+				c = Long.compare(c1.getRepositoryEntryKey(), c2.getRepositoryEntryKey());
+			} else {
+				c = Long.compare(c1.getCurriculumKey(), c2.getCurriculumKey());
+			}
+		}
+
+		return c;
+	}
+
+	private int compareSameParent(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		int c = 0;
+		if((c1.isCurriculumElementOnly() || c1.isCurriculumElementWithEntry()) && (c2.isCurriculumElementOnly() || c2.isCurriculumElementWithEntry())) {
+			// compare by position
+			c = compareCurriculumElements(c1, c2);
+		} else if(c1.isCurriculumElementOnly() || c1.isCurriculumElementWithEntry()) {
+			c = 1;
+		} else if(c2.isCurriculumElementOnly() || c2.isCurriculumElementWithEntry()) {
+			c = -1;
+		} else {
+			c = compareRepositoryEntry(c1, c2);
+		}
+		return c;
+	}
+
+	private int compareCurriculumElements(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		int c = compareClosed(c1, c2);
+
+		if(c == 0) {
+			if(c1.getCurriculumElementBeginDate() == null || c2.getCurriculumElementBeginDate() == null) {
+				c = compareNullObjects(c1.getCurriculumElementBeginDate(), c2.getCurriculumElementBeginDate());
+			} else {
+				c = c1.getCurriculumElementBeginDate().compareTo(c2.getCurriculumElementBeginDate());
+			}
+		}
+
+		if(c == 0) {
+			if(c1.getCurriculumElementDisplayName() == null || c2.getCurriculumElementDisplayName() == null) {
+				c = compareNullObjects(c1.getCurriculumElementDisplayName(), c2.getCurriculumElementDisplayName());
+			} else {
+				c = collator.compare(c1.getCurriculumElementDisplayName(), c2.getCurriculumElementDisplayName());
+			}
+		}
+
+		if(c == 0) {
+			if(c1.getCurriculumElementIdentifier() == null || c2.getCurriculumElementIdentifier() == null) {
+				c = compareNullObjects(c1.getCurriculumElementIdentifier(), c2.getCurriculumElementIdentifier());
+			} else {
+				c = collator.compare(c1.getCurriculumElementIdentifier(), c2.getCurriculumElementIdentifier());
+			}
+		}
+
+		if(c == 0) {
+
+			c = Long.compare(c1.getCurriculumElementKey().longValue(), c2.getCurriculumElementKey().longValue());
+		}
+		return c;
+	}
+
+	private int compareRepositoryEntry(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		int c = compareClosed(c1, c2);
+
+		if(c == 0) {
+			if(c1.getRepositoryEntryDisplayName() == null || c2.getRepositoryEntryDisplayName() == null) {
+				c = compareNullObjects(c1.getRepositoryEntryDisplayName(), c2.getRepositoryEntryDisplayName());
+			} else {
+				c = collator.compare(c1.getRepositoryEntryDisplayName(), c2.getRepositoryEntryDisplayName());
+			}
+		}
+
+		if(c == 0) {
+			if(c1.getRepositoryEntryExternalRef() == null || c2.getRepositoryEntryExternalRef() == null) {
+				c = compareNullObjects(c1.getRepositoryEntryExternalRef(), c2.getRepositoryEntryExternalRef());
+			} else {
+				c = collator.compare(c1.getRepositoryEntryExternalRef(), c2.getRepositoryEntryExternalRef());
+			}
+		}
+
+		if(c == 0) {
+			c = Long.compare(c1.getRepositoryEntryKey().longValue(), c2.getRepositoryEntryKey().longValue());
+		}
+		return c;
+	}
+
+	private int compareClosed(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		int c = 0;
+		if(c1.isClosedOrInactive() && !c2.isClosedOrInactive()) {
+			c = 1;
+		} else if(!c1.isClosedOrInactive() && c2.isClosedOrInactive()) {
+			c = -1;
+		}
+		return c;
+	}
+
+	private int compareDisplayName(CurriculumTreeWithViewsRow c1, CurriculumTreeWithViewsRow c2) {
+		String d1 = getDisplayName(c1);
+		String d2 = getDisplayName(c2);
+		if(d1 == null || d2 == null) {
+			return compareNullObjects(d1, d2);
+		}
+		return d1.compareTo(d2);
+	}
+
+	private String getDisplayName(CurriculumTreeWithViewsRow row) {
+		if(row.isCurriculumElementOnly()) {
+			return row.getCurriculumElementDisplayName();
+		}
+		if(row.isRepositoryEntryOnly()) {
+			return row.getRepositoryEntryDisplayName();
+		}
+		String d = row.getRepositoryEntryDisplayName();
+		if(d == null) {
+			d = row.getCurriculumElementDisplayName();
+		}
+		return d;
+	}
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementWithViewsDataModel.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementWithViewsDataModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..139c90cab922b73e805a36601195be9ff90eb2d3
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumElementWithViewsDataModel.java
@@ -0,0 +1,302 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTreeTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiBusinessPathModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.course.certificate.CertificateLight;
+import org.olat.modules.coach.model.EfficiencyStatementEntry;
+import org.olat.modules.coach.model.IdentityRepositoryEntryKey;
+import org.olat.modules.coach.model.IdentityResourceKey;
+import org.olat.modules.coach.ui.ProgressValue;
+import org.olat.modules.curriculum.CurriculumElementStatus;
+import org.olat.modules.lecture.model.LectureBlockStatistics;
+
+/**
+ * 
+ * Initial date: 11 mai 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CurriculumElementWithViewsDataModel extends DefaultFlexiTreeTableDataModel<CurriculumTreeWithViewsRow> implements FlexiBusinessPathModel {
+
+	private ConcurrentMap<IdentityResourceKey, CertificateLight> certificateMap;
+	private ConcurrentMap<IdentityRepositoryEntryKey, LectureBlockStatistics> lecturesStatisticsMap;
+
+	public CurriculumElementWithViewsDataModel(FlexiTableColumnModel columnsModel) {
+		super(columnsModel);
+	}
+	
+	@Override
+	public void filter(String searchString, List<FlexiTableFilter> filters) {
+		if(filters != null && !filters.isEmpty() && filters.get(0) != null) {
+			FlexiTableFilter filter = filters.get(0);
+			if(filter == null || filter.isShowAll()) {
+				setUnfilteredObjects();
+			} else {
+				List<CurriculumTreeWithViewsRow> filteredRows = new ArrayList<>(backupRows.size());
+				// curriculum element inactive -> all repo are inactives
+				// parent inactive, child is active -> parent is forced active
+				for(CurriculumTreeWithViewsRow row:backupRows) {
+					if (filters.get(0).getFilter().equals(FilterKeys.activ.name())) {
+						boolean accept = active(row);
+						if(accept) {
+							filteredRows.add(row);
+						}
+					} else if (filters.get(0).getFilter().equals(FilterKeys.withStatementOnly.name())) {
+						if (row.hasStatement()) {
+							filteredRows.add(row);
+						}
+					}
+
+				}
+				setFilteredObjects(filteredRows);
+			}
+		} else {
+			setUnfilteredObjects();
+		}
+	}
+	
+	private boolean active(CurriculumTreeWithViewsRow row) {
+		boolean active = true;
+		if(row.isCurriculumElementOnly() || row.isCurriculumElementWithEntry()) {
+			active = row.getCurriculumElementStatus() == CurriculumElementStatus.active;
+		}
+		if(active) {
+			for(CurriculumTreeWithViewsRow parent = row.getParent(); parent != null; parent=parent.getParent()) {
+				if(parent.isCurriculumElementOnly() || parent.isCurriculumElementWithEntry()) {
+					active &= row.getCurriculumElementStatus() == CurriculumElementStatus.active;
+				}
+			}
+		}
+		return active;
+	}
+	
+	@Override
+	public boolean hasChildren(int row) {
+		CurriculumTreeWithViewsRow element = getObject(row);
+		return element.hasChildren();
+	}
+
+	@Override
+	public Object getValueAt(int row, int col) {
+		CurriculumTreeWithViewsRow curriculum = getObject(row);
+		switch(ElementViewCols.values()[col]) {
+			case key: return curriculum.getKey();
+			case displayName:
+				return curriculum.getDisplayName();
+			case hasStatement:
+				return curriculum.hasStatement();
+			case identifier: {
+				String identifier;
+				if(curriculum.isRepositoryEntryOnly()) {
+					identifier = curriculum.getRepositoryEntryExternalRef();
+				} else {
+					identifier = curriculum.getCurriculumElementIdentifier();
+				}
+				return identifier;
+			}
+			case mark: return curriculum.getMarkLink();
+			case select: return curriculum.getSelectLink();
+			case details: return curriculum.getDetailsLink();
+			case start: return curriculum.getStartLink();
+			case calendars: return curriculum.getCalendarsLink();
+			case completion: return curriculum.getCompletionItem();
+			case score: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getScore() : null;
+			case passed: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getPassed() : null;
+			case certificate: return getCertificate(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+			case recertification: {
+				CertificateLight certificate = getCertificate(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return certificate == null ? null : certificate.getNextRecertificationDate();
+			}
+			case numberAssessments: {
+				ProgressValue val = null;
+				Integer totalNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getTotalNodes() : null;
+				if (totalNodes != null && totalNodes.intValue() > 0) {
+					val = new ProgressValue();
+					val.setTotal(totalNodes.intValue());
+					Integer attemptedNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getAttemptedNodes() : null;
+					val.setGreen(attemptedNodes == null ? 0 : attemptedNodes.intValue());
+				}
+				return val;
+			}
+			case progress: {
+				Integer totalNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getTotalNodes() : null;
+				if(totalNodes == null) {
+					ProgressValue val = new ProgressValue();
+					val.setTotal(100);
+					val.setGreen(0);
+					return val;
+				}
+
+				ProgressValue val = new ProgressValue();
+				val.setTotal(totalNodes.intValue());
+				Integer attemptedNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getAttemptedNodes() : null;
+				val.setGreen(attemptedNodes == null ? 0 : attemptedNodes.intValue());
+				return val;
+			}
+			case lastModification: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastModified() : null;
+			case lastUserModified: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastUserModified() : null;
+			case lastCoachModified: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastCoachModified() : null;
+			case plannedLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalPersonalPlannedLectures();
+			}
+			case attendedLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAttendedLectures();
+			}
+			case unauthorizedAbsenceLectures:
+			case absentLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAbsentLectures();
+			}
+			case authorizedAbsenceLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAuthorizedAbsentLectures();
+			}
+			case efficiencyStatement:
+				return curriculum.getEfficiencyStatementEntry() != null;
+			default: return "ERROR";
+		}
+	}
+
+	private CertificateLight getCertificate(EfficiencyStatementEntry entry) {
+		if(certificateMap != null) {
+			IdentityResourceKey key = new IdentityResourceKey(entry.getIdentityKey(), entry.getCourse().getOlatResource().getKey());
+			return certificateMap.get(key);
+		}
+		return null;
+	}
+
+	private LectureBlockStatistics getLectureBlockStatistics(EfficiencyStatementEntry entry) {
+		if(lecturesStatisticsMap != null) {
+			IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(entry);
+			return lecturesStatisticsMap.get(key);
+		}
+		return null;
+	}
+
+	public void setObjects(List<CurriculumTreeWithViewsRow> objects, ConcurrentMap<IdentityResourceKey, CertificateLight> certificates) {
+		setObjects(objects, certificates, null);
+	}
+
+	public void setObjects(List<CurriculumTreeWithViewsRow> objects,
+						   ConcurrentMap<IdentityResourceKey, CertificateLight> certificates,
+						   ConcurrentMap<IdentityRepositoryEntryKey, LectureBlockStatistics> lecturesStatisticsMap) {
+		setObjects(objects);
+		this.certificateMap = certificates;
+		this.lecturesStatisticsMap = lecturesStatisticsMap;
+	}
+
+	@Override
+	public CurriculumElementWithViewsDataModel createCopyWithEmptyList() {
+		return new CurriculumElementWithViewsDataModel(getTableColumnModel());
+	}
+
+	public enum ElementViewCols implements FlexiSortableColumnDef {
+		key("table.header.key"),
+		displayName("table.header.curriculum.element.displayName"),
+		hasStatement("table.header.curriculum.element.has.statement"),
+		identifier("table.header.curriculum.element.identifier"),
+		mark("table.header.mark"),
+		select("table.header.displayName"),
+		completion("table.header.completion"),
+		details("table.header.details"),
+		start("table.header.start"),
+		calendars("table.header.calendars"),
+		score("table.header.score"),
+		passed("table.header.passed"),
+		certificate("table.header.certificate"),
+		recertification("table.header.recertification"),
+		numberAssessments("table.header.number.assessments"),
+		progress("table.header.progress"),
+		lastModification("table.header.lastScoreDate"),
+		lastUserModified("table.header.lastUserModificationDate"),
+		lastCoachModified("table.header.lastCoachModificationDate"),
+		plannedLectures("table.header.planned.lectures"),
+		attendedLectures("table.header.attended.lectures"),
+		absentLectures("table.header.absent.lectures"),
+		unauthorizedAbsenceLectures("table.header.unauthorized.absence"),
+		authorizedAbsenceLectures("table.header.authorized.absence"),
+		efficiencyStatement("table.header.show"),
+		deleteEfficiencyStatement("table.action.delete"),
+		artefact("table.header.artefact");
+		
+		private final String i18nHeaderKey;
+		
+		private ElementViewCols(String i18nHeaderKey) {
+			this.i18nHeaderKey = i18nHeaderKey;
+		}
+
+		@Override
+		public boolean sortable() {
+			return false;
+		}
+
+		@Override
+		public String sortKey() {
+			return name();
+		}
+
+		@Override
+		public String i18nHeaderKey() {
+			return i18nHeaderKey;
+		}
+	}
+
+	@Override
+	public String getUrl(Component source, Object object, String action) {
+		if("select".equals(action) && object instanceof CurriculumTreeWithViewsRow) {
+			CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow)object;
+			if(row.getStartUrl() != null) {
+				return row.getStartUrl();
+			}
+			if(row.getDetailsUrl() != null) {
+				return row.getDetailsUrl();
+			}
+		}
+		return null;
+	}
+
+	public enum FilterKeys {
+		activ("filter.activ"),
+		withStatementOnly("filter.with.statement.only"),
+		showAll("show.all");
+
+		private final String i18nHeaderKey;
+
+		private FilterKeys(String i18nHeaderKey) {
+			this.i18nHeaderKey = i18nHeaderKey;
+		}
+
+		public String i18nHeaderKey() {
+			return i18nHeaderKey;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumKey.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumKey.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca48298d63dfbaaecb82a8bb17fee7511e2c5554
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumKey.java
@@ -0,0 +1,76 @@
+package org.olat.modules.coach.ui.curriculum.certificate;
+
+public class CurriculumKey {
+    private final Long curriculum;
+    private final Long curriculumElement;
+    private final boolean isWithoutCurriculum;
+
+    public CurriculumKey(Long curriculum, Long curriculumElement) {
+        this(curriculum, curriculumElement, false);
+    }
+
+    public CurriculumKey(Long curriculum, Long curriculumElement, boolean isWithoutCurriculum) {
+        this.curriculum = curriculum;
+        this.curriculumElement = curriculumElement;
+        this.isWithoutCurriculum = isWithoutCurriculum;
+    }
+
+    public Long getCurriculum() {
+        return curriculum;
+    }
+
+    public Long getCurriculumElement() {
+        return curriculumElement;
+    }
+
+    public boolean isWithoutCurriculum() {
+        return this.isWithoutCurriculum;
+    }
+
+    @Override
+    public String toString() {
+        return "CurriculumKey[" +
+                "curriculum=" + curriculum +
+                ", curriculumElement=" + curriculumElement +
+                ']';
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof CurriculumKey) {
+            CurriculumKey compareKey = (CurriculumKey) obj;
+            boolean equals = true;
+
+            // Compare curriculum
+            if ((curriculum == null && compareKey.getCurriculum() != null)
+                    || (curriculum != null && compareKey.getCurriculum() == null)) {
+                equals = false;
+            } else if ((curriculum != null && compareKey.getCurriculum() != null)
+                    && (!curriculum.equals(compareKey.getCurriculum()))) {
+                equals = false;
+            }
+
+            // Compare curriculumElement
+            if ((curriculumElement == null && compareKey.getCurriculumElement() != null)
+                    || (curriculumElement != null && compareKey.getCurriculumElement() == null)) {
+                equals = false;
+            } else if ((curriculumElement != null && compareKey.getCurriculumElement() != null)
+                    && (!curriculumElement.equals(compareKey.getCurriculumElement()))) {
+                equals = false;
+            }
+
+            return equals;
+        } else {
+            return  false;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return (curriculum == null ? 890112 : curriculum.hashCode()) + (curriculumElement == null ? 312739 : curriculumElement.hashCode());
+    }
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithView.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithView.java
new file mode 100644
index 0000000000000000000000000000000000000000..9a47e482353f5406cf1294b1a76b554721be3659
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithView.java
@@ -0,0 +1,56 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.util.List;
+
+import org.olat.repository.RepositoryEntryMyView;
+
+/**
+ * 
+ * Initial date: 8 Oct 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface CurriculumTreeWithView {
+	
+	public boolean isCurriculumMember();
+	
+	public CurriculumTreeWithView getParent();
+	
+	public List<RepositoryEntryMyView> getEntries();
+
+	public CurriculumKey getKey();
+	
+	public default boolean isParentOrSelf(CurriculumTreeWithView parent) {
+		boolean hasParent = false;
+		
+		if(getKey().equals(parent.getKey())) {
+			hasParent = true;
+		} else {
+			for(CurriculumTreeWithView parentRow = getParent(); parentRow != null; parentRow=parentRow.getParent()) {
+				if(parentRow.getKey().equals(parent.getKey())) {
+					hasParent = true;
+				}
+			}
+		}
+		return hasParent;
+	}
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithViewsRow.java b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithViewsRow.java
new file mode 100644
index 0000000000000000000000000000000000000000..6392755d53071e93b0168f7d4544a1cf5a4bda8d
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/CurriculumTreeWithViewsRow.java
@@ -0,0 +1,764 @@
+/**
+ * <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.modules.coach.ui.curriculum.certificate;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.olat.core.gui.components.form.flexible.elements.FormLink;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeTableNode;
+import org.olat.core.gui.components.progressbar.ProgressBarItem;
+import org.olat.core.id.OLATResourceable;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.filter.FilterFactory;
+import org.olat.course.assessment.AssessmentHelper;
+import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementListModel;
+import org.olat.modules.coach.model.EfficiencyStatementEntry;
+import org.olat.modules.curriculum.Curriculum;
+import org.olat.modules.curriculum.CurriculumCalendars;
+import org.olat.modules.curriculum.CurriculumElement;
+import org.olat.modules.curriculum.CurriculumElementMembership;
+import org.olat.modules.curriculum.CurriculumElementStatus;
+import org.olat.modules.curriculum.CurriculumElementType;
+import org.olat.modules.curriculum.CurriculumLearningProgress;
+import org.olat.repository.RepositoryEntryMyView;
+import org.olat.repository.RepositoryEntryStatusEnum;
+import org.olat.repository.ui.PriceMethod;
+import org.olat.repository.ui.RepositoyUIFactory;
+import org.olat.resource.OLATResource;
+
+/**
+ * 
+ * Initial date: 14 févr. 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CurriculumTreeWithViewsRow implements CurriculumTreeWithView, FlexiTreeTableNode {
+	
+	private boolean hasChildren;
+	private CurriculumTreeWithViewsRow parent;
+
+	private CurriculumKey parentKey;
+	private CurriculumKey key;
+
+	private final Curriculum curriculum;
+	private final CurriculumElement element;
+	private final CurriculumElementType elementType;
+	private final CurriculumElementMembership curriculumMembership;
+	private boolean curriculumMember;
+	private int level;
+
+	private boolean singleEntry;
+	private int elementEntryCount;
+	private OLATResource olatResource;
+	private RepositoryEntryMyView repositoryEntry;
+	
+	private String shortenedDescription;
+	private String representationalName;
+	
+	private RepositoryEntryStatusEnum status;
+	private boolean guests;
+	private boolean allUsers;
+	private boolean bookable;
+	private List<PriceMethod> accessTypes;
+
+	private boolean member;
+	private String thumbnailRelPath;
+	private boolean marked;
+
+	private String startUrl;
+	private String detailsUrl;
+
+	private FormLink startLink;
+	private FormLink detailsLink;
+	private FormLink markLink;
+	private FormLink selectLink;
+	private FormLink calendarsLink;
+	private ProgressBarItem completionItem;
+
+	private EfficiencyStatementEntry efficiencyStatementEntry;
+	private CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement certificateAndEfficiencyStatement;
+	private boolean hasStatement;
+	
+	public CurriculumTreeWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership, int myEntryCount) {
+		this.element = element;
+		elementType = element.getType();
+		this.curriculumMembership = curriculumMembership;
+		curriculumMember = curriculumMembership != null && curriculumMembership.hasMembership();
+		singleEntry = false;
+		elementEntryCount = myEntryCount;
+		this.curriculum = curriculum;
+		setKey();
+		setParentKey();
+		setShortenedDescription(element.getDescription());
+	
+		// calculate level of current curr element based on parent chain
+		for(CurriculumElement parentEl=element.getParent(); parentEl != null; parentEl=parentEl.getParent()) {
+			level++;
+		}
+	}
+
+	public CurriculumTreeWithViewsRow(Curriculum curriculum) {
+		this.curriculum = curriculum;
+		parentKey = null;
+		element = null;
+		elementType = null;
+		curriculumMembership = null;
+		curriculumMember = true;
+		level = -1;
+		setKey();
+	}
+
+	/**
+	 * Used to show the head parent of elements without any curriculum
+	 * @param representationalName
+	 */
+	public CurriculumTreeWithViewsRow(String representationalName) {
+		this.representationalName = representationalName;
+		curriculum = null;
+		parentKey = null;
+		element = null;
+		elementType = null;
+		curriculumMembership = null;
+		curriculumMember = false;
+		level = -1;
+		setKey();
+	}
+
+	/**
+	 * Used to show elements without any curriculum
+	 * @param repositoryEntryView
+	 */
+	public CurriculumTreeWithViewsRow(RepositoryEntryMyView repositoryEntryView) {
+		guests = repositoryEntryView.isGuests();
+		allUsers = repositoryEntryView.isAllUsers();
+		bookable = repositoryEntryView.isBookable();
+		status = repositoryEntryView.getEntryStatus();
+		repositoryEntry = repositoryEntryView;
+		olatResource = repositoryEntryView.getOlatResource();
+		marked = repositoryEntryView.isMarked();
+		setShortenedDescription(repositoryEntryView.getDescription());
+
+		curriculum = null;
+		parentKey = null;
+		element = null;
+		elementType = null;
+		curriculumMembership = null;
+		curriculumMember = false;
+		level = 0;
+		setKey(true);
+	}
+
+	public CurriculumTreeWithViewsRow(CertificateAndEfficiencyStatementListModel.CertificateAndEfficiencyStatement statement) {
+		this.certificateAndEfficiencyStatement = statement;
+
+		setShortenedDescription(statement.getDisplayName());
+		setKey(true);
+
+		curriculum = null;
+		parentKey = null;
+		element = null;
+		elementType = null;
+		curriculumMembership = null;
+		curriculumMember = false;
+		level = 0;
+	}
+
+	public CurriculumTreeWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership,
+									  RepositoryEntryMyView repositoryEntryView, boolean alone) {
+		this.element = element;
+		elementType = element == null ? null : element.getType();
+		this.curriculumMembership = curriculumMembership;
+		curriculumMember = curriculumMembership != null && curriculumMembership.hasMembership();
+		singleEntry = alone;
+		elementEntryCount = 0;
+
+		Long parentElementKey;
+		Long parentCurriculumKey = curriculum != null ? curriculum.getKey() : null;
+
+		if(alone) {
+			parentElementKey = element != null && element.getParent() != null ? element.getParent().getKey() : null;
+		} else {
+			parentElementKey = element == null ? null : element.getKey();
+			// add ourself as level
+			level++;
+		}
+		parentKey = new CurriculumKey(parentCurriculumKey, parentElementKey);
+		setKey();
+		
+		guests = repositoryEntryView.isGuests();
+		allUsers = repositoryEntryView.isAllUsers();
+		bookable = repositoryEntryView.isBookable();
+		status = repositoryEntryView.getEntryStatus();
+		repositoryEntry = repositoryEntryView;
+		olatResource = repositoryEntryView.getOlatResource();
+		marked = repositoryEntryView.isMarked();
+		setShortenedDescription(repositoryEntryView.getDescription());
+		
+		// calculate level of current curr element based on parent chain
+		for(CurriculumElement parentEl=element.getParent(); parentEl != null; parentEl=parentEl.getParent()) {
+			level++;
+		}
+
+		this.curriculum = curriculum;
+	}
+
+	@Override
+	public CurriculumKey getKey() {
+		return this.key;
+	}
+	
+	public boolean isActive() {
+		if(element != null) {
+			return element.getElementStatus() == null
+					|| element.getElementStatus() == CurriculumElementStatus.active;
+		}
+		return true;
+	}
+
+	public Curriculum getCurriculum() {
+		return curriculum;
+	}
+	
+	public String getDisplayName() {
+		if(repositoryEntry != null) {
+			return repositoryEntry.getDisplayname();
+		} else if(element != null) {
+			return element.getDisplayName();
+		} else if (curriculum != null) {
+			return curriculum.getDisplayName();
+		} else if (certificateAndEfficiencyStatement != null) {
+			return certificateAndEfficiencyStatement.getDisplayName();
+		} else if (representationalName != null) {
+			return representationalName;
+		}
+		return null;
+	}
+
+	public boolean isCurriculum() {
+		return curriculum != null && element == null && repositoryEntry == null && parentKey == null;
+	}
+	
+	public boolean isCurriculumElementOnly() {
+		return element != null && repositoryEntry == null;
+	}
+	
+	public boolean isRepositoryEntryOnly() {
+		return element != null && repositoryEntry != null && !singleEntry;
+	}
+	
+	public boolean isCurriculumElementWithEntry() {
+		return element != null && repositoryEntry != null && singleEntry;
+	}
+	
+	public String getCurriculumElementIdentifier() {
+		if ((repositoryEntry == null || singleEntry) && element != null) {
+			return element.getIdentifier();
+		} else if (isCurriculum()) {
+			return curriculum.getIdentifier();
+		} else {
+			return null;
+		}
+	}
+	
+	public String getCurriculumElementExternalId() {
+		return element == null ? null : element.getExternalId();
+	}
+	
+	public CurriculumElementStatus getCurriculumElementStatus() {
+		return element == null ? null : element.getElementStatus();
+	}
+	
+	public String getCurriculumElementDisplayName() {
+		if ((representationalName == null || singleEntry) && element != null) {
+			return element.getDisplayName();
+		} else if (isCurriculum()) {
+			return curriculum.getDisplayName();
+		} else if (repositoryEntry != null) {
+			return repositoryEntry.getDisplayname();
+		} else if (representationalName != null) {
+			return representationalName;
+		} else {
+			return null;
+		}
+	}
+
+	public Long getCurriculumKey() {
+		return curriculum == null ? null : curriculum.getKey();
+	}
+
+	public Long getCurriculumElementKey() {
+		return element == null ? null : element.getKey();
+	}
+	
+	public Date getCurriculumElementBeginDate() {
+		return element == null ? null : element.getBeginDate();
+	}
+	
+	public Date getCurriculumElementEndDate() {
+		return element == null ? null : element.getEndDate();
+	}
+	
+	public Long getCurriculumElementPos() {
+		return element == null ? null : element.getPos();
+	}
+	
+	public String getCurriculumElementTypeCssClass() {
+		return elementType == null ? null : element.getType().getCssClass();
+	}
+
+	public String getCurriculumElementTypeName() {
+		return elementType == null ? null : element.getType().getDisplayName();
+	}
+	
+	public boolean isCalendarsEnabled() {
+		boolean enabled = false;
+		if(element != null) {
+			if(element.getCalendars() == CurriculumCalendars.enabled) {
+				enabled = true;
+			} else if(element.getCalendars() == CurriculumCalendars.inherited && elementType != null) {
+				enabled = elementType.getCalendars() == CurriculumCalendars.enabled;
+			}
+		}
+		return enabled;
+	}
+	
+	public boolean isLearningProgressEnabled() {
+		boolean enabled = false;
+		if(element != null) {
+			if(element.getLearningProgress() == CurriculumLearningProgress.enabled) {
+				enabled = true;
+			} else if(element.getLearningProgress() == CurriculumLearningProgress.inherited && elementType != null) {
+				enabled = elementType.getLearningProgress() == CurriculumLearningProgress.enabled;
+			}
+		}
+		return enabled;
+	}
+	
+	public int getCurriculumElementRepositoryEntryCount() {
+		return elementEntryCount;
+	}
+	
+	public int getLevel() {
+		return level;
+	}
+
+	
+	public String getExternalId() {
+		String extId = null;
+		if (element != null && element.getExternalId() != null) {
+			extId = element.getExternalId();
+		}
+		if (repositoryEntry != null && repositoryEntry.getExternalId() != null) {
+			if (extId != null) {
+				extId += " ";
+				extId += repositoryEntry.getExternalId();
+			} else {
+				extId += repositoryEntry.getExternalId();				
+			}
+		}
+		return extId;
+	}
+	
+	public String getMaterializedPathKeys() {
+		return element.getMaterializedPathKeys();
+	}
+	
+	public String getShortenedDescription() {
+		return shortenedDescription;
+	}
+
+	private void setShortenedDescription(String description) {
+		if(description != null) {
+			String shortDesc = FilterFactory.getHtmlTagsFilter().filter(description);
+			if(shortDesc.length() > 255) {
+				shortenedDescription = shortDesc.substring(0, 255);
+			} else {
+				shortenedDescription = shortDesc;
+			}
+		} else {
+			shortenedDescription = "";
+		}
+	}
+
+	private void setParentKey() {
+		Long curriculumKey = element != null && curriculum != null ? curriculum.getKey() : null;
+		Long curriculumElementParentKey = element != null && element.getParent() != null ? element.getParent().getKey() : null;
+
+		parentKey = new CurriculumKey(curriculumKey, curriculumElementParentKey);
+	}
+
+	private void setKey() {
+		Long curriculumKey = curriculum != null ? curriculum.getKey() : null;
+		Long curriculumElementKey = element != null ? element.getKey() : null;
+
+		key = new CurriculumKey(curriculumKey, curriculumElementKey);
+	}
+
+	private void setKey(boolean isWithoutCurriculum) {
+		key = new CurriculumKey(null, null, isWithoutCurriculum);
+	}
+	
+	public boolean isClosed() {
+		return status.decommissioned();
+	}
+
+	public boolean isSingleEntry() {
+		return singleEntry;
+	}
+	
+	public boolean isMarked() {
+		return marked;
+	}
+	
+	public void setMarked(boolean marked) {
+		this.marked = marked;
+	}
+	
+	public RepositoryEntryStatusEnum getEntryStatus() {
+		return status;
+	}
+	
+	public boolean isAllUsers() {
+		return allUsers;
+	}
+	
+	public boolean isGuests() {
+		return guests;
+	}
+	
+	public boolean isBookable() {
+		return bookable;
+	}
+	
+	public boolean isThumbnailAvailable() {
+		return StringHelper.containsNonWhitespace(thumbnailRelPath);
+	}
+	
+	public String getThumbnailRelPath() {
+		return thumbnailRelPath;
+	}
+
+	public void setThumbnailRelPath(String thumbnailRelPath) {
+		this.thumbnailRelPath = thumbnailRelPath;
+	}
+	
+	public Long getRepositoryEntryKey() {
+		return repositoryEntry == null ? null : repositoryEntry.getKey();
+	}
+	
+	public String getRepositoryEntryDisplayName() {
+		if (repositoryEntry != null) {
+			return repositoryEntry.getDisplayname();
+		} else if (certificateAndEfficiencyStatement != null) {
+			return certificateAndEfficiencyStatement.getDisplayName();
+		} else {
+			return null;
+		}
+	}
+	
+	public String getRepositoryEntryExternalRef() {
+		return repositoryEntry == null ? null : repositoryEntry.getExternalRef();
+	}
+	
+	public String getRepositoryEntryCssClass() {
+		return olatResource == null ? "" : RepositoyUIFactory.getIconCssClass(olatResource.getResourceableTypeName());
+	}
+	
+	public String getRepositoryEntryAuthors() {
+		return repositoryEntry == null ? null : repositoryEntry.getAuthors();
+	}
+	
+	public String getRepositoryEntryLocation() {
+		return repositoryEntry == null ? null : repositoryEntry.getLocation();
+	}
+	
+	public String getRepositoryEntryShortenedDescription() {
+		return repositoryEntry == null ? null : repositoryEntry.getDescription();
+	}
+	
+	public Date getLifecycleStart() {
+		return repositoryEntry == null || repositoryEntry.getLifecycle() == null
+				? null : repositoryEntry.getLifecycle().getValidFrom();
+	}
+	
+	public Date getLifecycleEnd() {
+		return repositoryEntry == null || repositoryEntry.getLifecycle() == null
+				? null : repositoryEntry.getLifecycle().getValidTo();
+	}
+	
+	public String getLifecycleSoftKey() {
+		return repositoryEntry == null || repositoryEntry.getLifecycle() == null || repositoryEntry.getLifecycle().isPrivateCycle()
+				? null : repositoryEntry.getLifecycle().getSoftKey();
+	}
+	
+	public String getLifecycleLabel() {
+		return repositoryEntry == null || repositoryEntry.getLifecycle() == null || repositoryEntry.getLifecycle().isPrivateCycle()
+				? null : repositoryEntry.getLifecycle().getLabel();
+	}
+	
+	public String getScore() {
+		return repositoryEntry == null ? null : AssessmentHelper.getRoundedScore(repositoryEntry.getScore());
+	}
+	
+	public boolean isPassed() {
+		return repositoryEntry == null || repositoryEntry.getPassed() == null
+				? false : repositoryEntry.getPassed().booleanValue();
+	}
+	
+	public boolean isFailed() {
+		return repositoryEntry == null || repositoryEntry.getPassed() == null
+				? false : !repositoryEntry.getPassed().booleanValue();
+	}
+	
+	public Double getRepositoryEntryCompletion() {
+		return repositoryEntry != null? repositoryEntry.getCompletion(): null;
+	}
+	
+	public OLATResourceable getRepositoryEntryResourceable() {
+		return repositoryEntry;
+	}
+	
+	public OLATResource getOlatResource() {
+		return olatResource;
+	}
+	
+	@Override
+	public List<RepositoryEntryMyView> getEntries() {
+		if(repositoryEntry == null) {
+			return Collections.emptyList();
+		}
+		return Collections.singletonList(repositoryEntry);
+	}
+
+	/**
+	 * Is member if the row as some type of access control
+	 * @return
+	 */
+	public boolean isMember() {
+		return member;
+	}
+	
+	public void setMember(boolean member) {
+		this.member = member;
+	}
+
+	public CurriculumElementMembership getCurriculumMembership() {
+		return curriculumMembership;
+	}
+
+	@Override
+	public boolean isCurriculumMember() {
+		return curriculumMember;
+	}
+
+	public void setCurriculumMember(boolean curriculumMember) {
+		this.curriculumMember = curriculumMember;
+	}
+
+	public List<PriceMethod> getAccessTypes() {
+		return accessTypes;
+	}
+
+	public void setAccessTypes(List<PriceMethod> accessTypes) {
+		this.accessTypes = accessTypes;
+	}
+	
+	public boolean isClosedOrInactive() {
+		if(isCurriculumElementOnly()) {
+			return element.getElementStatus() == CurriculumElementStatus.inactive || element.getElementStatus() == CurriculumElementStatus.deleted;
+		}
+		if(isRepositoryEntryOnly()) {
+			return status != null && status.decommissioned();
+		}
+		return (status != null && status.decommissioned())
+				|| (element != null &&  element.getElementStatus() != null
+				&& (element.getElementStatus() == CurriculumElementStatus.inactive || element.getElementStatus() == CurriculumElementStatus.deleted));
+	}
+
+	@Override
+	public CurriculumTreeWithViewsRow getParent() {
+		return parent;
+	}
+	
+	public void setParent(CurriculumTreeWithViewsRow parent) {
+		this.parent = parent;
+		if(parent != null) {
+			parent.hasChildren = true;
+		}
+	}
+	
+	public boolean hasChildren() {
+		return hasChildren;
+	}
+
+	public CurriculumKey getParentKey() {
+		return parentKey;
+	}
+	
+	public FormLink getMarkLink() {
+		return markLink;
+	}
+	
+	public String getMarkLinkName() {
+		if(markLink != null) {
+			return markLink.getComponent().getComponentName();
+		}
+		return null;
+	}
+	
+	public void setMarkLink(FormLink markLink) {
+		this.markLink = markLink;
+	}
+	
+	public String getStartLinkName() {
+		return startLink == null ? null : startLink.getComponent().getComponentName();
+	}
+	
+	public FormLink getStartLink() {
+		return startLink;
+	}
+	
+	public void setStartLink(FormLink startLink, String startURL) {
+		this.startLink = startLink;
+		this.startUrl = startURL;
+	}
+
+	public String getStartUrl() {
+		return startUrl;
+	}
+	
+	public String getDetailsLinkName() {
+		return detailsLink == null ? null : detailsLink.getComponent().getComponentName();
+	}
+
+	public FormLink getDetailsLink() {
+		return detailsLink;
+	}
+
+	public void setDetailsLink(FormLink detailsLink, String detailsURL) {
+		this.detailsLink = detailsLink;
+		this.detailsUrl = detailsURL;
+	}
+
+	public String getDetailsUrl() {
+		return detailsUrl;
+	}
+	
+	public String getSelectLinkName() {
+		return selectLink == null ? null : selectLink.getComponent().getComponentName();
+	}
+	
+	public FormLink getSelectLink() {
+		return selectLink;
+	}
+	
+	public void setSelectLink(FormLink selectLink) {
+		this.selectLink = selectLink;
+	}
+	
+	public FormLink getCalendarsLink() {
+		return calendarsLink;
+	}
+
+	public void setCalendarsLink(FormLink calendarsLink) {
+		this.calendarsLink = calendarsLink;
+	}
+	
+	public String getCalendarsLinkName() {
+		return calendarsLink == null ? null : calendarsLink.getComponent().getComponentName();
+	}
+	
+	public ProgressBarItem getCompletionItem() {
+		return completionItem;
+	}
+	
+	public void setCompletionItem(ProgressBarItem completionItem) {
+		this.completionItem = completionItem;
+	}
+	
+	public String getCompletionItemName() {
+		return completionItem == null ? null : completionItem.getComponent().getComponentName();
+	}
+
+	public EfficiencyStatementEntry getEfficiencyStatementEntry() {
+		return this.efficiencyStatementEntry;
+	}
+
+	public void setEfficiencyStatementEntry(EfficiencyStatementEntry efficiencyStatementEntry) {
+		this.efficiencyStatementEntry = efficiencyStatementEntry;
+	}
+
+	public boolean hasStatement() {
+		return hasStatement;
+	}
+
+	public void setHasStatement(boolean hasStatement) {
+		if (parent != null) {
+			parent.setHasStatement(true);
+		}
+		this.hasStatement = hasStatement;
+	}
+
+	@Override
+	public String getCrump() {
+		return element.getDisplayName();
+	}
+
+	@Override
+	public int hashCode() {
+		return (element == null ? 73465971 : element.getKey().hashCode())
+				+ (repositoryEntry == null ?-3726247 : repositoryEntry.getKey().hashCode());
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if(this == obj) {
+			return true;
+		}
+		if(obj instanceof CurriculumTreeWithViewsRow) {
+			CurriculumTreeWithViewsRow row = (CurriculumTreeWithViewsRow)obj;
+			return ((element == null && row.element == null && curriculum!= null && row.curriculum != null && curriculum.getKey().equals(row.curriculum.getKey()))
+							|| (element != null && row.element != null && element.getKey().equals(row.element.getKey())))
+					&& ((repositoryEntry == null && row.repositoryEntry == null)
+							|| (repositoryEntry != null && row.repositoryEntry != null && repositoryEntry.getKey().equals(row.repositoryEntry.getKey())));
+		}
+		return false;
+	}
+	
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		if(isCurriculumElementOnly()) {
+			sb.append("element[key").append(element.getKey()).append(":identifier=").append(element.getIdentifier()).append("]");
+		} else if(isRepositoryEntryOnly()) {
+			sb.append("repositoryEntry[key").append(repositoryEntry.getKey()).append(":identifier=").append(repositoryEntry.getExternalRef()).append("]");
+		} else if(isCurriculumElementWithEntry()) {
+			sb.append("composite[key").append(element.getKey()).append(":identifier=").append(element.getIdentifier()).append("]")
+			  .append("entry[key").append(repositoryEntry.getKey()).append(":identifier=").append(repositoryEntry.getExternalRef()).append("]");
+		} else if(isCurriculum()) {
+			sb.append("curriculum[key").append(curriculum.getKey()).append(":identifier=").append(curriculum.getIdentifier()).append("]");
+		}
+		
+		return sb.toString();
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/_content/course_list_wrapper.html b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/certificate_list_wrapper.html
similarity index 100%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/_content/course_list_wrapper.html
rename to src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/certificate_list_wrapper.html
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/_content/curriculum_element_list.html b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/curriculum_element_list.html
similarity index 100%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/_content/curriculum_element_list.html
rename to src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/curriculum_element_list.html
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/_content/curriculum_list.html b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/curriculum_list.html
similarity index 100%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/_content/curriculum_list.html
rename to src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_content/curriculum_list.html
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_de.properties
new file mode 100644
index 0000000000000000000000000000000000000000..87a51a349088f79cb84addae67475bb1435634da
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_de.properties
@@ -0,0 +1,4 @@
+curriculum.foreign.entries=Sonstige Kurse
+curriculum.toggle.description=Curriculum-Struktur anzeigen
+filter.with.statement.only=Nur mit Leistungsnachweis
+filter.activ=Nur aktiv
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_en.properties
new file mode 100644
index 0000000000000000000000000000000000000000..75ff302635bd7a30ed7ccb6ad04a608b350f42d0
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/certificate/_i18n/LocalStrings_en.properties
@@ -0,0 +1,4 @@
+curriculum.foreign.entries=Other courses
+curriculum.toggle.description=Show curriculum structure
+filter.with.statement.only=With efficiency statement only
+filter.activ=Only active
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsRow.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseCurriculumTreeWithViewsRow.java
similarity index 92%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsRow.java
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseCurriculumTreeWithViewsRow.java
index d09fedba7228e48adc726e22ebce31f0e5543b81..e215e7b57be3eaa42f09e8e318f6427bddd0e6ad 100644
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementWithViewsRow.java
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseCurriculumTreeWithViewsRow.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.modules.coach.ui.curriculum;
+package org.olat.modules.coach.ui.curriculum.course;
 
 import java.util.Collections;
 import java.util.Date;
@@ -30,6 +30,7 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.filter.FilterFactory;
 import org.olat.course.assessment.AssessmentHelper;
+import org.olat.modules.coach.model.EfficiencyStatementEntry;
 import org.olat.modules.curriculum.Curriculum;
 import org.olat.modules.curriculum.CurriculumCalendars;
 import org.olat.modules.curriculum.CurriculumElement;
@@ -50,10 +51,10 @@ import org.olat.resource.OLATResource;
  * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  *
  */
-public class CurriculumElementWithViewsRow implements CurriculumElementWithView, FlexiTreeTableNode {
+public class CourseCurriculumTreeWithViewsRow implements CurriculumElementWithView, FlexiTreeTableNode {
 	
 	private boolean hasChildren;
-	private CurriculumElementWithViewsRow parent;
+	private CourseCurriculumTreeWithViewsRow parent;
 
 	private Long parentKey;
 
@@ -91,8 +92,10 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 	private FormLink selectLink;
 	private FormLink calendarsLink;
 	private ProgressBarItem completionItem;
+
+	private EfficiencyStatementEntry efficiencyStatementEntry;
 	
-	public CurriculumElementWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership, int myEntryCount) {
+	public CourseCurriculumTreeWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership, int myEntryCount) {
 		this.element = element;
 		elementType = element.getType();
 		this.curriculumMembership = curriculumMembership;
@@ -109,7 +112,7 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 		}
 	}
 
-	public CurriculumElementWithViewsRow(Curriculum curriculum) {
+	public CourseCurriculumTreeWithViewsRow(Curriculum curriculum) {
 		this.curriculum = curriculum;
 		parentKey = null;
 		element = null;
@@ -123,7 +126,7 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 	 * Used to show the head parent of elements without any curriculum
 	 * @param representationalName
 	 */
-	public CurriculumElementWithViewsRow(String representationalName) {
+	public CourseCurriculumTreeWithViewsRow(String representationalName) {
 		this.representationalName = representationalName;
 		curriculum = null;
 		parentKey = null;
@@ -138,7 +141,7 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 	 * Used to show elements without any curriculum
 	 * @param repositoryEntryView
 	 */
-	public CurriculumElementWithViewsRow(RepositoryEntryMyView repositoryEntryView) {
+	public CourseCurriculumTreeWithViewsRow(RepositoryEntryMyView repositoryEntryView) {
 		guests = repositoryEntryView.isGuests();
 		allUsers = repositoryEntryView.isAllUsers();
 		bookable = repositoryEntryView.isBookable();
@@ -157,8 +160,8 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 		level = 0;
 	}
 
-	public CurriculumElementWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership,
-                                         RepositoryEntryMyView repositoryEntryView, boolean alone) {
+	public CourseCurriculumTreeWithViewsRow(Curriculum curriculum, CurriculumElement element, CurriculumElementMembership curriculumMembership,
+											RepositoryEntryMyView repositoryEntryView, boolean alone) {
 		this.element = element;
 		elementType = element == null ? null : element.getType();
 		this.curriculumMembership = curriculumMembership;
@@ -215,7 +218,7 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 			return element.getDisplayName();
 		} else if (curriculum != null) {
 			return curriculum.getDisplayName();
-		}
+		} else
 		return null;
 	}
 
@@ -535,11 +538,11 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 	}
 
 	@Override
-	public CurriculumElementWithViewsRow getParent() {
+	public CourseCurriculumTreeWithViewsRow getParent() {
 		return parent;
 	}
 	
-	public void setParent(CurriculumElementWithViewsRow parent) {
+	public void setParent(CourseCurriculumTreeWithViewsRow parent) {
 		this.parent = parent;
 		if(parent != null) {
 			parent.hasChildren = true;
@@ -639,6 +642,14 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 		return completionItem == null ? null : completionItem.getComponent().getComponentName();
 	}
 
+	public EfficiencyStatementEntry getEfficiencyStatementEntry() {
+		return this.efficiencyStatementEntry;
+	}
+
+	public void setEfficiencyStatementEntry(EfficiencyStatementEntry efficiencyStatementEntry) {
+		this.efficiencyStatementEntry = efficiencyStatementEntry;
+	}
+
 	@Override
 	public String getCrump() {
 		return element.getDisplayName();
@@ -655,8 +666,8 @@ public class CurriculumElementWithViewsRow implements CurriculumElementWithView,
 		if(this == obj) {
 			return true;
 		}
-		if(obj instanceof CurriculumElementWithViewsRow) {
-			CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow)obj;
+		if(obj instanceof CourseCurriculumTreeWithViewsRow) {
+			CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow)obj;
 			return ((element == null && row.element == null && curriculum!= null && row.curriculum != null && curriculum.getKey().equals(row.curriculum.getKey()))
 							|| (element != null && row.element != null && element.getKey().equals(row.element.getKey())))
 					&& ((repositoryEntry == null && row.repositoryEntry == null)
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CourseListWrapperController.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseListWrapperController.java
similarity index 82%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/CourseListWrapperController.java
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseListWrapperController.java
index a1544fec257699ea68009f28fae36f3c11db421b..4da55e05b58eaf46f2ac6b0f17b45820f187faf7 100644
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CourseListWrapperController.java
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CourseListWrapperController.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.modules.coach.ui.curriculum;
+package org.olat.modules.coach.ui.curriculum.course;
 
 import java.util.List;
 
@@ -36,9 +36,9 @@ import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.core.util.event.GenericEventListener;
 import org.olat.core.util.resource.OresHelper;
-import org.olat.modules.coach.UserRelationSecurityCallback;
+import org.olat.modules.coach.RoleSecurityCallback;
 import org.olat.modules.coach.model.StudentStatEntry;
-import org.olat.modules.coach.ui.UserRelationEnrollmentListController;
+import org.olat.modules.coach.ui.EnrollmentListController;
 import org.olat.modules.curriculum.CurriculumModule;
 import org.olat.modules.curriculum.CurriculumRef;
 import org.olat.modules.curriculum.CurriculumSecurityCallback;
@@ -53,11 +53,11 @@ public class CourseListWrapperController extends BasicController implements Acti
     private final Identity mentee;
     private final StudentStatEntry statEntry;
     private final CurriculumSecurityCallback curriculumSecurityCallback;
-    private final UserRelationSecurityCallback userRelationSecurityCallback;
+    private final RoleSecurityCallback roleSecurityCallback;
     private final List<CurriculumRef> curriculumRefs;
 
     private CurriculumElementListController curriculumListController;
-    private UserRelationEnrollmentListController userRelationEnrollmentListController;
+    private EnrollmentListController enrollmentListController;
 
     private Link curriculumShow;
     private Link curriculumHide;
@@ -69,18 +69,18 @@ public class CourseListWrapperController extends BasicController implements Acti
     @Autowired
     CurriculumModule curriculumModule;
 
-    public CourseListWrapperController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, Identity mentee, CurriculumSecurityCallback curriculumSecurityCallback, UserRelationSecurityCallback userRelationSecurityCallback, List<CurriculumRef> curriculumRefs, StudentStatEntry statEntry) {
+    public CourseListWrapperController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel, Identity mentee, CurriculumSecurityCallback curriculumSecurityCallback, RoleSecurityCallback roleSecurityCallback, List<CurriculumRef> curriculumRefs, StudentStatEntry statEntry) {
         super(ureq, wControl);
 
         this.stackPanel = stackPanel;
         this.mentee = mentee;
         this.curriculumSecurityCallback = curriculumSecurityCallback;
-        this.userRelationSecurityCallback = userRelationSecurityCallback;
+        this.roleSecurityCallback = roleSecurityCallback;
         this.curriculumRefs = curriculumRefs;
         this.statEntry = statEntry;
 
         content = createVelocityContainer("course_list_wrapper");
-        showCurriculum = curriculumModule.isEnabled() && userRelationSecurityCallback.canViewCoursesAndCurriculum();
+        showCurriculum = curriculumModule.isEnabled() && roleSecurityCallback.canViewCoursesAndCurriculum();
 
         if (showCurriculum) {
             curriculumShow = LinkFactory.createLink("off", content, this);
@@ -144,7 +144,7 @@ public class CourseListWrapperController extends BasicController implements Acti
 
         if (curriculumListController == null) {
             WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType(WITH_CURRICULUM), null);
-            curriculumListController = new CurriculumElementListController(ureq, bwControl, stackPanel, mentee, curriculumRefs, curriculumSecurityCallback, userRelationSecurityCallback);
+            curriculumListController = new CurriculumElementListController(ureq, bwControl, stackPanel, mentee, curriculumRefs, curriculumSecurityCallback, roleSecurityCallback);
             listenTo(curriculumListController);
         }
 
@@ -157,15 +157,15 @@ public class CourseListWrapperController extends BasicController implements Acti
     public Activateable2 hideCurriculumStructure(UserRequest ureq) {
         showCurriculum = false;
 
-        if (userRelationEnrollmentListController == null) {
+        if (enrollmentListController == null) {
             WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableType(WITHOUT_CURRICULM), null);
-            userRelationEnrollmentListController = new UserRelationEnrollmentListController(ureq, bwControl, stackPanel, statEntry, mentee, userRelationSecurityCallback);
-            listenTo(userRelationEnrollmentListController);
+            enrollmentListController = new EnrollmentListController(ureq, bwControl, stackPanel, statEntry, mentee, roleSecurityCallback);
+            listenTo(enrollmentListController);
         }
 
         content.contextPut("showCurriculum", showCurriculum);
-        content.put("content", userRelationEnrollmentListController.getInitialComponent());
-    	addToHistory(ureq, userRelationEnrollmentListController);
-        return userRelationEnrollmentListController;
+        content.put("content", enrollmentListController.getInitialComponent());
+    	addToHistory(ureq, enrollmentListController);
+        return enrollmentListController;
     }
 }
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementCompositeRenderer.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementCompositeRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7ca1336ac2ced47bc60327ee3756dbf7055854a
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementCompositeRenderer.java
@@ -0,0 +1,52 @@
+/**
+ * <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.modules.coach.ui.curriculum.course;
+
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer;
+import org.olat.core.gui.render.Renderer;
+import org.olat.core.gui.render.StringOutput;
+import org.olat.core.gui.render.URLBuilder;
+import org.olat.core.gui.translator.Translator;
+
+/**
+ * 
+ * Initial date: 10 août 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CurriculumElementCompositeRenderer extends StaticFlexiCellRenderer {
+	
+	public CurriculumElementCompositeRenderer(String action, FlexiCellRenderer labelDelegate) {
+		super(action, labelDelegate);
+	}
+
+	@Override
+	public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source,
+			URLBuilder ubu, Translator translator) {
+		CourseCurriculumTreeWithViewsRow view = (CourseCurriculumTreeWithViewsRow)source.getFlexiTableElement().getTableDataModel().getObject(row);
+		if(view.isCurriculumElementOnly()) {
+			getLabelDelegate().render(renderer, target, cellValue, row, source, ubu, translator);
+		} else {
+			super.render(renderer, target, cellValue, row, source, ubu, translator);
+		}
+	}
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementListController.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementListController.java
similarity index 84%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementListController.java
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementListController.java
index a728565415fd99e4df33ac65cddc80b8011d7507..af2ba1035232603f878fd5566e8101612aee7e2f 100644
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementListController.java
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementListController.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.modules.coach.ui.curriculum;
+package org.olat.modules.coach.ui.curriculum.course;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -79,8 +79,8 @@ import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.course.CorruptedCourseException;
 import org.olat.modules.assessment.AssessmentEntryCompletion;
 import org.olat.modules.assessment.AssessmentService;
-import org.olat.modules.coach.UserRelationSecurityCallback;
-import org.olat.modules.coach.ui.curriculum.CurriculumElementWithViewsDataModel.ElementViewCols;
+import org.olat.modules.coach.RoleSecurityCallback;
+import org.olat.modules.coach.ui.curriculum.course.CurriculumElementWithViewsDataModel.ElementViewCols;
 import org.olat.modules.curriculum.Curriculum;
 import org.olat.modules.curriculum.CurriculumElement;
 import org.olat.modules.curriculum.CurriculumElementMembership;
@@ -137,7 +137,7 @@ public class CurriculumElementListController extends FormBasicController impleme
     private final MapperKey mapperThumbnailKey;
     private final Identity assessedIdentity;
     private final CurriculumSecurityCallback curriculumSecurityCallback;
-    private final UserRelationSecurityCallback userRelationSecurityCallback;
+    private final RoleSecurityCallback roleSecurityCallback;
 
     private RepositoryEntryDetailsController detailsCtrl;
     private CurriculumElementCalendarController calendarsCtrl;
@@ -162,12 +162,12 @@ public class CurriculumElementListController extends FormBasicController impleme
     private BaseSecurity securityManager;
 
     public CurriculumElementListController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
-                                           Identity assessedIdentity, List<CurriculumRef> curriculumRefList, CurriculumSecurityCallback curriculumSecurityCallback, UserRelationSecurityCallback userRelationSecurityCallback) {
+                                           Identity assessedIdentity, List<CurriculumRef> curriculumRefList, CurriculumSecurityCallback curriculumSecurityCallback, RoleSecurityCallback roleSecurityCallback) {
         super(ureq, wControl, "curriculum_element_list", Util.createPackageTranslator(CurriculumListController.class, RepositoryService.class, ureq.getLocale()));
         this.curriculumRefList = curriculumRefList;
         this.stackPanel = stackPanel;
         this.curriculumSecurityCallback = curriculumSecurityCallback;
-        this.userRelationSecurityCallback = userRelationSecurityCallback;
+        this.roleSecurityCallback = roleSecurityCallback;
         this.assessedIdentity = assessedIdentity;
         this.curriculumList = curriculumService.getMyCurriculums(assessedIdentity);
         guestOnly = ureq.getUserSession().getRoles().isGuestOnly();
@@ -185,18 +185,25 @@ public class CurriculumElementListController extends FormBasicController impleme
     @Override
     protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
         FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+
         columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.key));
+
         TreeNodeFlexiCellRenderer treeNodeRenderer = new TreeNodeFlexiCellRenderer("select");
         columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.displayName, treeNodeRenderer));
+
         DefaultFlexiColumnModel elementIdentifierCol = new DefaultFlexiColumnModel(ElementViewCols.identifier, "select");
         elementIdentifierCol.setCellRenderer(new CurriculumElementCompositeRenderer("select", new TextFlexiCellRenderer()));
         columnsModel.addFlexiColumnModel(elementIdentifierCol);
-        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.select));
-        columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.details));
-        if (userRelationSecurityCallback.canViewCourseProgressAndStatus()) {
+
+        // Name column
+        // columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(false, ElementViewCols.select));
+        // Info site column
+        // columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.details));
+
+        if (roleSecurityCallback.canViewCourseProgressAndStatus()) {
             columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.completion));
         }
-        if (userRelationSecurityCallback.canViewCalendar()) {
+        if (roleSecurityCallback.canViewCalendar()) {
             columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ElementViewCols.calendars));
         }
 
@@ -238,7 +245,7 @@ public class CurriculumElementListController extends FormBasicController impleme
     @Override
     public String getRowCssClass(FlexiTableRendererType type, int pos) {
         StringBuilder sb = new StringBuilder(64);
-        CurriculumElementWithViewsRow rowWithView = tableModel.getObject(pos);
+        CourseCurriculumTreeWithViewsRow rowWithView = tableModel.getObject(pos);
         if (type == FlexiTableRendererType.custom) {
             sb.append("o_table_row ");
 
@@ -258,7 +265,7 @@ public class CurriculumElementListController extends FormBasicController impleme
             sb.append(" o_curriculum");
         } else {
             int count = 0;
-            for (CurriculumElementWithViewsRow parent = rowWithView.getParent(); parent != null; parent = parent.getParent()) {
+            for (CourseCurriculumTreeWithViewsRow parent = rowWithView.getParent(); parent != null; parent = parent.getParent()) {
                 count++;
             }
 
@@ -285,15 +292,15 @@ public class CurriculumElementListController extends FormBasicController impleme
 
     private void loadModel(UserRequest ureq) {
         Roles roles = ureq.getUserSession().getRoles();
-        List<CurriculumElementWithViewsRow> allRows = new ArrayList<>();
+        List<CourseCurriculumTreeWithViewsRow> allRows = new ArrayList<>();
         List<CurriculumElementRepositoryEntryViews> elementsWithViewsForAll = curriculumService.getCurriculumElements(assessedIdentity, roles, curriculumRefList);
         Map<Curriculum, List<CurriculumElementRepositoryEntryViews>> elementsMap = elementsWithViewsForAll.stream().collect(Collectors.groupingBy(row -> row.getCurriculumElement().getCurriculum(), Collectors.toList()));
 
         for (Curriculum curriculum : curriculumList) {
-            CurriculumElementWithViewsRow curriculumRow = new CurriculumElementWithViewsRow(curriculum);
+            CourseCurriculumTreeWithViewsRow curriculumRow = new CourseCurriculumTreeWithViewsRow(curriculum);
             List<CurriculumElementRepositoryEntryViews> elementsWithViews = elementsMap.get(curriculum);
             if (elementsWithViews != null && !elementsWithViews.isEmpty()) {
-                List<CurriculumElementWithViewsRow> rows = new ArrayList<>();
+                List<CourseCurriculumTreeWithViewsRow> rows = new ArrayList<>();
 
                 Set<Long> repoKeys = new HashSet<>();
                 List<OLATResource> resourcesWithAC = new ArrayList<>();
@@ -313,20 +320,20 @@ public class CurriculumElementListController extends FormBasicController impleme
                     CurriculumElementMembership elementMembership = elementWithViews.getCurriculumMembership();
 
                     if (elementWithViews.getEntries() == null || elementWithViews.getEntries().isEmpty()) {
-                        CurriculumElementWithViewsRow row = new CurriculumElementWithViewsRow(curriculum, element, elementMembership, 0);
+                        CourseCurriculumTreeWithViewsRow row = new CourseCurriculumTreeWithViewsRow(curriculum, element, elementMembership, 0);
                         forgeCalendarsLink(row);
                         rows.add(row);
                     } else if (elementWithViews.getEntries().size() == 1) {
-                        CurriculumElementWithViewsRow row = new CurriculumElementWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().get(0), true);
+                        CourseCurriculumTreeWithViewsRow row = new CourseCurriculumTreeWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().get(0), true);
                         forge(row, repoKeys, resourcesWithOffer);
                         forgeCalendarsLink(row);
                         rows.add(row);
                     } else {
-                        CurriculumElementWithViewsRow elementRow = new CurriculumElementWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().size());
+                        CourseCurriculumTreeWithViewsRow elementRow = new CourseCurriculumTreeWithViewsRow(curriculum, element, elementMembership, elementWithViews.getEntries().size());
                         forgeCalendarsLink(elementRow);
                         rows.add(elementRow);
                         for (RepositoryEntryMyView entry : elementWithViews.getEntries()) {
-                            CurriculumElementWithViewsRow row = new CurriculumElementWithViewsRow(curriculum, element, elementMembership, entry, false);
+                            CourseCurriculumTreeWithViewsRow row = new CourseCurriculumTreeWithViewsRow(curriculum, element, elementMembership, entry, false);
                             forge(row, repoKeys, resourcesWithOffer);
                             rows.add(row);
                         }
@@ -335,8 +342,8 @@ public class CurriculumElementListController extends FormBasicController impleme
                 }
 
 
-                Map<Long, CurriculumElementWithViewsRow> keyToRow = rows.stream()
-                        .collect(Collectors.toMap(CurriculumElementWithViewsRow::getKey, row -> row, (row1, row2) -> row1));
+                Map<Long, CourseCurriculumTreeWithViewsRow> keyToRow = rows.stream()
+                        .collect(Collectors.toMap(CourseCurriculumTreeWithViewsRow::getKey, row -> row, (row1, row2) -> row1));
                 rows.forEach(row -> {
                     row.setParent(keyToRow.get(row.getParentKey()));
                     if (row.getOlatResource() != null) {
@@ -368,7 +375,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         // Filter for entries which are already in a curriculum
 
         if (!courses.isEmpty()) {
-            CurriculumElementWithViewsRow foreignEntryParent = new CurriculumElementWithViewsRow(translate("curriculum.foreign.entries"));
+            CourseCurriculumTreeWithViewsRow foreignEntryParent = new CourseCurriculumTreeWithViewsRow(translate("curriculum.foreign.entries"));
             allRows.add(foreignEntryParent);
 
             List<RepositoryEntryMyView> foreignCourses = courses.stream()
@@ -377,7 +384,7 @@ public class CurriculumElementListController extends FormBasicController impleme
                     ).collect(Collectors.toList());
 
             foreignCourses.forEach(course -> {
-                CurriculumElementWithViewsRow row = new CurriculumElementWithViewsRow(course);
+                CourseCurriculumTreeWithViewsRow row = new CourseCurriculumTreeWithViewsRow(course);
                 forgeSelectLink(row);
                 forgeCompletion(row,row.getRepositoryEntryCompletion());
                 forgeDetails(row);
@@ -391,25 +398,25 @@ public class CurriculumElementListController extends FormBasicController impleme
         tableEl.reset(true, true, true);
     }
 
-    private void removeByPermissions(List<CurriculumElementWithViewsRow> rows) {
+    private void removeByPermissions(List<CourseCurriculumTreeWithViewsRow> rows) {
         // propagate the member marker along the parent line
-        for (CurriculumElementWithViewsRow row : rows) {
+        for (CourseCurriculumTreeWithViewsRow row : rows) {
             if (row.isCurriculumMember()) {
-                for (CurriculumElementWithViewsRow parentRow = row.getParent(); parentRow != null; parentRow = parentRow.getParent()) {
+                for (CourseCurriculumTreeWithViewsRow parentRow = row.getParent(); parentRow != null; parentRow = parentRow.getParent()) {
                     parentRow.setCurriculumMember(true);
                 }
             }
         }
 
         // trim part of the tree without member flag
-        for (Iterator<CurriculumElementWithViewsRow> it = rows.iterator(); it.hasNext(); ) {
+        for (Iterator<CourseCurriculumTreeWithViewsRow> it = rows.iterator(); it.hasNext(); ) {
             if (!it.next().isCurriculumMember()) {
                 it.remove();
             }
         }
     }
 
-    private void forge(CurriculumElementWithViewsRow row, Collection<Long> repoKeys, List<OLATResourceAccess> resourcesWithOffer) {
+    private void forge(CourseCurriculumTreeWithViewsRow row, Collection<Long> repoKeys, List<OLATResourceAccess> resourcesWithOffer) {
         if (row.getRepositoryEntryKey() == null || guestOnly) return;// nothing for guests
 
         boolean isMember = repoKeys.contains(row.getRepositoryEntryKey());
@@ -466,7 +473,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         forgeCompletion(row, row.getRepositoryEntryCompletion());
     }
 
-    private void forgeDetails(CurriculumElementWithViewsRow row) {
+    private void forgeDetails(CourseCurriculumTreeWithViewsRow row) {
         FormLink detailsLink = uifactory.addFormLink("details_" + (++counter), "details", "details", null, null, Link.LINK);
         detailsLink.setCustomEnabledLinkCSS("o_details");
         detailsLink.setUserObject(row);
@@ -481,7 +488,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         row.setDetailsLink(detailsLink, detailsUrl);
     }
 
-    private void forgeMarkLink(CurriculumElementWithViewsRow row) {
+    private void forgeMarkLink(CourseCurriculumTreeWithViewsRow row) {
         if (!guestOnly) {
             FormLink markLink = uifactory.addFormLink("mark_" + (++counter), "mark", "", null, null, Link.NONTRANSLATED);
             markLink.setIconLeftCSS(row.isMarked() ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE);
@@ -491,7 +498,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private void forgeSelectLink(CurriculumElementWithViewsRow row) {
+    private void forgeSelectLink(CourseCurriculumTreeWithViewsRow row) {
         if (row.isCurriculumElementOnly()) return;
 
         String displayName = StringHelper.escapeHtml(row.getRepositoryEntryDisplayName());
@@ -509,7 +516,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         row.setSelectLink(selectLink);
     }
 
-    private void forgeCalendarsLink(CurriculumElementWithViewsRow row) {
+    private void forgeCalendarsLink(CourseCurriculumTreeWithViewsRow row) {
         if (row.isCalendarsEnabled()) {
             FormLink calendarLink = uifactory.addFormLink("cals_" + (++counter), "calendars", "calendars", null, null, Link.LINK);
             calendarLink.setIconLeftCSS("o_icon o_icon-fw o_icon_timetable");
@@ -518,17 +525,17 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private void forgeCurriculumCompletions(List<CurriculumElementWithViewsRow> rows) {
+    private void forgeCurriculumCompletions(List<CourseCurriculumTreeWithViewsRow> rows) {
         Map<Long, Double> completions = loadCurriculumElementCompletions(rows);
 
-        for (CurriculumElementWithViewsRow row : rows) {
+        for (CourseCurriculumTreeWithViewsRow row : rows) {
             if (row.getCompletionItem() == null) { // does not show completion of the child entry
                 forgeCompletion(row, completions.get(row.getKey()));
             }
         }
     }
 
-    private void forgeCompletion(CurriculumElementWithViewsRow row, Double completion) {
+    private void forgeCompletion(CourseCurriculumTreeWithViewsRow row, Double completion) {
         if (completion != null) {
             ProgressBarItem completionItem = new ProgressBarItem("completion_" + row.getKey(), 100,
                     completion.floatValue(), Float.valueOf(1), null);
@@ -541,14 +548,14 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private void addRoot(List<CurriculumElementWithViewsRow> rows, CurriculumElementWithViewsRow parent) {
+    private void addRoot(List<CourseCurriculumTreeWithViewsRow> rows, CourseCurriculumTreeWithViewsRow parent) {
         rows.stream().filter(row -> row.getParent() == null).forEach(row -> row.setParent(parent));
     }
 
-    private Map<Long, Double> loadCurriculumElementCompletions(List<CurriculumElementWithViewsRow> rows) {
+    private Map<Long, Double> loadCurriculumElementCompletions(List<CourseCurriculumTreeWithViewsRow> rows) {
         List<Long> curEleLearningProgressKeys = rows.stream()
-                .filter(CurriculumElementWithViewsRow::isLearningProgressEnabled)
-                .map(CurriculumElementWithViewsRow::getKey)
+                .filter(CourseCurriculumTreeWithViewsRow::isLearningProgressEnabled)
+                .map(CourseCurriculumTreeWithViewsRow::getKey)
                 .collect(Collectors.toList());
         List<AssessmentEntryCompletion> loadAvgCompletionsByCurriculumElements = assessmentService
                 .loadAvgCompletionsByCurriculumElements(assessedIdentity, curEleLearningProgressKeys);
@@ -579,8 +586,8 @@ public class CurriculumElementListController extends FormBasicController impleme
                 if (StringHelper.isLong(rowKeyStr)) {
                     try {
                         Long rowKey = Long.valueOf(rowKeyStr);
-                        List<CurriculumElementWithViewsRow> rows = tableModel.getObjects();
-                        for (CurriculumElementWithViewsRow row : rows) {
+                        List<CourseCurriculumTreeWithViewsRow> rows = tableModel.getObjects();
+                        for (CourseCurriculumTreeWithViewsRow row : rows) {
                             if (row != null && row.getRepositoryEntryKey() != null && row.getRepositoryEntryKey().equals(rowKey)) {
                                 if (row.isMember()) {
                                     doOpen(ureq, row, null);
@@ -603,33 +610,33 @@ public class CurriculumElementListController extends FormBasicController impleme
         if (source instanceof FormLink) {
             FormLink link = (FormLink) source;
             if ("start".equals(link.getCmd())) {
-                CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow) link.getUserObject();
+                CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow) link.getUserObject();
                 doOpen(ureq, row, null);
             } else if ("details".equals(link.getCmd())) {
-                CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow) link.getUserObject();
+                CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow) link.getUserObject();
                 doOpenDetails(ureq, row);
             } else if ("select".equals(link.getCmd())) {
-                CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow) link.getUserObject();
+                CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow) link.getUserObject();
                 if (row.isMember()) {
                     doOpen(ureq, row, null);
                 } else {
                     doOpenDetails(ureq, row);
                 }
             } else if ("mark".equals(link.getCmd())) {
-                CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow) link.getUserObject();
+                CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow) link.getUserObject();
                 boolean marked = doMark(ureq, row);
                 link.setIconLeftCSS(marked ? "o_icon o_icon_bookmark o_icon-lg" : "o_icon o_icon_bookmark_add o_icon-lg");
                 link.setTitle(translate(marked ? "details.bookmark.remove" : "details.bookmark"));
                 link.getComponent().setDirty(true);
                 row.setMarked(marked);
             } else if ("calendars".equals(link.getCmd())) {
-                CurriculumElementWithViewsRow row = (CurriculumElementWithViewsRow) link.getUserObject();
+                CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow) link.getUserObject();
                 doOpenCalendars(ureq, row);
             }
         } else if (source == tableEl) {
             if (event instanceof SelectionEvent) {
                 SelectionEvent se = (SelectionEvent) event;
-                CurriculumElementWithViewsRow row = tableModel.getObject(se.getIndex());
+                CourseCurriculumTreeWithViewsRow row = tableModel.getObject(se.getIndex());
                 if (row.isMember()) {
                     doOpen(ureq, row, null);
                 } else {
@@ -645,7 +652,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         //
     }
 
-    private void doOpen(UserRequest ureq, CurriculumElementWithViewsRow row, String subPath) {
+    private void doOpen(UserRequest ureq, CourseCurriculumTreeWithViewsRow row, String subPath) {
         try {
             String businessPath = "[RepositoryEntry:" + row.getRepositoryEntryKey() + "]";
             if (subPath != null) {
@@ -658,7 +665,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private void doOpenDetails(UserRequest ureq, CurriculumElementWithViewsRow row) {
+    private void doOpenDetails(UserRequest ureq, CourseCurriculumTreeWithViewsRow row) {
         // to be more consistent: course members see info page within the course, non-course members see it outside the course
         if (row.isMember()) {
             doOpen(ureq, row, "[Infos:0]");
@@ -685,14 +692,14 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private void doOpenCalendars(UserRequest ureq, CurriculumElementWithViewsRow row) {
+    private void doOpenCalendars(UserRequest ureq, CourseCurriculumTreeWithViewsRow row) {
         removeAsListenerAndDispose(calendarsCtrl);
 
         OLATResourceable ores = OresHelper.createOLATResourceableInstance("Calendars", row.getCurriculumElementKey());
         WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
         CurriculumElement element = curriculumService
                 .getCurriculumElement(new CurriculumElementRefImpl(row.getCurriculumElementKey()));
-        List<CurriculumElementWithViewsRow> rows = tableModel.getObjects();
+        List<CourseCurriculumTreeWithViewsRow> rows = tableModel.getObjects();
 
         Set<Long> entryKeys = new HashSet<>();
         for (CurriculumElementWithView elementWithView : rows) {
@@ -714,7 +721,7 @@ public class CurriculumElementListController extends FormBasicController impleme
         stackPanel.pushController(translate("calendars"), calendarsCtrl);
     }
 
-    private boolean doMark(UserRequest ureq, CurriculumElementWithViewsRow row) {
+    private boolean doMark(UserRequest ureq, CourseCurriculumTreeWithViewsRow row) {
         OLATResourceable item = OresHelper.createOLATResourceableInstance("RepositoryEntry", row.getRepositoryEntryKey());
         RepositoryEntryRef ref = new RepositoryEntryRefImpl(row.getRepositoryEntryKey());
         if (markManager.isMarked(item, getIdentity(), null)) {
@@ -733,10 +740,10 @@ public class CurriculumElementListController extends FormBasicController impleme
         }
     }
 
-    private List<CurriculumElementWithViewsRow> sortCurriculumRows(List<CurriculumElementWithViewsRow> rows) {
-        List<CurriculumElementWithViewsRow> sortedRows = rows.stream().filter(row -> row.   getLevel() == 0).collect(Collectors.toList());
+    private List<CourseCurriculumTreeWithViewsRow> sortCurriculumRows(List<CourseCurriculumTreeWithViewsRow> rows) {
+        List<CourseCurriculumTreeWithViewsRow> sortedRows = rows.stream().filter(row -> row.   getLevel() == 0).collect(Collectors.toList());
 
-        for (CurriculumElementWithViewsRow parent : sortedRows) {
+        for (CourseCurriculumTreeWithViewsRow parent : sortedRows) {
             if (parent.hasChildren()) {
                 sortedRows.addAll(sortedRows.indexOf(parent) + 1, sortCurriculumRows(rows, parent));
             }
@@ -745,11 +752,11 @@ public class CurriculumElementListController extends FormBasicController impleme
         return sortedRows;
     }
 
-    private List<CurriculumElementWithViewsRow> sortCurriculumRows(List<CurriculumElementWithViewsRow> rows, CurriculumElementWithViewsRow parent) {
-        List<CurriculumElementWithViewsRow> filteredRows = rows.stream().filter(row -> row.getParent() != null && row.getParent().equals(parent)).collect(Collectors.toList());
-        List<CurriculumElementWithViewsRow> sortedRows = new ArrayList<>(filteredRows);
+    private List<CourseCurriculumTreeWithViewsRow> sortCurriculumRows(List<CourseCurriculumTreeWithViewsRow> rows, CourseCurriculumTreeWithViewsRow parent) {
+        List<CourseCurriculumTreeWithViewsRow> filteredRows = rows.stream().filter(row -> row.getParent() != null && row.getParent().equals(parent)).collect(Collectors.toList());
+        List<CourseCurriculumTreeWithViewsRow> sortedRows = new ArrayList<>(filteredRows);
 
-        for (CurriculumElementWithViewsRow child : filteredRows) {
+        for (CourseCurriculumTreeWithViewsRow child : filteredRows) {
             if (child.hasChildren()) {
                 sortedRows.addAll(filteredRows.indexOf(child) + 1, sortCurriculumRows(rows, parent));
             }
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementViewsRowComparator.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementViewsRowComparator.java
similarity index 85%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementViewsRowComparator.java
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementViewsRowComparator.java
index 14d136c31b9ec717e91d0f47c0f43a0ead9b42f5..87b8af24262cb8abf10100e08dd172440d9d8595 100644
--- a/src/main/java/org/olat/modules/coach/ui/curriculum/CurriculumElementViewsRowComparator.java
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementViewsRowComparator.java
@@ -17,7 +17,7 @@
  * frentix GmbH, http://www.frentix.com
  * <p>
  */
-package org.olat.modules.coach.ui.curriculum;
+package org.olat.modules.coach.ui.curriculum.course;
 
 import java.text.Collator;
 import java.util.Locale;
@@ -47,8 +47,8 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 			return compareNullObjects(o1, o2);
 		}
 
-		CurriculumElementWithViewsRow c1 = (CurriculumElementWithViewsRow)o1;
-		CurriculumElementWithViewsRow c2 = (CurriculumElementWithViewsRow)o2;
+		CourseCurriculumTreeWithViewsRow c1 = (CourseCurriculumTreeWithViewsRow)o1;
+		CourseCurriculumTreeWithViewsRow c2 = (CourseCurriculumTreeWithViewsRow)o2;
 		Long parentKey1 = c1.getParentKey();
 		Long parentKey2 = c2.getParentKey();
 
@@ -59,8 +59,8 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 			c = compareSameParent(c1, c2);
 		} else if(parentKey1 != null && parentKey2 != null) {
 			// This case is usually not possible
-			CurriculumElementWithViewsRow p1 = c1.getParent();
-			CurriculumElementWithViewsRow p2 = c2.getParent();
+			CourseCurriculumTreeWithViewsRow p1 = c1.getParent();
+			CourseCurriculumTreeWithViewsRow p2 = c2.getParent();
 			if(p1 == null || p2 == null) {
 				// reversed because no parent at the top, higher in the hierarchy
 				c = -compareNullObjects(p1, p2);
@@ -78,7 +78,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return c;
 	}
 
-	private int compareSameParent(CurriculumElementWithViewsRow c1, CurriculumElementWithViewsRow c2) {
+	private int compareSameParent(CourseCurriculumTreeWithViewsRow c1, CourseCurriculumTreeWithViewsRow c2) {
 		int c = 0;
 		if((c1.isCurriculumElementOnly() || c1.isCurriculumElementWithEntry()) && (c2.isCurriculumElementOnly() || c2.isCurriculumElementWithEntry())) {
 			// compare by position
@@ -93,7 +93,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return c;
 	}
 
-	private int compareCurriculumElements(CurriculumElementWithViewsRow c1, CurriculumElementWithViewsRow c2) {
+	private int compareCurriculumElements(CourseCurriculumTreeWithViewsRow c1, CourseCurriculumTreeWithViewsRow c2) {
 		int c = compareClosed(c1, c2);
 
 		if(c == 0) {
@@ -126,7 +126,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return c;
 	}
 
-	private int compareRepositoryEntry(CurriculumElementWithViewsRow c1, CurriculumElementWithViewsRow c2) {
+	private int compareRepositoryEntry(CourseCurriculumTreeWithViewsRow c1, CourseCurriculumTreeWithViewsRow c2) {
 		int c = compareClosed(c1, c2);
 
 		if(c == 0) {
@@ -151,7 +151,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return c;
 	}
 
-	private int compareClosed(CurriculumElementWithViewsRow c1, CurriculumElementWithViewsRow c2) {
+	private int compareClosed(CourseCurriculumTreeWithViewsRow c1, CourseCurriculumTreeWithViewsRow c2) {
 		int c = 0;
 		if(c1.isClosedOrInactive() && !c2.isClosedOrInactive()) {
 			c = 1;
@@ -161,7 +161,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return c;
 	}
 
-	private int compareDisplayName(CurriculumElementWithViewsRow c1, CurriculumElementWithViewsRow c2) {
+	private int compareDisplayName(CourseCurriculumTreeWithViewsRow c1, CourseCurriculumTreeWithViewsRow c2) {
 		String d1 = getDisplayName(c1);
 		String d2 = getDisplayName(c2);
 		if(d1 == null || d2 == null) {
@@ -170,7 +170,7 @@ public class CurriculumElementViewsRowComparator extends FlexiTreeNodeComparator
 		return d1.compareTo(d2);
 	}
 
-	private String getDisplayName(CurriculumElementWithViewsRow row) {
+	private String getDisplayName(CourseCurriculumTreeWithViewsRow row) {
 		if(row.isCurriculumElementOnly()) {
 			return row.getCurriculumElementDisplayName();
 		}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementWithViewsDataModel.java b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementWithViewsDataModel.java
new file mode 100644
index 0000000000000000000000000000000000000000..a925b43ac177dd3331197970391318139775d453
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/CurriculumElementWithViewsDataModel.java
@@ -0,0 +1,278 @@
+/**
+ * <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.modules.coach.ui.curriculum.course;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTreeTableDataModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiBusinessPathModel;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
+import org.olat.course.certificate.CertificateLight;
+import org.olat.modules.coach.model.EfficiencyStatementEntry;
+import org.olat.modules.coach.model.IdentityRepositoryEntryKey;
+import org.olat.modules.coach.model.IdentityResourceKey;
+import org.olat.modules.coach.ui.ProgressValue;
+import org.olat.modules.curriculum.CurriculumElementStatus;
+import org.olat.modules.lecture.model.LectureBlockStatistics;
+
+/**
+ * 
+ * Initial date: 11 mai 2018<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class CurriculumElementWithViewsDataModel extends DefaultFlexiTreeTableDataModel<CourseCurriculumTreeWithViewsRow> implements FlexiBusinessPathModel {
+
+	private ConcurrentMap<IdentityResourceKey, CertificateLight> certificateMap;
+	private ConcurrentMap<IdentityRepositoryEntryKey, LectureBlockStatistics> lecturesStatisticsMap;
+
+	public CurriculumElementWithViewsDataModel(FlexiTableColumnModel columnsModel) {
+		super(columnsModel);
+	}
+	
+	@Override
+	public void filter(String searchString, List<FlexiTableFilter> filters) {
+		if(filters != null && !filters.isEmpty() && filters.get(0) != null) {
+			FlexiTableFilter filter = filters.get(0);
+			if(filter == null || filter.isShowAll()) {
+				setUnfilteredObjects();
+			} else {
+				List<CourseCurriculumTreeWithViewsRow> filteredRows = new ArrayList<>(backupRows.size());
+				// curriculum element inactive -> all repo are inactives
+				// parent inactive, child is active -> parent is forced active
+				for(CourseCurriculumTreeWithViewsRow row:backupRows) {
+					boolean accept = active(row);
+					if(accept) {
+						filteredRows.add(row);
+					}
+				}
+				setFilteredObjects(filteredRows);
+			}
+		} else {
+			setUnfilteredObjects();
+		}
+	}
+	
+	private boolean active(CourseCurriculumTreeWithViewsRow row) {
+		boolean active = true;
+		if(row.isCurriculumElementOnly() || row.isCurriculumElementWithEntry()) {
+			active = row.getCurriculumElementStatus() == CurriculumElementStatus.active;
+		}
+		if(active) {
+			for(CourseCurriculumTreeWithViewsRow parent = row.getParent(); parent != null; parent=parent.getParent()) {
+				if(parent.isCurriculumElementOnly() || parent.isCurriculumElementWithEntry()) {
+					active &= row.getCurriculumElementStatus() == CurriculumElementStatus.active;
+				}
+			}
+		}
+		return active;
+	}
+	
+	@Override
+	public boolean hasChildren(int row) {
+		CourseCurriculumTreeWithViewsRow element = getObject(row);
+		return element.hasChildren();
+	}
+
+	@Override
+	public Object getValueAt(int row, int col) {
+		CourseCurriculumTreeWithViewsRow curriculum = getObject(row);
+		switch(ElementViewCols.values()[col]) {
+			case key: return curriculum.getKey();
+			case displayName: {
+				String displayName;
+				if(curriculum.isRepositoryEntryOnly()) {
+					displayName = curriculum.getRepositoryEntryDisplayName();
+				} else {
+					displayName = curriculum.getCurriculumElementDisplayName();
+				}
+				return displayName;
+			}
+			case identifier: {
+				String identifier;
+				if(curriculum.isRepositoryEntryOnly()) {
+					identifier = curriculum.getRepositoryEntryExternalRef();
+				} else {
+					identifier = curriculum.getCurriculumElementIdentifier();
+				}
+				return identifier;
+			}
+			case mark: return curriculum.getMarkLink();
+			case select: return curriculum.getSelectLink();
+			case details: return curriculum.getDetailsLink();
+			case start: return curriculum.getStartLink();
+			case calendars: return curriculum.getCalendarsLink();
+			case completion: return curriculum.getCompletionItem();
+			case score: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getScore() : null;
+			case passed: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getPassed() : null;
+			case certificate: return getCertificate(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+			case recertification: {
+				CertificateLight certificate = getCertificate(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return certificate == null ? null : certificate.getNextRecertificationDate();
+			}
+			case numberAssessments: {
+				ProgressValue val = null;
+				Integer totalNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getTotalNodes() : null;
+				if (totalNodes != null && totalNodes.intValue() > 0) {
+					val = new ProgressValue();
+					val.setTotal(totalNodes.intValue());
+					Integer attemptedNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getAttemptedNodes() : null;
+					val.setGreen(attemptedNodes == null ? 0 : attemptedNodes.intValue());
+				}
+				return val;
+			}
+			case progress: {
+				Integer totalNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getTotalNodes() : null;
+				if(totalNodes == null) {
+					ProgressValue val = new ProgressValue();
+					val.setTotal(100);
+					val.setGreen(0);
+					return val;
+				}
+
+				ProgressValue val = new ProgressValue();
+				val.setTotal(totalNodes.intValue());
+				Integer attemptedNodes = curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getAttemptedNodes() : null;
+				val.setGreen(attemptedNodes == null ? 0 : attemptedNodes.intValue());
+				return val;
+			}
+			case lastModification: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastModified() : null;
+			case lastUserModified: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastUserModified() : null;
+			case lastCoachModified: return curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry().getLastCoachModified() : null;
+			case plannedLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalPersonalPlannedLectures();
+			}
+			case attendedLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAttendedLectures();
+			}
+			case unauthorizedAbsenceLectures:
+			case absentLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAbsentLectures();
+			}
+			case authorizedAbsenceLectures: {
+				LectureBlockStatistics statistics = getLectureBlockStatistics(curriculum.getEfficiencyStatementEntry() != null ? curriculum.getEfficiencyStatementEntry() : null);
+				return statistics == null ? null : statistics.getTotalAuthorizedAbsentLectures();
+			}
+			default: return "ERROR";
+		}
+	}
+
+	private CertificateLight getCertificate(EfficiencyStatementEntry entry) {
+		if(certificateMap != null) {
+			IdentityResourceKey key = new IdentityResourceKey(entry.getIdentityKey(), entry.getCourse().getOlatResource().getKey());
+			return certificateMap.get(key);
+		}
+		return null;
+	}
+
+	private LectureBlockStatistics getLectureBlockStatistics(EfficiencyStatementEntry entry) {
+		if(lecturesStatisticsMap != null) {
+			IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(entry);
+			return lecturesStatisticsMap.get(key);
+		}
+		return null;
+	}
+
+	public void setObjects(List<CourseCurriculumTreeWithViewsRow> objects, ConcurrentMap<IdentityResourceKey, CertificateLight> certificates) {
+		setObjects(objects, certificates, null);
+	}
+
+	public void setObjects(List<CourseCurriculumTreeWithViewsRow> objects,
+						   ConcurrentMap<IdentityResourceKey, CertificateLight> certificates,
+						   ConcurrentMap<IdentityRepositoryEntryKey, LectureBlockStatistics> lecturesStatisticsMap) {
+		setObjects(objects);
+		this.certificateMap = certificates;
+		this.lecturesStatisticsMap = lecturesStatisticsMap;
+	}
+
+	@Override
+	public CurriculumElementWithViewsDataModel createCopyWithEmptyList() {
+		return new CurriculumElementWithViewsDataModel(getTableColumnModel());
+	}
+
+	public enum ElementViewCols implements FlexiSortableColumnDef {
+		key("table.header.key"),
+		displayName("table.header.curriculum.element.displayName"),
+		identifier("table.header.curriculum.element.identifier"),
+		mark("table.header.mark"),
+		select("table.header.displayName"),
+		completion("table.header.completion"),
+		details("table.header.details"),
+		start("table.header.start"),
+		calendars("table.header.calendars"),
+		score("table.header.score"),
+		passed("table.header.passed"),
+		certificate("table.header.certificate"),
+		recertification("table.header.recertification"),
+		numberAssessments("table.header.number.assessments"),
+		progress("table.header.progress"),
+		lastModification("table.header.lastScoreDate"),
+		lastUserModified("table.header.lastUserModificationDate"),
+		lastCoachModified("table.header.lastCoachModificationDate"),
+		plannedLectures("table.header.planned.lectures"),
+		attendedLectures("table.header.attended.lectures"),
+		absentLectures("table.header.absent.lectures"),
+		unauthorizedAbsenceLectures("table.header.unauthorized.absence"),
+		authorizedAbsenceLectures("table.header.authorized.absence");
+		
+		private final String i18nHeaderKey;
+		
+		private ElementViewCols(String i18nHeaderKey) {
+			this.i18nHeaderKey = i18nHeaderKey;
+		}
+
+		@Override
+		public boolean sortable() {
+			return false;
+		}
+
+		@Override
+		public String sortKey() {
+			return name();
+		}
+
+		@Override
+		public String i18nHeaderKey() {
+			return i18nHeaderKey;
+		}
+	}
+
+	@Override
+	public String getUrl(Component source, Object object, String action) {
+		if("select".equals(action) && object instanceof CourseCurriculumTreeWithViewsRow) {
+			CourseCurriculumTreeWithViewsRow row = (CourseCurriculumTreeWithViewsRow)object;
+			if(row.getStartUrl() != null) {
+				return row.getStartUrl();
+			}
+			if(row.getDetailsUrl() != null) {
+				return row.getDetailsUrl();
+			}
+		}
+		return null;
+	}
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/course_list_wrapper.html b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/course_list_wrapper.html
new file mode 100644
index 0000000000000000000000000000000000000000..5e24835375b6742bb25c795c4f459f1d76814dc9
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/course_list_wrapper.html
@@ -0,0 +1,12 @@
+#if($r.available("on"))
+<span>
+	$r.translate("curriculum.toggle.description")
+	#if($showCurriculum)
+		$r.render("on")
+	#else
+		$r.render("off")
+	#end
+</span>
+#end
+
+$r.render("content")
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_element_list.html b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_element_list.html
new file mode 100644
index 0000000000000000000000000000000000000000..99ac382380fc019dd5fcdceaf52f22eea7dbda71
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_element_list.html
@@ -0,0 +1 @@
+$r.render("table")
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_list.html b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_list.html
new file mode 100644
index 0000000000000000000000000000000000000000..99ac382380fc019dd5fcdceaf52f22eea7dbda71
--- /dev/null
+++ b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_content/curriculum_list.html
@@ -0,0 +1 @@
+$r.render("table")
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_i18n/LocalStrings_de.properties
similarity index 100%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/_i18n/LocalStrings_de.properties
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/_i18n/LocalStrings_de.properties
diff --git a/src/main/java/org/olat/modules/coach/ui/curriculum/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/coach/ui/curriculum/course/_i18n/LocalStrings_en.properties
similarity index 100%
rename from src/main/java/org/olat/modules/coach/ui/curriculum/_i18n/LocalStrings_en.properties
rename to src/main/java/org/olat/modules/coach/ui/curriculum/course/_i18n/LocalStrings_en.properties
diff --git a/src/main/java/org/olat/modules/curriculum/CurriculumService.java b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
index 6d79391713dddd68c101f0c0f07f3ea6337a3e40..a4e867373f3384db6fa6d8bbdd321e005efffca4 100644
--- a/src/main/java/org/olat/modules/curriculum/CurriculumService.java
+++ b/src/main/java/org/olat/modules/curriculum/CurriculumService.java
@@ -501,7 +501,7 @@ public interface CurriculumService {
 	public List<CurriculumElement> filterElementsWithoutManagerRole(List<CurriculumElement> elements, Roles roles);
 	
 	
-	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, List<CurriculumRef> curriculum);
+	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, List<? extends CurriculumRef> curriculum);
 	
 
 	public List<CurriculumElementWebDAVInfos> getCurriculumElementInfosForWebDAV(IdentityRef identity);
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
index 0e1ef0d1ca4a6736e602e92354415bd945de1bf4..a2f7626c3948044a631b30885444b12c19071eca 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumElementDAO.java
@@ -870,7 +870,7 @@ public class CurriculumElementDAO {
 				.getResultList();
 	}
 	
-	public List<CurriculumElementMembership> getMembershipInfos(List<CurriculumRef> curriculums, Collection<CurriculumElement> elements, Identity... identities) {
+	public List<CurriculumElementMembership> getMembershipInfos(List<? extends CurriculumRef> curriculums, Collection<CurriculumElement> elements, Identity... identities) {
 		StringBuilder sb = new StringBuilder(256);
 		sb.append("select el.key, membership from curriculumelement el")
 		  .append(" inner join el.group baseGroup")
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
index 6afbd5dc9f3dcf96cd52fcb6b8d9037f0e5ee491..74175307c96ee931f18304a338253edf6ead4816 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumRepositoryEntryRelationDAO.java
@@ -172,7 +172,7 @@ public class CurriculumRepositoryEntryRelationDAO {
 	 * @param curriculum The curriculum
 	 * @return A map of curriculum element to their repository entries
 	 */
-	public Map<CurriculumElement, List<Long>> getCurriculumElementsWithRepositoryEntryKeys(List<CurriculumRef> curriculums) {
+	public Map<CurriculumElement, List<Long>> getCurriculumElementsWithRepositoryEntryKeys(List<? extends CurriculumRef> curriculums) {
 		if(curriculums == null || curriculums.isEmpty()) return Collections.emptyMap();
 		
 		QueryBuilder sb = new QueryBuilder(256);
diff --git a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
index c5a11a19f6f9ca9a3a683317a9a17e35eb8e8f82..4993272a91b65431a4b3f4bd1cf645ab507236f6 100644
--- a/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
+++ b/src/main/java/org/olat/modules/curriculum/manager/CurriculumServiceImpl.java
@@ -866,7 +866,7 @@ public class CurriculumServiceImpl implements CurriculumService, OrganisationDat
 	}
 
 	@Override
-	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, List<CurriculumRef> curriculums) {
+	public List<CurriculumElementRepositoryEntryViews> getCurriculumElements(Identity identity, Roles roles, List<? extends CurriculumRef> curriculums) {
 		if(curriculums == null || curriculums.isEmpty()) return Collections.emptyList();
 		
 		List<CurriculumElementMembership> memberships = curriculumElementDao.getMembershipInfos(curriculums, null, identity);
diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
index 46f5889befb4af3726e60ff9267fee01e200a328..36ffa7701e124387737190aabdec9516af1499cc 100644
--- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_de.properties
@@ -111,6 +111,7 @@ table.header.completion=$org.olat.modules.assessment.ui\:learning.progress
 table.header.curriculum=Curriculum
 table.header.curriculum.element.displayName=Name
 table.header.curriculum.element.identifier=Bezeichnung
+table.header.curriculum.element.has.statement=Leistungsnachweis vorhanden
 table.header.details=<i class\="o_icon o_icon-lg o_icon_details" title\="Infoseite"> </i>
 table.header.displayName=Name
 table.header.edit=Bearbeiten
diff --git a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
index 8d8b2ba8da8b9671e0363fe782a1c9dd573cbc02..cd542c2674be9f14fd8acff61c5a473b337592fc 100644
--- a/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/modules/curriculum/ui/_i18n/LocalStrings_en.properties
@@ -110,6 +110,7 @@ table.header.calendars=Calendar
 table.header.completion=$org.olat.modules.assessment.ui\:learning.progress
 table.header.curriculum=Curriculum
 table.header.curriculum.element.displayName=Name
+table.header.curriculum.element.has.statement=Has Statement
 table.header.curriculum.element.identifier=Identifier
 table.header.details=<i class\="o_icon o_icon-lg o_icon_details" title\="Info page"> </i>
 table.header.displayName=Name
diff --git a/src/main/java/org/olat/modules/quality/QualityReportAccessRightProvider.java b/src/main/java/org/olat/modules/quality/QualityReportAccessRightProvider.java
index 2f0a486f33ce9fe602640cdb0d9c804cff85d3d0..9406cc5fd20660b2805620490773e7c3388f835c 100644
--- a/src/main/java/org/olat/modules/quality/QualityReportAccessRightProvider.java
+++ b/src/main/java/org/olat/modules/quality/QualityReportAccessRightProvider.java
@@ -19,9 +19,12 @@
  */
 package org.olat.modules.quality;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.Locale;
 
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.OrganisationRoles;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.modules.quality.ui.QualityMainController;
@@ -34,23 +37,38 @@ import org.springframework.stereotype.Component;
  *
  */
 @Component
-public class QualityReportAccessRightProvider implements RelationRightProvider {
+public class QualityReportAccessRightProvider implements RightProvider {
 
 	public static final String RELATION_RIGHT = "selectableQualityReportAccess";
 
 	@Override
-	public RelationRightProvider getParent() {
+	public String getRight() {
+		return RELATION_RIGHT;
+	}
+
+	@Override
+	public RightProvider getParent() {
 		return null;
 	}
 
 	@Override
-	public int getPosition() {
-		return Order.QualityReportAccessRight.ordinal();
+	public boolean isUserRelationsRight() {
+		return true;
 	}
-	
+
 	@Override
-	public String getRight() {
-		return RELATION_RIGHT;
+	public int getUserRelationsPosition() {
+		return UserRelationRightsOrder.QualityReportAccessRight.ordinal();
+	}
+
+	@Override
+	public Collection<OrganisationRoles> getOrganisationRoles() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	public int getOrganisationPosition() {
+		return -1;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/repository/model/SearchMyRepositoryEntryViewParams.java b/src/main/java/org/olat/repository/model/SearchMyRepositoryEntryViewParams.java
index a7207b5e70624ca43fd122ad7a89d70af8c7a8d9..2e30cb192bbe97e3fcb5bff98beedef21702f315 100644
--- a/src/main/java/org/olat/repository/model/SearchMyRepositoryEntryViewParams.java
+++ b/src/main/java/org/olat/repository/model/SearchMyRepositoryEntryViewParams.java
@@ -47,7 +47,7 @@ public class SearchMyRepositoryEntryViewParams {
 	private List<Filter> filters;
 	private CatalogEntry parentEntry;
 	private List<String> resourceTypes;
-	private List<CurriculumRef> curriculums;
+	private List<? extends CurriculumRef> curriculums;
 
 	private String idAndRefs;
 	private String idRefsAndTitle;
@@ -76,11 +76,11 @@ public class SearchMyRepositoryEntryViewParams {
 		this.membershipMandatory = membershipMandatory;
 	}
 
-	public List<CurriculumRef> getCurriculums() {
+	public List<? extends CurriculumRef> getCurriculums() {
 		return curriculums;
 	}
 
-	public void setCurriculums(List<CurriculumRef> curriculums) {
+	public void setCurriculums(List<? extends CurriculumRef> curriculums) {
 		this.curriculums = curriculums;
 	}
 
diff --git a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml
index 8d509faafad9553a06e1b357f9c6aa78588177b4..6bafc0f7595165a882d6102e2c5d5b8cf96af41b 100644
--- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml
+++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml
@@ -1291,7 +1291,7 @@
 					</bean>
 				</entry>
 
-				<entry key="org.olat.modules.coach.ui.UserRelationOverviewController">
+				<entry key="org.olat.modules.coach.ui.UserOverviewController">
 					<bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext">
 						<property name="description" value="Short description of a user" />
 						<property name="propertyHandlers">
diff --git a/src/main/java/org/olat/user/ui/role/EditRelationRoleController.java b/src/main/java/org/olat/user/ui/role/EditRelationRoleController.java
index c65561b3e12bf9804642263e6a29154dcbc61fbe..023e787a014bc80b8fed00b88ec92c18ebb5611f 100644
--- a/src/main/java/org/olat/user/ui/role/EditRelationRoleController.java
+++ b/src/main/java/org/olat/user/ui/role/EditRelationRoleController.java
@@ -30,10 +30,10 @@ import java.util.stream.Collectors;
 
 import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.RelationRight;
-import org.olat.basesecurity.RelationRightProvider;
 import org.olat.basesecurity.RelationRole;
 import org.olat.basesecurity.RelationRoleManagedFlag;
 import org.olat.basesecurity.RelationRoleToRight;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -66,8 +66,7 @@ public class EditRelationRoleController extends FormBasicController {
 		"", "supervisor", "legalRepresentative", "tutor", "parent",
 		"teacher", "expert", "legalGardian", "employer", "sportsClub"
 	};
-	private static final String INTENDING = "\u00a0"; // &nbsp; non-breaking space
-	
+
 	private TextElement roleEl;
 	private SingleSelection predefinedLabelEl;
 	private MultipleSelectionElement rightsEl;
@@ -75,7 +74,7 @@ public class EditRelationRoleController extends FormBasicController {
 	private RelationRole relationRole;
 	String[] rightKeys;
 	String[] rightValues;
-	List<RelationRightProvider> rightProviders;
+	List<RightProvider> rightProviders;
 
 	@Autowired
 	private I18nModule i18nModule;
@@ -84,19 +83,15 @@ public class EditRelationRoleController extends FormBasicController {
 	@Autowired
 	private IdentityRelationshipService identityRelationsService;
 	@Autowired
-	private List<RelationRightProvider> relationRights;
+	private List<RightProvider> relationRights;
 
-	public EditRelationRoleController(UserRequest ureq, WindowControl wControl) {
-		this(ureq, wControl,null);
-	}
-	
 	public EditRelationRoleController(UserRequest ureq, WindowControl wControl, RelationRole relationRole) {
 		super(ureq, wControl, Util.createPackageTranslator(UserModule.class, ureq.getLocale()));
 		this.relationRole = relationRole;
 		this.rightKeys = new String[relationRights.size()];
 		this.rightValues = new String[relationRights.size()];
 		this.rightProviders = new ArrayList<>(relationRights.size());
-		this.relationRights.sort(Comparator.comparing(RelationRightProvider::getPosition));
+		this.relationRights.sort(Comparator.comparing(RightProvider::getUserRelationsPosition));
 
 		initForm(ureq);
 	}
@@ -233,7 +228,7 @@ public class EditRelationRoleController extends FormBasicController {
 
 	private void checkDependentRights() {
 		for(int i=0; i < relationRights.size(); i++) {
-			RelationRightProvider rightProvider = rightProviders.get(i);
+			RightProvider rightProvider = rightProviders.get(i);
 
 			if (rightProvider.getParent() != null) {
 				int parentIndex = rightProviders.indexOf(rightProvider.getParent());
diff --git a/src/main/java/org/olat/user/ui/role/RelationRolesAdminController.java b/src/main/java/org/olat/user/ui/role/RelationRolesAdminController.java
index 13cacb6a7bdfec2899496162d61b7fbdae2f75e3..403b334955a7ff9ff6d0409a4cabc5fa89d33165 100644
--- a/src/main/java/org/olat/user/ui/role/RelationRolesAdminController.java
+++ b/src/main/java/org/olat/user/ui/role/RelationRolesAdminController.java
@@ -25,6 +25,7 @@ import java.util.List;
 import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.RelationRole;
+import org.olat.basesecurity.RightProvider;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -77,7 +78,7 @@ public class RelationRolesAdminController extends FormBasicController {
 	private BaseSecurityModule securityModule;
 	@Autowired
 	private IdentityRelationshipService identityRelationsService;
-	
+
 	public RelationRolesAdminController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl, "relation_roles", Util.createPackageTranslator(UserModule.class, ureq.getLocale()));
 		initForm(ureq);
@@ -131,6 +132,7 @@ public class RelationRolesAdminController extends FormBasicController {
 	
 	private void loadModel() {
 		List<RelationRole> relationRoles = identityRelationsService.getAvailableRoles();
+
 		List<RelationRoleRow> rows = new ArrayList<>(relationRoles.size());
 		for(RelationRole relationRole:relationRoles) {
 			rows.add(new RelationRoleRow(relationRole));
@@ -143,9 +145,10 @@ public class RelationRolesAdminController extends FormBasicController {
 	@Override
 	protected void event(UserRequest ureq, Controller source, Event event) {
 		if(editRoleCtrl == source || translatorCtrl == source) {
-			if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
-				loadModel();
+			if(event == Event.DONE_EVENT) {
+				System.out.println("save");
 			}
+			loadModel();
 			cmc.deactivate();
 			cleanUp();
 		} else if(confirmDeleteCtrl == source) {
@@ -207,8 +210,9 @@ public class RelationRolesAdminController extends FormBasicController {
 	
 	private void doAddRole(UserRequest ureq) {
 		if(guardModalController(editRoleCtrl)) return;
-		
-		editRoleCtrl = new EditRelationRoleController(ureq, getWindowControl());
+
+		List<RightProvider> userRelationRights = identityRelationsService.getAvailableRightProviders();
+		editRoleCtrl = new EditRelationRoleController(ureq, getWindowControl(), null);
 		listenTo(editRoleCtrl);
 		
 		cmc = new CloseableModalController(getWindowControl(), "close", editRoleCtrl.getInitialComponent(), true, translate("add.role"));
diff --git a/src/main/java/org/olat/user/ui/role/RelationRolesAndRightsUIFactory.java b/src/main/java/org/olat/user/ui/role/RelationRolesAndRightsUIFactory.java
index 1845f786ddded122571c512534e999414a56cafb..5cceaf0577e17bd7c9fcb30199616ab267a98815 100644
--- a/src/main/java/org/olat/user/ui/role/RelationRolesAndRightsUIFactory.java
+++ b/src/main/java/org/olat/user/ui/role/RelationRolesAndRightsUIFactory.java
@@ -24,7 +24,7 @@ import java.util.Locale;
 import org.apache.logging.log4j.Level;
 import org.olat.basesecurity.IdentityRelationshipService;
 import org.olat.basesecurity.RelationRight;
-import org.olat.basesecurity.RelationRightProvider;
+import org.olat.basesecurity.RightProvider;
 import org.olat.basesecurity.RelationRole;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.translator.Translator;
@@ -46,7 +46,7 @@ public class RelationRolesAndRightsUIFactory {
 	
 	public static String getTranslatedRight(RelationRight right, Locale locale) {
 		IdentityRelationshipService relationshipService = CoreSpringFactory.getImpl(IdentityRelationshipService.class);
-		RelationRightProvider provider = relationshipService.getRelationRightProvider(right);
+		RightProvider provider = relationshipService.getRelationRightProvider(right);
 		return provider != null? provider.getTranslatedName(locale): "???";
 	}
 	
diff --git a/src/main/java/org/olat/user/ui/role/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/role/_i18n/LocalStrings_de.properties
index 761735a8db3fd596f4bea4bfd4183799ae4419d4..e6b93336716fe122cd47c639ae71f96445167cc9 100644
--- a/src/main/java/org/olat/user/ui/role/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/user/ui/role/_i18n/LocalStrings_de.properties
@@ -15,6 +15,7 @@ on=ein
 predefined.labels=Vordefinierte Bezeichnungen
 relations.enable=Rolle Benutzer zu Benutzer
 role.identifier=Bezeichnung
+role.line.manager=Linienvorgesetzter
 role.name=Rolle
 role.rights=Rechte
 table.header.id=ID
diff --git a/src/test/java/org/olat/basesecurity/manager/IdentityToIdentityRelationDAOTest.java b/src/test/java/org/olat/basesecurity/manager/IdentityToIdentityRelationDAOTest.java
index 7bf7b72debad3f3d9cf6226669772c1c39704b4d..b5638f184c6e952ccd6aa207c17e442e159cfee2 100644
--- a/src/test/java/org/olat/basesecurity/manager/IdentityToIdentityRelationDAOTest.java
+++ b/src/test/java/org/olat/basesecurity/manager/IdentityToIdentityRelationDAOTest.java
@@ -57,7 +57,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void createIdentityToIdentityRelation() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		dbInstance.commitAndCloseSession();
@@ -76,7 +76,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void isUsed_yes() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
@@ -90,7 +90,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void isUsed_no() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		dbInstance.commitAndCloseSession();
 		
 		boolean used = identityToIdentityRelationDao.isUsed(relationRole);
@@ -100,7 +100,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void hasRelation() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
@@ -120,7 +120,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getRelation() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, "External-id", "all");
@@ -141,7 +141,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getRelationsAsSource() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
@@ -162,7 +162,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getRelationsAsTarget() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-1");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-2");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
@@ -184,9 +184,9 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getRelationsAsTarget_filterRight() {
 		// Init roles
-		RelationRole roleA = relationRoleDao.createRelationRole(random(), null, null, null);
-		RelationRole roleB = relationRoleDao.createRelationRole(random(), null, null, null);
-		RelationRole roleNoRight = relationRoleDao.createRelationRole(random(), null, null, null);
+		RelationRole roleA = relationRoleDao.createRelationRole(random(), null, null, null, true);
+		RelationRole roleB = relationRoleDao.createRelationRole(random(), null, null, null, true);
+		RelationRole roleNoRight = relationRoleDao.createRelationRole(random(), null, null, null, true);
 		// Init rights
 		relationRightDao.ensureRightExists("testRight");
 		RelationRight right = relationRightDao.loadRelationRightByRight("testRight");
@@ -225,7 +225,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getSources() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-8");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-9");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
@@ -240,7 +240,7 @@ public class IdentityToIdentityRelationDAOTest extends OlatTestCase {
 	@Test
 	public void getTargets() {
 		String role = random();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		Identity idSource = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-8");
 		Identity idTarget = JunitTestHelper.createAndPersistIdentityAsRndUser("id-2-id-9");
 		IdentityToIdentityRelation relation = identityToIdentityRelationDao.createRelation(idSource, idTarget, relationRole, null, null);
diff --git a/src/test/java/org/olat/basesecurity/manager/RelationRoleDAOTest.java b/src/test/java/org/olat/basesecurity/manager/RelationRoleDAOTest.java
index 199cec34436743670461cee74bd9041da66a4cd9..d433ab40a26de3ae83d8009a3bc9c0233140a79d 100644
--- a/src/test/java/org/olat/basesecurity/manager/RelationRoleDAOTest.java
+++ b/src/test/java/org/olat/basesecurity/manager/RelationRoleDAOTest.java
@@ -54,7 +54,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void createRelationRole() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, "External-id", "External-ref", null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, "External-id", "External-ref", null, true);
 		dbInstance.commit();
 		
 		Assert.assertNotNull(relationRole);
@@ -68,7 +68,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void loadRelationRole_byKey() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		dbInstance.commitAndCloseSession();
 		
 		RelationRole loadedRelationRole = relationRoleDao.loadRelationRoleByKey(relationRole.getKey());
@@ -81,7 +81,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void loadRelationRole_byRole() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		dbInstance.commitAndCloseSession();
 		
 		RelationRole loadedRelationRole = relationRoleDao.loadRelationRoleByRole(role);
@@ -96,9 +96,9 @@ public class RelationRoleDAOTest extends OlatTestCase {
 		String role1 = UUID.randomUUID().toString();
 		String role2 = UUID.randomUUID().toString();
 		String roleOther = UUID.randomUUID().toString();
-		RelationRole relationRole1 = relationRoleDao.createRelationRole(role1, null, null, null);
-		RelationRole relationRole2 = relationRoleDao.createRelationRole(role2, null, null, null);
-		RelationRole relationRole3 = relationRoleDao.createRelationRole(roleOther, null, null, null);
+		RelationRole relationRole1 = relationRoleDao.createRelationRole(role1, null, null, null, true);
+		RelationRole relationRole2 = relationRoleDao.createRelationRole(role2, null, null, null, true);
+		RelationRole relationRole3 = relationRoleDao.createRelationRole(roleOther, null, null, null, true);
 		String right1 = UUID.randomUUID().toString();
 		RelationRight relationRight1 = relationRightDao.createRelationRight(right1);
 		String rightOther = UUID.randomUUID().toString();
@@ -117,7 +117,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void addRight() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		String right = UUID.randomUUID().toString();
 		RelationRight relationRight = relationRightDao.createRelationRight(right);
 		relationRoleDao.addRight(relationRole, relationRight);
@@ -138,7 +138,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void setRights_once() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		String right = UUID.randomUUID().toString();
 		RelationRight relationRight1 = relationRightDao.createRelationRight(right + "-1");
 		RelationRight relationRight2 = relationRightDao.createRelationRight(right + "-2");
@@ -167,7 +167,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void setRights_twice() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		String right = UUID.randomUUID().toString();
 		RelationRight relationRight1 = relationRightDao.createRelationRight(right + "-1");
 		RelationRight relationRight2 = relationRightDao.createRelationRight(right + "-2");
@@ -217,7 +217,7 @@ public class RelationRoleDAOTest extends OlatTestCase {
 	@Test
 	public void deleteRelationRole() {
 		String role = UUID.randomUUID().toString();
-		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null);
+		RelationRole relationRole = relationRoleDao.createRelationRole(role, null, null, null, true);
 		String right = UUID.randomUUID().toString();
 		RelationRight relationRight1 = relationRightDao.createRelationRight(right + "-1");
 		RelationRight relationRight2 = relationRightDao.createRelationRight(right + "-2");