From c237cf301c4ddeacbcc70666d9126abb01a5637b Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 24 Nov 2015 14:26:38 +0100
Subject: [PATCH] OO-1593: add group filters, show group list for group
 tasks...

---
 .../flexible/elements/FlexiTableElement.java  |  10 ++
 .../table/AbstractFlexiTableRenderer.java     |   7 +-
 .../DefaultFlexiTableDataSourceModel.java     |   9 +-
 .../table/ExtendedFilterController.java       | 128 +++++++++++++++++
 .../elements/table/FlexiTableDataSource.java  |   3 +-
 .../table/FlexiTableDataSourceDelegate.java   |   3 +-
 .../elements/table/FlexiTableElementImpl.java | 130 +++++++++++++-----
 .../elements/table/FlexiTableSearchEvent.java |  19 ++-
 .../table/_content/extended_filters.html      |   5 +
 .../manager/AssessmentToolManagerImpl.java    |   9 +-
 .../model/SearchAssessedIdentityParams.java   |  42 +++++-
 .../AssessmentIdentitiesCourseController.java |  68 ++++++++-
 ...essmentIdentitiesCourseNodeController.java |  69 +++++++++-
 ...essmentIdentitiesCourseTreeController.java |  11 +-
 .../ui/tool/_i18n/LocalStrings_de.properties  |   7 +
 .../course/nodes/AssessableCourseNode.java    |   6 +
 .../olat/course/nodes/BasicLTICourseNode.java |   5 +
 .../course/nodes/CheckListCourseNode.java     |   5 +
 .../org/olat/course/nodes/GTACourseNode.java  |  23 +++-
 .../olat/course/nodes/IQTESTCourseNode.java   |   5 +
 .../org/olat/course/nodes/MSCourseNode.java   |  24 ++++
 .../course/nodes/PortfolioCourseNode.java     |   5 +
 .../course/nodes/ProjectBrokerCourseNode.java |  25 ++++
 .../org/olat/course/nodes/STCourseNode.java   |   9 ++
 .../olat/course/nodes/ScormCourseNode.java    |  43 +++---
 .../org/olat/course/nodes/TACourseNode.java   |   6 +
 .../ui/GTAAssessmentDetailsController.java    |   2 +-
 .../gta/ui/GTACoachSelectionController.java   |   2 +-
 .../gta/ui/GTACoachedGroupListController.java |  21 ++-
 .../course/run/CourseRuntimeController.java   |   7 +-
 .../ims/qti21/ui/QTI21RuntimeController.java  |   3 +-
 .../model/AssessmentEntryStatus.java          |  13 +-
 .../ui/AssessmentToolSecurityCallback.java    |  13 +-
 .../qpool/ui/AbstractItemListController.java  |   3 +-
 .../ui/author/AuthoringEntryDataSource.java   |   9 +-
 .../DefaultRepositoryEntryDataSource.java     |  11 +-
 .../_spring/userPropertiesContext.xml         |   6 +-
 37 files changed, 669 insertions(+), 97 deletions(-)
 create mode 100644 src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/ExtendedFilterController.java
 create mode 100644 src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_content/extended_filters.html

diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
index 3b6e0d16972..9a9a748260d 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
@@ -221,6 +221,8 @@ public interface FlexiTableElement extends FormItem {
 	 */
 	public boolean isFilterEnabled();
 	
+	public List<FlexiTableFilter> getSelectedFilters();
+	
 	/**
 	 * @return The selected key by the filter, or null if no item is selected
 	 */
@@ -294,6 +296,14 @@ public interface FlexiTableElement extends FormItem {
 	 */
 	public void collapseExtendedSearch();
 	
+	/**
+	 * Setup a filter button right of the quick search
+	 * @param label
+	 */
+	public void setExtendedFilterButton(String label, List<FlexiTableFilter> extendedFilters);
+	
+	public List<FlexiTableFilter> getSelectedExtendedFilters();
+	
 	/**
 	 * Is the details view visible for this particular row?
 	 */
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
index c32a98922a5..d7bea92a663 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
@@ -134,7 +134,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 		}
 		sb.append("</div>");
 
-		sb.append("<div class='col-sm-3 col-xs-4 o_table_row_count'>");
+		sb.append("<div class='col-sm-2 col-xs-4 o_table_row_count'>");
 		if(ftE.isNumOfRowsEnabled()) {
 			int rowCount = ftE.getTableDataModel().getRowCount();
 			if(rowCount == 1) {
@@ -143,7 +143,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 				sb.append(rowCount).append(" ").append(ftE.getTranslator().translate("table.entries"));
 			}
 		}
-		sb.append("</div><div class='col-sm-3 col-xs-8'><div class='pull-right'><div class='o_table_tools'>");
+		sb.append("</div><div class='col-sm-4 col-xs-8'><div class='pull-right'><div class='o_table_tools'>");
 		
 		boolean empty = ftE.getTableDataModel().getRowCount() == 0;
 
@@ -206,6 +206,9 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 			if(ftE.getExtendedSearchButton() != null) {
 				renderFormItem(renderer, sb, ftE.getExtendedSearchButton(), ubu, translator, renderResult, args);
 			}
+			if(ftE.getExtendedFilterButton() != null) {
+				renderFormItem(renderer, sb, ftE.getExtendedFilterButton(), ubu, translator, renderResult, args);
+			}
 			sb.append("</div></div>");
 		} else if(ftE.getExtendedSearchButton() != null) {
 			renderFormItem(renderer, sb, ftE.getExtendedSearchButton(), ubu, translator, renderResult, args);
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTableDataSourceModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTableDataSourceModel.java
index e4de3f4189d..b7d677f4b95 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTableDataSourceModel.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTableDataSourceModel.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import org.olat.core.commons.persistence.DefaultResultInfos;
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.table.TableDataModel;
 
 /**
@@ -166,11 +167,11 @@ public abstract class DefaultFlexiTableDataSourceModel<U> implements FlexiTableD
 	}
 
 	@Override
-	public ResultInfos<U> load(String query, List<String> addQueries, int firstResult, int maxResults, SortKey... orderBy) {
-		return loadDatas(query, addQueries, false, firstResult, maxResults, orderBy);
+	public ResultInfos<U> load(String query, List<FlexiTableFilter> filters, List<String> addQueries, int firstResult, int maxResults, SortKey... orderBy) {
+		return loadDatas(query, filters, addQueries, false, firstResult, maxResults, orderBy);
 	}
 	
-	private ResultInfos<U> loadDatas(String query, List<String> addQueries, final boolean force, final int firstResult, final int maxResults, SortKey... orderBy) {
+	private ResultInfos<U> loadDatas(String query, List<FlexiTableFilter> filters, List<String> addQueries, final boolean force, final int firstResult, final int maxResults, SortKey... orderBy) {
 		if(rows == null) {
 			rows = new ArrayList<U>();
 		}
@@ -198,7 +199,7 @@ public abstract class DefaultFlexiTableDataSourceModel<U> implements FlexiTableD
 			}
 		}
 		
-		ResultInfos<U> newRows = sourceDelegate.getRows(query, addQueries, correctedFirstResult, correctMaxResults, orderBy);
+		ResultInfos<U> newRows = sourceDelegate.getRows(query, filters, addQueries, correctedFirstResult, correctMaxResults, orderBy);
 		if(firstResult == 0) {
 			if(newRows.getObjects().size() < correctMaxResults) {
 				rowCount = newRows.getObjects().size();
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/ExtendedFilterController.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/ExtendedFilterController.java
new file mode 100644
index 00000000000..d073edc5aef
--- /dev/null
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/ExtendedFilterController.java
@@ -0,0 +1,128 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.core.gui.components.form.flexible.impl.elements.table;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.olat.core.gui.UserRequest;
+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.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.FormLayoutContainer;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.control.Event;
+import org.olat.core.gui.control.WindowControl;
+
+/**
+ * 
+ * Initial date: 23.11.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ExtendedFilterController extends FormBasicController {
+	
+	private final List<FlexiTableFilter> filters;
+	
+	public ExtendedFilterController(UserRequest ureq, WindowControl wControl, List<FlexiTableFilter> filters) {
+		super(ureq, wControl, "extended_filters");
+		this.filters = new ArrayList<>(filters);
+		initForm(ureq);
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		int count = 0;
+		List<ExtendedFilter> filterNames = new ArrayList<>(filters.size());
+		for(FlexiTableFilter filter:filters) {
+			String name = "f-" + (++count);
+			FormLink filterLink = uifactory.addFormLink(name, formLayout, Link.LINK | Link.NONTRANSLATED);
+			filterLink.setI18nKey(filter.getLabel());
+			filterLink.setIconLeftCSS(filter.getIconLeftCSS());
+			filterLink.setUserObject(filter);
+			filterNames.add(new ExtendedFilter(filter, name));
+		}
+		
+		if(formLayout instanceof FormLayoutContainer) {
+			((FormLayoutContainer)formLayout).contextPut("filters", filterNames);
+		}
+	}
+	
+	@Override
+	protected void doDispose() {
+		//
+	}
+	
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(source instanceof FormLink) {
+			FormLink link = (FormLink)source;
+			Object uobject = link.getUserObject();
+			if(uobject instanceof FlexiTableFilter) {
+				FlexiTableFilter filter = (FlexiTableFilter)uobject;
+				filter.setSelected(!filter.isSelected());
+			}
+		}
+		fireEvent(ureq, Event.DONE_EVENT);
+		super.formInnerEvent(ureq, source, event);
+	}
+	
+	public List<FlexiTableFilter> getFilters() {
+		List<FlexiTableFilter> selectedFilters = new ArrayList<>();
+		for(FlexiTableFilter filter:filters) {
+			if(filter.isSelected()) {
+				selectedFilters.add(filter);
+			}
+		}
+		return selectedFilters;
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+
+	public static final class ExtendedFilter {
+		
+		private final FlexiTableFilter filter;
+		private final String componentName;
+		
+		public ExtendedFilter(FlexiTableFilter filter, String componentName) {
+			this.filter = filter;
+			this.componentName = componentName;
+		}
+
+		public FlexiTableFilter getFilter() {
+			return filter;
+		}
+		
+		public boolean isSelected() {
+			return filter.isSelected();
+		}
+
+		public String getComponentName() {
+			return componentName;
+		}
+	}
+}
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSource.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSource.java
index d72b758a5ba..c95a2ed06f6 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSource.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSource.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 
 /**
  * 
@@ -50,6 +51,6 @@ public interface FlexiTableDataSource<U> extends FlexiTableDataModel<U> {
 	 * @param maxResults
 	 * @param orderBy
 	 */
-	public ResultInfos<U> load(String query, List<String> addQueries, int firstResult, int maxResults, SortKey... orderBy);
+	public ResultInfos<U> load(String query, List<FlexiTableFilter> filters, List<String> addQueries, int firstResult, int maxResults, SortKey... orderBy);
 
 }
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSourceDelegate.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSourceDelegate.java
index 24cb63e80ae..b72754b88a7 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSourceDelegate.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableDataSourceDelegate.java
@@ -23,6 +23,7 @@ import java.util.List;
 
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 
 /**
  * 
@@ -36,5 +37,5 @@ public interface FlexiTableDataSourceDelegate<V> {
 	
 	public List<V> reload(List<V> rows);
 	
-	public ResultInfos<V> getRows(String query, List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy);
+	public ResultInfos<V> getRows(String query, List<FlexiTableFilter> filters, List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy);
 }
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
index f22abb3eacf..ef52f2a8e3f 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
@@ -26,7 +26,6 @@
 package org.olat.core.gui.components.form.flexible.impl.elements.table;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -35,7 +34,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -67,7 +65,6 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableCalloutWindowController;
 import org.olat.core.gui.media.MediaResource;
-import org.olat.core.gui.media.ServletUtil;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
@@ -115,7 +112,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	private FormLink customButton, exportButton;
 	private FormLink searchButton, extendedSearchButton;
 	private FormLink classicTypeButton, customTypeButton;
+	private FormLink extendedFilterButton;
 	private AbstractTextElement searchFieldEl;
+	private ExtendedFilterController extendedFilterCtrl;
 	private ExtendedFlexiTableSearchController extendedSearchCtrl;
 	
 	private final FlexiTableDataModel<?> dataModel;
@@ -131,6 +130,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	private SortKey[] orderBy;
 	private FlexiTableSortOptions sortOptions;
 	private List<FlexiTableFilter> filters;
+	private List<FlexiTableFilter> extendedFilters;
 	private Object selectedObj;
 	private boolean allSelectedNeedLoadOfWholeModel = false;
 	private Set<Integer> multiSelectedIndex;
@@ -174,7 +174,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		
 		if(dataSource != null && loadOnStart) {
 			//preload it
-			dataSource.load(null, null, 0, pageSize);
+			dataSource.load(null, null, null, 0, pageSize);
 		}
 	}
 
@@ -343,6 +343,19 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		return filters != null && filters.size() > 0;
 	}
 
+	@Override
+	public List<FlexiTableFilter> getSelectedFilters() {
+		List<FlexiTableFilter> selectedFilters = new ArrayList<>(2);
+		if(filters != null) {
+			for(FlexiTableFilter filter:filters) {
+				if(filter.isSelected()) {
+					selectedFilters.add(filter);
+				}
+			}
+		}
+		return selectedFilters;
+	}
+
 	@Override
 	public String getSelectedFilterKey() {
 		String key = null;
@@ -541,6 +554,42 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		}
 	}
 	
+	@Override
+	public void setExtendedFilterButton(String label, List<FlexiTableFilter> extendedFilters) {
+		if(StringHelper.containsNonWhitespace(label) && extendedFilters != null && extendedFilters.size() > 0) {
+			this.extendedFilters = extendedFilters;
+			
+			String dispatchId = component.getDispatchID();
+			extendedFilterButton = new FormLinkImpl(dispatchId + "_extFilterButton", "rExtFilterButton", "extfilter", Link.BUTTON | Link.NONTRANSLATED);
+			extendedFilterButton.setI18nKey(label);
+			extendedFilterButton.setTranslator(translator);
+			extendedFilterButton.setIconLeftCSS("o_icon o_icon_filter");
+			components.put("rExtFilterB", extendedFilterButton);
+			rootFormAvailable(extendedFilterButton);
+			extendedFilterButton.setElementCssClass("o_sel_flexi_extendedsearch");
+		} else {
+			extendedFilterButton = null;
+			extendedFilters = null;
+		}
+	}
+	
+	@Override
+	public List<FlexiTableFilter> getSelectedExtendedFilters() {
+		List<FlexiTableFilter> selectedFilters = new ArrayList<>();
+		if(extendedFilters != null && extendedFilters.size() > 0) {
+			for(FlexiTableFilter extendedFilter:extendedFilters) {
+				if(extendedFilter.isSelected()) {
+					selectedFilters.add(extendedFilter);
+				}
+			}
+		}
+		return selectedFilters;
+	}
+	
+	public FormLink getExtendedFilterButton() {
+		return extendedFilterButton;
+	}
+	
 	@Override
 	public boolean isSelectAllEnable() {
 		return selectAllEnabled;
@@ -668,7 +717,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		if(dataSource != null) {
 			int firstResult = currentPage * getPageSize();
 			int maxResults = getPageSize();
-			dataSource.load(getSearchText(), getConditionalQueries(), firstResult, maxResults, orderBy);
+			dataSource.load(getSearchText(), getSelectedFilters(), getConditionalQueries(), firstResult, maxResults, orderBy);
 		}
 		component.setDirty(true);
 	}
@@ -720,7 +769,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		String filter = form.getRequestParameter("filter");
 		String pagesize = form.getRequestParameter("pagesize");
 		String checkbox = form.getRequestParameter("chkbox");
-		ServletUtil.printOutRequestParameters(ureq.getHttpReq());
 		if("undefined".equals(dispatchuri)) {
 			evalSearchRequest(ureq);
 		} else if(StringHelper.containsNonWhitespace(checkbox)) {
@@ -754,6 +802,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		} else if(extendedSearchButton != null
 				&& extendedSearchButton.getFormDispatchId().equals(dispatchuri)) {
 			expandExtendedSearch(ureq);
+		} else if(extendedFilterButton != null
+				&& extendedFilterButton.getFormDispatchId().equals(dispatchuri)) {
+			extendedFilterCallout(ureq);
 		} else if(dispatchuri != null && StringHelper.containsNonWhitespace(filter)) {
 			doFilter(filter);
 		} else if(exportButton != null
@@ -812,6 +863,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			} else if(event == Event.DONE_EVENT) {
 				evalExtendedSearch(ureq);
 			}
+		} else if(source == extendedFilterCtrl) {
+			doExtendedFilter(ureq);
+			callout.deactivate();
 		}
 	}
 	
@@ -860,7 +914,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		} else if(dataSource != null) {
 			currentPage = 0;
 			dataSource.clear();
-			dataSource.load(null, conditionalQueries, 0, getPageSize(), orderBy);
+			dataSource.load(null, getSelectedFilters(), conditionalQueries, 0, getPageSize(), orderBy);
 		}
 
 		selectSortOption(sortKey, asc);
@@ -883,6 +937,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	
 	private void doFilter(String filterKey) {
 		String selectedFilterKey = null;
+		FlexiTableFilter selectedFilter = null;
 		if(filterKey == null) {
 			for(FlexiTableFilter filter:filters) {
 				filter.setSelected(false);
@@ -896,6 +951,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 					} else {
 						filter.setSelected(true);
 						selectedFilterKey = filterKey;
+						selectedFilter = filter;
 					}
 				} else {
 					filter.setSelected(false);
@@ -911,17 +967,31 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			rowCount = -1;
 			currentPage = 0;
 
-			List<String> addQueries = Collections.singletonList(selectedFilterKey);
+			List<FlexiTableFilter> selectedFilters = Collections.singletonList(selectedFilter);
 			dataSource.clear();
-			dataSource.load(null, addQueries, 0, getPageSize(), orderBy);
+			dataSource.load(null, selectedFilters, null, 0, getPageSize(), orderBy);
 		}
 		component.setDirty(true);
 	}
 	
+	private void doExtendedFilter(UserRequest ureq) {
+		if(dataSource != null) {
+			rowCount = -1;
+			currentPage = 0;
+
+			List<FlexiTableFilter> selectedFilters = new ArrayList<>(extendedFilters);
+			dataSource.clear();
+			dataSource.load(null, selectedFilters, null, 0, getPageSize(), orderBy);
+		}
+
+		getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(FlexiTableSearchEvent.EXTENDED_FILTER, this,
+				getSearchText(), getSelectedFilters(), getSelectedExtendedFilters(), getConditionalQueries(), FormEvent.ONCLICK));
+	}
+	
 	private void doExport(UserRequest ureq) {
 		// ensure the all rows are loaded to export
 		if(dataSource != null) {
-			dataSource.load(getSearchText(), getConditionalQueries(), 0, -1, orderBy);
+			dataSource.load(getSearchText(), getSelectedFilters(), getConditionalQueries(), 0, -1, orderBy);
 		}
 		
 		MediaResource resource;
@@ -943,6 +1013,15 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			searchFieldEl.setVisible(false);
 		}
 	}
+
+	private void extendedFilterCallout(UserRequest ureq) {
+		extendedFilterCtrl = new ExtendedFilterController(ureq, wControl, extendedFilters);
+		extendedFilterCtrl.addControllerListener(this);
+		callout = new CloseableCalloutWindowController(ureq, wControl, extendedFilterCtrl.getInitialComponent(),
+				extendedFilterButton, "Filter", true, "o_sel_flexi_filter_callout");
+		callout.activate();
+		callout.addControllerListener(this);
+	}
 	
 	@Override
 	public void collapseExtendedSearch() {
@@ -1207,29 +1286,10 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			currentPage = 0;
 			resetInternComponents();
 			dataSource.clear();
-			dataSource.load(search, conditionalQueries, 0, getPageSize(), orderBy);
-		}
-		getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(eventCmd, this, search, condQueries, FormEvent.ONCLICK));
-	}
-	
-	protected ResultInfos<?> doScroll(int firstResult, int maxResults, SortKey... sortKeys) {
-		boolean same = isOrderByEqual(sortKeys);
-		if(!same) {
-			//clear data source
-			dataSource.clear();
-			orderBy = sortKeys;
-		}
-		
-		return dataSource.load(getSearchText(), getConditionalQueries(), firstResult, maxResults, sortKeys);
-	}
-	
-	private boolean isOrderByEqual(SortKey... sortKeys) {
-		if(orderBy == null &&
-				(sortKeys == null || sortKeys.length == 0 ||
-					(sortKeys.length == 1 && sortKeys[0] == null))) {
-			return true;
+			dataSource.load(search, getSelectedFilters(), conditionalQueries, 0, getPageSize(), orderBy);
 		}
-		return Arrays.equals(orderBy , sortKeys);
+		getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(eventCmd, this,
+				search, getSelectedFilters(), getSelectedExtendedFilters(), condQueries, FormEvent.ONCLICK));
 	}
 	
 	protected void doResetSearch(UserRequest ureq) {
@@ -1238,7 +1298,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		if(dataSource != null) {
 			resetInternComponents();
 			dataSource.clear();
-			dataSource.load(null, null, 0, getPageSize());
+			dataSource.load(null, null, null, 0, getPageSize());
 		} else {
 			getRootForm().fireFormEvent(ureq, new FlexiTableSearchEvent(this, FormEvent.ONCLICK));
 		}
@@ -1248,7 +1308,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	public Set<Integer> getMultiSelectedIndex() {
 		if(allSelectedNeedLoadOfWholeModel && dataSource != null) {
 			//ensure the whole data model is loaded
-			dataSource.load(getSearchText(), getConditionalQueries(), 0, -1);
+			dataSource.load(getSearchText(), getSelectedFilters(), getConditionalQueries(), 0, -1);
 			Set<Integer> allIndex = new HashSet<Integer>();
 			for(int i=dataModel.getRowCount(); i-->0; ) {
 				allIndex.add(new Integer(i));
@@ -1350,7 +1410,7 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		if(dataSource != null) {
 			dataSource.clear();
 			int firstResult = currentPage * getPageSize();
-			dataSource.load(getSearchText(), getConditionalQueries(), firstResult, getPageSize(), orderBy);//reload needed rows
+			dataSource.load(getSearchText(), getSelectedFilters(), getConditionalQueries(), firstResult, getPageSize(), orderBy);//reload needed rows
 		} else {
 			if(dataModel instanceof FilterableFlexiTableModel) {
 				if(isFilterEnabled()) {
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableSearchEvent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableSearchEvent.java
index cce665c23f7..280beb08295 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableSearchEvent.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableSearchEvent.java
@@ -22,6 +22,7 @@ package org.olat.core.gui.components.form.flexible.impl.elements.table;
 import java.util.List;
 
 import org.olat.core.gui.components.form.flexible.FormItem;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 
 /**
@@ -37,20 +38,28 @@ public class FlexiTableSearchEvent extends FormEvent {
 	public static final String SEARCH = "ftSearch";
 	public static final String QUICK_SEARCH = "ftQuickSearch";
 	public static final String QUICK_SEARCH_KEY_SELECTION = "ftQuickSearchSelectKey";
+	public static final String EXTENDED_FILTER = "ftEXTENDEDFILTER";
 
 	private final String search;
 	private final List<String> condQueries;
+	private final List<FlexiTableFilter> filters;
+	private final List<FlexiTableFilter> extendedFilters;
 
-	public FlexiTableSearchEvent(String cmd, FormItem source, String search, List<String> condQueries, int action) {
+	public FlexiTableSearchEvent(String cmd, FormItem source, String search, List<FlexiTableFilter> filters,
+			List<FlexiTableFilter> extendedFilters, List<String> condQueries, int action) {
 		super(cmd, source, action);
 		this.search = search;
+		this.filters = filters;
 		this.condQueries = condQueries;
+		this.extendedFilters = extendedFilters;
 	}
 	
 	public FlexiTableSearchEvent(FormItem source, int action) {
 		super(RESET, source, action);
 		this.search = null;
+		this.filters = null;
 		this.condQueries = null;
+		this.extendedFilters = null;
 	}
 
 	public String getSearch() {
@@ -60,4 +69,12 @@ public class FlexiTableSearchEvent extends FormEvent {
 	public List<String> getCondQueries() {
 		return condQueries;
 	}
+
+	public List<FlexiTableFilter> getFilters() {
+		return filters;
+	}
+
+	public List<FlexiTableFilter> getExtendedFilters() {
+		return extendedFilters;
+	}
 }
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_content/extended_filters.html b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_content/extended_filters.html
new file mode 100644
index 00000000000..943097d9994
--- /dev/null
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/_content/extended_filters.html
@@ -0,0 +1,5 @@
+<ul class="list-unstyled">
+#foreach($filter in $filters)
+	<li>#if($filter.selected)<i class="o_icon o_icon_check"> </i> #end$r.render($filter.componentName)</li>
+#end
+</ul>
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
index e6a4fcb6f1d..ee439ebb13f 100644
--- a/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
+++ b/src/main/java/org/olat/course/assessment/manager/AssessmentToolManagerImpl.java
@@ -196,7 +196,11 @@ public class AssessmentToolManagerImpl implements AssessmentToolManager {
 		sb.append(" from ").append(IdentityImpl.class.getName()).append(" as ident ")
 		  .append(" inner join ident.user user ")
 		  .append(" where ");
-		if(params.isAdmin()) {
+		if(params.getBusinessGroupKeys() != null && params.getBusinessGroupKeys().size() > 0) {
+			sb.append(" ident.key in (select participant.identity.key from repoentrytogroup as rel, businessgroup bgi, bgroupmember as participant")
+	          .append("    where rel.entry.key=:repoEntryKey and rel.group=bgi.baseGroup and rel.group=participant.group and bgi.key in (:businessGroupKeys) ")
+	          .append("  )");
+		} else if(params.isAdmin()) {
 			sb.append(" (ident.key in (select participant.identity.key from repoentrytogroup as rel, bgroupmember as participant")
 	          .append("    where rel.entry.key=:repoEntryKey and rel.group=participant.group")
 	          .append("      and participant.role='").append(GroupRoles.participant.name()).append("'")
@@ -231,6 +235,9 @@ public class AssessmentToolManagerImpl implements AssessmentToolManager {
 		if(identityKey != null) {
 			query.setParameter("searchIdentityKey", identityKey);
 		}
+		if(params.getBusinessGroupKeys() != null && params.getBusinessGroupKeys().size() > 0) {
+			query.setParameter("businessGroupKeys", params.getBusinessGroupKeys());
+		}
 		appendUserSearchToQuery(searchArr, query);
 		return query;
 	}
diff --git a/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java b/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java
index c41bd679286..261d082815e 100644
--- a/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java
+++ b/src/main/java/org/olat/course/assessment/model/SearchAssessedIdentityParams.java
@@ -19,6 +19,9 @@
  */
 package org.olat.course.assessment.model;
 
+import java.util.List;
+
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 
@@ -39,7 +42,12 @@ public class SearchAssessedIdentityParams {
 	private final boolean repositoryEntryCoach;
 	private final boolean businessGroupCoach;
 	
+	private boolean passed;
+	private boolean failed;
+	private List<AssessmentEntryStatus> assessmentStatus;
+	
 	private String searchString;
+	private List<Long> businessGroupKeys;
 	
 	public SearchAssessedIdentityParams(RepositoryEntry entry, RepositoryEntry referenceEntry, String subIdent,
 			AssessmentToolSecurityCallback secCallback) {
@@ -87,6 +95,36 @@ public class SearchAssessedIdentityParams {
 	public void setSearchString(String searchString) {
 		this.searchString = searchString;
 	}
-	
-	
+
+	public boolean isPassed() {
+		return passed;
+	}
+
+	public void setPassed(boolean passed) {
+		this.passed = passed;
+	}
+
+	public boolean isFailed() {
+		return failed;
+	}
+
+	public void setFailed(boolean failed) {
+		this.failed = failed;
+	}
+
+	public List<AssessmentEntryStatus> getAssessmentStatus() {
+		return assessmentStatus;
+	}
+
+	public void setAssessmentStatus(List<AssessmentEntryStatus> assessmentStatus) {
+		this.assessmentStatus = assessmentStatus;
+	}
+
+	public List<Long> getBusinessGroupKeys() {
+		return businessGroupKeys;
+	}
+
+	public void setBusinessGroupKeys(List<Long> businessGroupKeys) {
+		this.businessGroupKeys = businessGroupKeys;
+	}
 }
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseController.java
index 5a3bbd3d71b..7cb1f228844 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseController.java
+++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseController.java
@@ -34,6 +34,7 @@ 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.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
@@ -49,7 +50,10 @@ 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.id.Identity;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentMainController;
 import org.olat.course.assessment.AssessmentToolManager;
 import org.olat.course.assessment.bulk.PassedCellRenderer;
@@ -58,6 +62,8 @@ import org.olat.course.assessment.ui.tool.AssessmentIdentitiesCourseTableModel.I
 import org.olat.course.certificate.CertificateLight;
 import org.olat.course.certificate.CertificatesManager;
 import org.olat.course.certificate.ui.DownloadCertificateCellRenderer;
+import org.olat.group.BusinessGroup;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
 import org.olat.modules.coach.CoachingService;
 import org.olat.modules.coach.model.EfficiencyStatementEntry;
@@ -112,7 +118,7 @@ public class AssessmentIdentitiesCourseController extends FormBasicController {
 		userPropertyHandlers = userManager.getUserPropertyHandlersFor(AssessmentToolConstants.usageIdentifyer, isAdministrativeUser);
 
 		initForm(ureq);
-		loadModel(null);
+		loadModel(null, null, null);
 	}
 
 	@Override
@@ -141,11 +147,66 @@ public class AssessmentIdentitiesCourseController extends FormBasicController {
 		tableEl = uifactory.addTableElement(getWindowControl(), "table", usersTableModel, 20, false, getTranslator(), formLayout);
 		tableEl.setExportEnabled(true);
 		tableEl.setSearchEnabled(new AssessedIdentityListProvider(getIdentity(), courseEntry, null, null, assessmentCallback), ureq.getUserSession());
+		
+		List<FlexiTableFilter> filters = new ArrayList<>();
+		filters.add(new FlexiTableFilter(translate("filter.passed"), "passed"));
+		filters.add(new FlexiTableFilter(translate("filter.failed"), "failed"));
+		filters.add(new FlexiTableFilter(translate("filter.inProgress"), "inProgress"));
+		filters.add(new FlexiTableFilter(translate("filter.inReview"), "inReview"));
+		filters.add(new FlexiTableFilter(translate("filter.done"), "done"));
+		tableEl.setFilters("", filters);
+
+		if(assessmentCallback.canAssessBusinessGoupMembers()) {
+			List<BusinessGroup> coachedGroups = null;;
+			if(assessmentCallback.isAdmin()) {
+				ICourse course = CourseFactory.loadCourse(courseEntry);
+				coachedGroups = course.getCourseEnvironment().getCourseGroupManager().getAllBusinessGroups();
+			} else {
+				coachedGroups = assessmentCallback.getCoachedGroups(); 
+			}
+
+			if(coachedGroups.size() > 0) {
+				List<FlexiTableFilter> groupFilters = new ArrayList<>();
+				for(BusinessGroup coachedGroup:coachedGroups) {
+					groupFilters.add(new FlexiTableFilter(coachedGroup.getName(), coachedGroup.getKey().toString(), "o_icon o_icon_group"));
+				}
+				
+				tableEl.setExtendedFilterButton(translate("filter.groups"), groupFilters);
+			}
+		}
 	}
 	
-	public List<EfficiencyStatementEntry> loadModel(String searchStr) {
+	public List<EfficiencyStatementEntry> loadModel(String searchStr, List<FlexiTableFilter> filters, List<FlexiTableFilter> extendedFilters) {
+
 		SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(courseEntry, null, null, assessmentCallback);
+		
+		List<AssessmentEntryStatus> assessmentStatus = null;
+		if(filters != null && filters.size() > 0) {
+			assessmentStatus = new ArrayList<>(filters.size());
+			for(FlexiTableFilter filter:filters) {
+				if("passed".equals(filter.getFilter())) {
+					params.setPassed(true);
+				} else if("failed".equals(filter.getFilter())) {
+					params.setFailed(true);
+				} else if(AssessmentEntryStatus.isValueOf(filter.getFilter())){
+					assessmentStatus.add(AssessmentEntryStatus.valueOf(filter.getFilter()));
+				}
+			}
+		}
+		params.setAssessmentStatus(assessmentStatus);
+		
+		List<Long> businessGroupKeys = null;
+		if(extendedFilters != null && extendedFilters.size() > 0) {
+			businessGroupKeys = new ArrayList<>(extendedFilters.size());
+			for(FlexiTableFilter extendedFilter:extendedFilters) {
+				if(StringHelper.isLong(extendedFilter.getFilter())) {
+					businessGroupKeys.add(Long.parseLong(extendedFilter.getFilter()));
+				}
+			}
+		}
+		params.setBusinessGroupKeys(businessGroupKeys);
 		params.setSearchString(searchStr);
+		
 		List<Identity> assessedIdentities = assessmentToolManager.getAssessedIdentities(getIdentity(), params);
 		List<EfficiencyStatementEntry> entries = coachingService.getCourse(getIdentity(), courseEntry);
 		Map<Long,EfficiencyStatementEntry> identityKeyToStatementMap = entries.stream()
@@ -201,8 +262,7 @@ public class AssessmentIdentitiesCourseController extends FormBasicController {
 				}
 			} else if(event instanceof FlexiTableSearchEvent) {
 				FlexiTableSearchEvent ftse = (FlexiTableSearchEvent)event;
-				String searchKey = ftse.getSearch();
-				loadModel(searchKey);
+				loadModel(ftse.getSearch(), ftse.getFilters(), ftse.getExtendedFilters());
 			}
 		}
 		
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseNodeController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseNodeController.java
index c94fc829ec3..c47cd0a704b 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseNodeController.java
+++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseNodeController.java
@@ -31,6 +31,7 @@ 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.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
@@ -47,7 +48,10 @@ 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.id.Identity;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentMainController;
 import org.olat.course.assessment.AssessmentToolManager;
 import org.olat.course.assessment.bulk.PassedCellRenderer;
@@ -56,7 +60,9 @@ import org.olat.course.assessment.ui.tool.AssessmentIdentitiesCourseNodeTableMod
 import org.olat.course.nodes.AssessableCourseNode;
 import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.CourseNodeFactory;
+import org.olat.group.BusinessGroup;
 import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 import org.olat.user.UserManager;
@@ -115,7 +121,7 @@ public class AssessmentIdentitiesCourseNodeController extends FormBasicControlle
 		userPropertyHandlers = userManager.getUserPropertyHandlersFor(AssessmentToolConstants.usageIdentifyer, isAdministrativeUser);
 		
 		initForm(ureq);
-		updateModel(null);
+		updateModel(null, null, null);
 	}
 
 	@Override
@@ -164,11 +170,65 @@ public class AssessmentIdentitiesCourseNodeController extends FormBasicControlle
 		tableEl = uifactory.addTableElement(getWindowControl(), "table", usersTableModel, 20, false, getTranslator(), formLayout);
 		tableEl.setExportEnabled(true);
 		tableEl.setSearchEnabled(new AssessedIdentityListProvider(getIdentity(), courseEntry, referenceEntry, courseNode.getIdent(), assessmentCallback), ureq.getUserSession());
+		
+		List<FlexiTableFilter> filters = new ArrayList<>();
+		filters.add(new FlexiTableFilter(translate("filter.passed"), "passed"));
+		filters.add(new FlexiTableFilter(translate("filter.failed"), "failed"));
+		filters.add(new FlexiTableFilter(translate("filter.inProgress"), "inProgress"));
+		filters.add(new FlexiTableFilter(translate("filter.inReview"), "inReview"));
+		filters.add(new FlexiTableFilter(translate("filter.done"), "done"));
+		tableEl.setFilters("", filters);
+		
+		if(assessmentCallback.canAssessBusinessGoupMembers()) {
+			List<BusinessGroup> coachedGroups = null;;
+			if(assessmentCallback.isAdmin()) {
+				ICourse course = CourseFactory.loadCourse(courseEntry);
+				coachedGroups = course.getCourseEnvironment().getCourseGroupManager().getAllBusinessGroups();
+			} else {
+				coachedGroups = assessmentCallback.getCoachedGroups(); 
+			}
+
+			if(coachedGroups.size() > 0) {
+				List<FlexiTableFilter> groupFilters = new ArrayList<>();
+				for(BusinessGroup coachedGroup:coachedGroups) {
+					groupFilters.add(new FlexiTableFilter(coachedGroup.getName(), coachedGroup.getKey().toString(), "o_icon o_icon_group"));
+				}
+				
+				tableEl.setExtendedFilterButton(translate("filter.groups"), groupFilters);
+			}
+		}
 	}
 	
-	private void updateModel(String searchKey) {
+	private void updateModel(String searchString, List<FlexiTableFilter> filters, List<FlexiTableFilter> extendedFilters) {
 		SearchAssessedIdentityParams params = new SearchAssessedIdentityParams(courseEntry, referenceEntry, courseNode.getIdent(), assessmentCallback);
-		params.setSearchString(searchKey);
+		
+		List<AssessmentEntryStatus> assessmentStatus = null;
+		if(filters != null && filters.size() > 0) {
+			assessmentStatus = new ArrayList<>(filters.size());
+			for(FlexiTableFilter filter:filters) {
+				if("passed".equals(filter.getFilter())) {
+					params.setPassed(true);
+				} else if("failed".equals(filter.getFilter())) {
+					params.setFailed(true);
+				} else if(AssessmentEntryStatus.isValueOf(filter.getFilter())){
+					assessmentStatus.add(AssessmentEntryStatus.valueOf(filter.getFilter()));
+				}
+			}
+		}
+		params.setAssessmentStatus(assessmentStatus);
+		
+		List<Long> businessGroupKeys = null;
+		if(extendedFilters != null && extendedFilters.size() > 0) {
+			businessGroupKeys = new ArrayList<>(extendedFilters.size());
+			for(FlexiTableFilter extendedFilter:extendedFilters) {
+				if(StringHelper.isLong(extendedFilter.getFilter())) {
+					businessGroupKeys.add(Long.parseLong(extendedFilter.getFilter()));
+				}
+			}
+		}
+		params.setBusinessGroupKeys(businessGroupKeys);
+		params.setSearchString(searchString);
+		
 		List<Identity> assessedIdentities = assessmentToolManager.getAssessedIdentities(getIdentity(), params);
 		List<AssessmentEntry> assessmentEntries = assessmentToolManager.getAssessmentEntries(getIdentity(), params, null);
 		Map<Long,AssessmentEntry> entryMap = new HashMap<>();
@@ -215,8 +275,7 @@ public class AssessmentIdentitiesCourseNodeController extends FormBasicControlle
 				}
 			} else if(event instanceof FlexiTableSearchEvent) {
 				FlexiTableSearchEvent ftse = (FlexiTableSearchEvent)event;
-				String searchKey = ftse.getSearch();
-				updateModel(searchKey);
+				updateModel(ftse.getSearch(), ftse.getFilters(), ftse.getExtendedFilters());
 			}
 		}
 		
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java
index 39712ccaf26..0d56bd00e26 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java
+++ b/src/main/java/org/olat/course/assessment/ui/tool/AssessmentIdentitiesCourseTreeController.java
@@ -42,7 +42,10 @@ import org.olat.core.util.resource.OresHelper;
 import org.olat.course.CourseFactory;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentHelper;
+import org.olat.course.nodes.AssessableCourseNode;
 import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
 import org.olat.repository.RepositoryEntry;
 
@@ -79,8 +82,6 @@ public class AssessmentIdentitiesCourseTreeController extends BasicController im
 		menuTree.addListener(this);
 		
 		mainPanel = new Panel("empty");
-		
-		
 		LayoutMain3ColsController columLayoutCtr = new LayoutMain3ColsController(ureq, getWindowControl(), menuTree, mainPanel, "course" + course.getResourceableId());
 		listenTo(columLayoutCtr); // cleanup on dispose
 		putInitialPanel(columLayoutCtr.getInitialComponent());
@@ -122,6 +123,12 @@ public class AssessmentIdentitiesCourseTreeController extends BasicController im
 		ICourse course = CourseFactory.loadCourse(courseEntry);
 		if(course.getRunStructure().getRootNode().equals(courseNode)) {
 			currentCtrl = new AssessmentIdentitiesCourseController(ureq, bwControl, stackPanel, courseEntry, assessmentCallback);
+		} else if(courseNode instanceof AssessableCourseNode && ((AssessableCourseNode)courseNode).isAssessedBusinessGroups()) {
+			if(courseNode instanceof GTACourseNode) {
+				CourseEnvironment courseEnv = CourseFactory.loadCourse(courseEntry).getCourseEnvironment();
+				currentCtrl = ((GTACourseNode)courseNode).getCoachedGroupListController(ureq, getWindowControl(), stackPanel,
+						courseEnv, assessmentCallback.isAdmin(), assessmentCallback.getCoachedGroups());
+			}
 		} else {
 			currentCtrl = new AssessmentIdentitiesCourseNodeController(ureq, bwControl, stackPanel, courseEntry, courseNode, assessmentCallback);
 		}
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties
index cf4ee081929..c6061631de5 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/assessment/ui/tool/_i18n/LocalStrings_de.properties
@@ -24,3 +24,10 @@ waiting.review=Pending reviews
 no.certificate=Kein Zertifikat vorhanden
 elements.to.review=<i class="o_icon o_icon_warning"> </i> {0} pending
 sub.details=Details
+filter=Filter
+filter.passed=Bestanden
+filter.failed=Nicht bestanden
+filter.inProgress=Gestartet
+filter.inReview=Korrigieren
+filter.done=Bewertet
+filter.groups=Gruppen
diff --git a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java
index 3bffecf748c..8e4fec8cdf0 100644
--- a/src/main/java/org/olat/course/nodes/AssessableCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/AssessableCourseNode.java
@@ -49,6 +49,12 @@ import org.olat.course.run.userview.UserCourseEnvironment;
  * tool.
  */
 public interface AssessableCourseNode extends CourseNode {
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public boolean isAssessedBusinessGroups();
     
 	/**
 	 * @return Returns the maximal score that can be achieved on this node. Throws 
diff --git a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
index 59a3a15d9e1..7a7d4424385 100644
--- a/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
+++ b/src/main/java/org/olat/course/nodes/BasicLTICourseNode.java
@@ -224,6 +224,11 @@ public class BasicLTICourseNode extends AbstractAccessableCourseNode implements
 		}
 	}
 
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
+
 	@Override
 	public Float getMaxScoreConfiguration() {
 		if (!hasScoreConfigured()) {
diff --git a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java
index 8cc7db0752b..70f7c65ae6a 100644
--- a/src/main/java/org/olat/course/nodes/CheckListCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/CheckListCourseNode.java
@@ -242,6 +242,11 @@ public class CheckListCourseNode extends AbstractAccessableCourseNode implements
 	public boolean needsReferenceToARepositoryEntry() {
 		return false;
 	}
+	
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
diff --git a/src/main/java/org/olat/course/nodes/GTACourseNode.java b/src/main/java/org/olat/course/nodes/GTACourseNode.java
index 571fc4fda3c..059c217f69c 100644
--- a/src/main/java/org/olat/course/nodes/GTACourseNode.java
+++ b/src/main/java/org/olat/course/nodes/GTACourseNode.java
@@ -67,6 +67,7 @@ import org.olat.course.editor.NodeEditController;
 import org.olat.course.editor.PublishEvents;
 import org.olat.course.editor.StatusDescription;
 import org.olat.course.export.CourseEnvironmentMapper;
+import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.course.nodes.gta.GTAManager;
 import org.olat.course.nodes.gta.GTAType;
 import org.olat.course.nodes.gta.Task;
@@ -76,6 +77,7 @@ import org.olat.course.nodes.gta.model.TaskDefinition;
 import org.olat.course.nodes.gta.model.TaskDefinitionList;
 import org.olat.course.nodes.gta.ui.BulkDownloadToolController;
 import org.olat.course.nodes.gta.ui.GTAAssessmentDetailsController;
+import org.olat.course.nodes.gta.ui.GTACoachedGroupListController;
 import org.olat.course.nodes.gta.ui.GTAEditController;
 import org.olat.course.nodes.gta.ui.GTAGroupAssessmentToolController;
 import org.olat.course.nodes.gta.ui.GTARunController;
@@ -604,7 +606,12 @@ public class GTACourseNode extends AbstractAccessableCourseNode implements Persi
 		RepositoryEntry entry = course.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
 		gtaManager.deleteTaskList(entry, this);
 	}
-	
+
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return GTAType.group.name().equals(getModuleConfiguration().getStringValue(GTACourseNode.GTASK_TYPE));
+	}
+
 	@Override
 	public boolean hasStatusConfigured() {
 		return true; // Task Course node has always a status-field
@@ -768,6 +775,20 @@ public class GTACourseNode extends AbstractAccessableCourseNode implements Persi
 			BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
 		return new GTAAssessmentDetailsController(ureq, wControl, userCourseEnvironment, this);
 	}
+	
+	public GTACoachedGroupListController getCoachedGroupListController(UserRequest ureq, WindowControl wControl,
+			BreadcrumbPanel stackPanel, CourseEnvironment courseEnv, boolean admin, List<BusinessGroup> coachedGroups) {
+		
+		List<BusinessGroup> groups;
+		CourseGroupManager gm = courseEnv.getCourseGroupManager();
+		if(admin) {
+			groups = gm.getAllBusinessGroups();
+		} else {
+			groups = coachedGroups;
+		}
+		groups = CoreSpringFactory.getImpl(GTAManager.class).filterBusinessGroups(groups, this);
+		return new GTACoachedGroupListController(ureq, wControl, stackPanel, courseEnv, this, groups);
+	}
 
 	@Override
 	public List<Controller> createAssessmentTools(UserRequest ureq, WindowControl wControl,
diff --git a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
index 0eee3516220..f4bd2e2a72d 100644
--- a/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/IQTESTCourseNode.java
@@ -345,6 +345,11 @@ public class IQTESTCourseNode extends AbstractAccessableCourseNode implements Pe
 		}
 		return null;
 	}
+	
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java
index 4ab0f551b5a..359f3d74044 100644
--- a/src/main/java/org/olat/course/nodes/MSCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java
@@ -282,6 +282,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasScoreConfigured()
 	 */
+	@Override
 	public boolean hasScoreConfigured() {
 		ModuleConfiguration config = getModuleConfiguration();
 		Boolean score = (Boolean) config.get(CONFIG_KEY_HAS_SCORE_FIELD);
@@ -292,13 +293,20 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasStatusConfigured()
 	 */
+	@Override
 	public boolean hasStatusConfigured() {
 		return false;
 	}
+	
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMaxScoreConfiguration()
 	 */
+	@Override
 	public Float getMaxScoreConfiguration() {
 		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMaxScore not defined when hasScore set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -309,6 +317,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMinScoreConfiguration()
 	 */
+	@Override
 	public Float getMinScoreConfiguration() {
 		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMinScore not defined when hasScore set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -319,6 +328,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
 	 */
+	@Override
 	public Float getCutValueConfiguration() {
 		if (!hasPassedConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getCutValue not defined when hasPassed set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -329,6 +339,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserCoachComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		String coachCommentValue = am.getNodeCoachComment(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -338,6 +349,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserUserComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserUserComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		String userCommentValue = am.getNodeComment(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -347,6 +359,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserLog(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserLog(UserCourseEnvironment userCourseEnvironment) {
 		UserNodeAuditManager am = userCourseEnvironment.getCourseEnvironment().getAuditManager();
 		String logValue = am.getUserNodeLog(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -356,6 +369,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#isEditableConfigured()
 	 */
+	@Override
 	public boolean isEditableConfigured() {
 		// manual scoring fields can be edited manually
 		return true;
@@ -365,6 +379,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserCoachComment(java.lang.String,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -378,6 +393,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment,
 			Identity coachingIdentity, boolean incrementAttempts) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -390,6 +406,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -401,6 +418,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Integer getUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		throw new OLATRuntimeException(MSCourseNode.class, "No attempts available in MS nodes", null);
 
@@ -409,6 +427,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasAttemptsConfigured()
 	 */
+	@Override
 	public boolean hasAttemptsConfigured() {
 		return false;
 	}
@@ -418,6 +437,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		throw new OLATRuntimeException(MSCourseNode.class, "Attempts variable can't be updated in MS nodes", null);
 	}
@@ -425,6 +445,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#incrementUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void incrementUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		throw new OLATRuntimeException(MSCourseNode.class, "Attempts variable can't be updated in MS nodes", null);
 	}
@@ -434,6 +455,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 *      org.olat.core.gui.control.WindowControl,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
 		throw new OLATRuntimeException(MSCourseNode.class, "Details controler not available in MS nodes", null);
 	}
@@ -454,6 +476,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListViewHeaderKey()
 	 */
+	@Override
 	public String getDetailsListViewHeaderKey() {
 		throw new OLATRuntimeException(MSCourseNode.class, "Details not available in MS nodes", null);
 	}
@@ -461,6 +484,7 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasDetails()
 	 */
+	@Override
 	public boolean hasDetails() {
 		return false;
 	}
diff --git a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
index 6cab1716ef0..35881e699a1 100644
--- a/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/PortfolioCourseNode.java
@@ -244,6 +244,11 @@ public class PortfolioCourseNode extends AbstractAccessableCourseNode implements
 		nodeEval.putAccessStatus(EDIT_CONDITION_ID, editor);
 	}
 
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
+
 	@Override
 	public Float getMaxScoreConfiguration() {
 		if (!hasScoreConfigured()) { 
diff --git a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
index bbc4870c1b5..fd4987f38bd 100644
--- a/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ProjectBrokerCourseNode.java
@@ -482,10 +482,16 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 		Identity mySelf = userCourseEnv.getIdentityEnvironment().getIdentity();
 		return am.getAssessmentEntry(this, mySelf, null);
 	}
+	
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasCommentConfigured()
 	 */
+	@Override
 	public boolean hasCommentConfigured() {
 		return false;
 	}
@@ -493,6 +499,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasPassedConfigured()
 	 */
+	@Override
 	public boolean hasPassedConfigured() {
 		return false;
 	}
@@ -500,6 +507,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasScoreConfigured()
 	 */
+	@Override
 	public boolean hasScoreConfigured() {
 		return false;
 	}
@@ -507,6 +515,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasStatusConfigured()
 	 */
+	@Override
 	public boolean hasStatusConfigured() {
 		return false; // Project broker Course node has no status-field
 	}
@@ -514,6 +523,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMaxScoreConfiguration()
 	 */
+	@Override
 	public Float getMaxScoreConfiguration() {
 		if (!hasScoreConfigured()) { throw new OLATRuntimeException(ProjectBrokerCourseNode.class, "getMaxScore not defined when hasScore set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -524,6 +534,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMinScoreConfiguration()
 	 */
+	@Override
 	public Float getMinScoreConfiguration() {
 		if (!hasScoreConfigured()) { throw new OLATRuntimeException(ProjectBrokerCourseNode.class, "getMinScore not defined when hasScore set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -534,6 +545,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
 	 */
+	@Override
 	public Float getCutValueConfiguration() {
 		if (!hasPassedConfigured()) { throw new OLATRuntimeException(ProjectBrokerCourseNode.class, "getCutValue not defined when hasPassed set to false", null); }
 		ModuleConfiguration config = getModuleConfiguration();
@@ -544,6 +556,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserCoachComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		String coachCommentValue = am.getNodeCoachComment(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -553,6 +566,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserUserComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserUserComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		String userCommentValue = am.getNodeComment(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -562,6 +576,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserLog(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserLog(UserCourseEnvironment userCourseEnvironment) {
 		UserNodeAuditManager am = userCourseEnvironment.getCourseEnvironment().getAuditManager();
 		String logValue = am.getUserNodeLog(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
@@ -571,6 +586,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#isEditableConfigured()
 	 */
+	@Override
 	public boolean isEditableConfigured() {
 		// always true when assessable
 		return false;
@@ -580,6 +596,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserCoachComment(java.lang.String,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -593,6 +610,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment,
 			Identity coachingIdentity, boolean incrementAttempts) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -605,6 +623,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -616,6 +635,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Integer getUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -627,6 +647,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasAttemptsConfigured()
 	 */
+	@Override
 	public boolean hasAttemptsConfigured() {
 		return false;
 	}
@@ -636,6 +657,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		if (userAttempts != null) {
 			AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -647,6 +669,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#incrementUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void incrementUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -658,6 +681,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	 *      org.olat.core.gui.control.WindowControl,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
 		// prepare file component
 		throw new AssertException("ProjectBroker does not support AssessmentTool");
@@ -675,6 +699,7 @@ public class ProjectBrokerCourseNode extends GenericCourseNode implements Persis
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) {
 		Identity identity = userCourseEnvironment.getIdentityEnvironment().getIdentity();
 		CoursePropertyManager propMgr = userCourseEnvironment.getCourseEnvironment().getCoursePropertyManager();
diff --git a/src/main/java/org/olat/course/nodes/STCourseNode.java b/src/main/java/org/olat/course/nodes/STCourseNode.java
index 447db53637e..a38d1b30bee 100644
--- a/src/main/java/org/olat/course/nodes/STCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/STCourseNode.java
@@ -391,9 +391,15 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess
 		passedExpression.setConditionId("passed");
 	}
 
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
+
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
 	 */
+	@Override
 	public Float getCutValueConfiguration() {
 		throw new OLATRuntimeException(STCourseNode.class, "Cut value never defined for ST nodes", null);
 	}
@@ -401,6 +407,7 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMaxScoreConfiguration()
 	 */
+	@Override
 	public Float getMaxScoreConfiguration() {
 		throw new OLATRuntimeException(STCourseNode.class, "Max score never defined for ST nodes", null);
 	}
@@ -408,6 +415,7 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMinScoreConfiguration()
 	 */
+	@Override
 	public Float getMinScoreConfiguration() {
 		throw new OLATRuntimeException(STCourseNode.class, "Min score never defined for ST nodes", null);
 	}
@@ -415,6 +423,7 @@ public class STCourseNode extends AbstractAccessableCourseNode implements Assess
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserCoachComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) {
 		throw new OLATRuntimeException(STCourseNode.class, "No coach comments available in ST nodes", null);
 	}
diff --git a/src/main/java/org/olat/course/nodes/ScormCourseNode.java b/src/main/java/org/olat/course/nodes/ScormCourseNode.java
index 2763cc6133a..5a3061a9887 100644
--- a/src/main/java/org/olat/course/nodes/ScormCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/ScormCourseNode.java
@@ -396,9 +396,15 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 		return null;
 	}
 
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
+
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
 	 */
+	@Override
 	public Float getCutValueConfiguration() {
 		ModuleConfiguration config = this.getModuleConfiguration();
 		int cutValue = config.getIntegerSafe(ScormEditController.CONFIG_CUTVALUE, 0); 
@@ -408,6 +414,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMaxScoreConfiguration()
 	 */
+	@Override
 	public Float getMaxScoreConfiguration() {
 		// According to SCORM Standard, SCORE is between 0 and 100.
 		return new Float(100);
@@ -416,6 +423,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getMinScoreConfiguration()
 	 */
+	@Override
 	public Float getMinScoreConfiguration() {
 		// According to SCORM Standard, SCORE is between 0 and 100.
 		return new Float(0);
@@ -424,6 +432,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasCommentConfigured()
 	 */
+	@Override
 	public boolean hasCommentConfigured() {
 		return false;
 	}
@@ -431,6 +440,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasPassedConfigured()
 	 */
+	@Override
 	public boolean hasPassedConfigured() {
 		return getModuleConfiguration().getBooleanSafe(ScormEditController.CONFIG_ISASSESSABLE, true);
 	}
@@ -438,6 +448,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasScoreConfigured()
 	 */
+	@Override
 	public boolean hasScoreConfigured() {
 		boolean assessable = getModuleConfiguration().getBooleanSafe(ScormEditController.CONFIG_ISASSESSABLE, true);
 		if(assessable) {
@@ -451,6 +462,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasStatusConfigured()
 	 */
+	@Override
 	public boolean hasStatusConfigured() {
 		return false;
 	}
@@ -458,6 +470,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#isEditableConfigured()
 	 */
+	@Override
 	public boolean isEditableConfigured() {
 		return getModuleConfiguration().getBooleanSafe(ScormEditController.CONFIG_ISASSESSABLE, true);
 	}
@@ -466,6 +479,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserCoachComment(java.lang.String,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		if (coachComment != null) {
@@ -478,6 +492,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment,
 			Identity coachingIdentity, boolean incrementAttempts) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -490,6 +505,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		if (userComment != null) {
 			AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -501,6 +517,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserCoachComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -511,6 +528,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserUserComment(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserUserComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -521,6 +539,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserLog(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getUserLog(UserCourseEnvironment userCourseEnvironment) {
 		UserNodeAuditManager am = userCourseEnvironment.getCourseEnvironment().getAuditManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -531,6 +550,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Integer getUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -542,6 +562,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasAttemptsConfigured()
 	 */
+	@Override
 	public boolean hasAttemptsConfigured() {
 		return getModuleConfiguration().getBooleanSafe(ScormEditController.CONFIG_ISASSESSABLE, true);
 	}
@@ -551,6 +572,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	 *      org.olat.course.run.userview.UserCourseEnvironment,
 	 *      org.olat.core.id.Identity)
 	 */
+	@Override
 	public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		if (userAttempts != null) {
 			AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -562,6 +584,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#incrementUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public void incrementUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
 		Identity mySelf = userCourseEnvironment.getIdentityEnvironment().getIdentity();
@@ -573,6 +596,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	 *      org.olat.core.gui.control.WindowControl,
 	 *      org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, UserCourseEnvironment userCourseEnvironment) {
 		return new ScormResultDetailsController(ureq, wControl, this, userCourseEnvironment);
 	}
@@ -580,6 +604,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListView(org.olat.course.run.userview.UserCourseEnvironment)
 	 */
+	@Override
 	public String getDetailsListView(UserCourseEnvironment userCourseEnvironment) {
 		return null;
 	}
@@ -587,6 +612,7 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListViewHeaderKey()
 	 */
+	@Override
 	public String getDetailsListViewHeaderKey() {
 		return null;
 	}
@@ -594,26 +620,11 @@ public class ScormCourseNode extends AbstractAccessableCourseNode implements Per
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasDetails()
 	 */
+	@Override
 	public boolean hasDetails() {
 		return getModuleConfiguration().getBooleanSafe(ScormEditController.CONFIG_ISASSESSABLE, true);
 	}
 
-	////////////////////////////// fix it
-	
-	/**
-	 * @see org.olat.course.nodes.CourseNode#informOnDelete(org.olat.core.gui.UserRequest,
-	 *      org.olat.course.ICourse)
-	 */
-	public String informOnDelete(Locale locale, ICourse course) {
-		// checking for data is too complex - we would have to work through all users
-		// of the system since data is stored under users name instead of the repo entry
-		// with many users on the system it could take quite some time and the user
-		// is waiting in a workflow
-		// FIXME gs
-		// see comment on cleanupOnDelete
-		return null;
-	}
-
 	/**
 	 * @see org.olat.course.nodes.CourseNode#cleanupOnDelete(org.olat.course.ICourse)
 	 */
diff --git a/src/main/java/org/olat/course/nodes/TACourseNode.java b/src/main/java/org/olat/course/nodes/TACourseNode.java
index eecd2d623b6..ad5a6e5f1db 100644
--- a/src/main/java/org/olat/course/nodes/TACourseNode.java
+++ b/src/main/java/org/olat/course/nodes/TACourseNode.java
@@ -552,6 +552,12 @@ public class TACourseNode extends GenericCourseNode implements PersistentAssessa
 		}
 		return false;
 	}
+	
+
+	@Override
+	public boolean isAssessedBusinessGroups() {
+		return false;
+	}
 
 	/**
 	 * @see org.olat.course.nodes.AssessableCourseNode#hasStatusConfigured()
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTAAssessmentDetailsController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTAAssessmentDetailsController.java
index d609ff76cf3..572e0299d1f 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/GTAAssessmentDetailsController.java
+++ b/src/main/java/org/olat/course/nodes/gta/ui/GTAAssessmentDetailsController.java
@@ -114,7 +114,7 @@ public class GTAAssessmentDetailsController extends BasicController {
 			} else if(participatingGroups.size() == 1) {
 				doSelectBusinessGroup(ureq, participatingGroups.get(0));
 			} else {
-				groupListCtrl = new GTACoachedGroupListController(ureq, getWindowControl(), courseEnv, gtaNode, participatingGroups);
+				groupListCtrl = new GTACoachedGroupListController(ureq, getWindowControl(), null, courseEnv, gtaNode, participatingGroups);
 				listenTo(groupListCtrl);
 				mainVC.put("list", groupListCtrl.getInitialComponent());
 			}	
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachSelectionController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachSelectionController.java
index ee787002bfa..4e1213d45d7 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachSelectionController.java
+++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachSelectionController.java
@@ -107,7 +107,7 @@ public class GTACoachSelectionController extends BasicController {
 			if(groups.size() == 1) {
 				doSelectBusinessGroup(ureq, groups.get(0));
 			} else {
-				groupListCtrl = new GTACoachedGroupListController(ureq, getWindowControl(), courseEnv, gtaNode, groups);
+				groupListCtrl = new GTACoachedGroupListController(ureq, getWindowControl(), null, courseEnv, gtaNode, groups);
 				listenTo(groupListCtrl);
 				mainVC.put("list", groupListCtrl.getInitialComponent());
 			}	
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java
index 0cb2d3be87e..3d59c5da6e7 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java
+++ b/src/main/java/org/olat/course/nodes/gta/ui/GTACoachedGroupListController.java
@@ -34,6 +34,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFle
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent;
+import org.olat.core.gui.components.stack.BreadcrumbPanel;
 import org.olat.core.gui.control.Controller;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.course.nodes.GTACourseNode;
@@ -55,6 +56,9 @@ public class GTACoachedGroupListController extends FormBasicController {
 	
 	private FlexiTableElement tableEl;
 	private CoachGroupsTableModel tableModel;
+	private final BreadcrumbPanel stackPanel;
+	
+	private GTACoachController coachingCtrl;
 	
 	private final GTACourseNode gtaNode;
 	private final CourseEnvironment courseEnv;
@@ -63,12 +67,13 @@ public class GTACoachedGroupListController extends FormBasicController {
 	@Autowired
 	private GTAManager gtaManager;
 	
-	public GTACoachedGroupListController(UserRequest ureq, WindowControl wControl,
+	public GTACoachedGroupListController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
 			CourseEnvironment courseEnv, GTACourseNode gtaNode, List<BusinessGroup> coachedGroups) {
 		super(ureq, wControl, LAYOUT_BAREBONE);
 		this.gtaNode = gtaNode;
 		this.courseEnv = courseEnv;
 		this.coachedGroups = coachedGroups;
+		this.stackPanel = stackPanel;
 		initForm(ureq);
 		updateModel();
 	}
@@ -125,12 +130,24 @@ public class GTACoachedGroupListController extends FormBasicController {
 				String cmd = se.getCommand();
 				CoachedGroupRow row = tableModel.getObject(se.getIndex());
 				if("details".equals(cmd) || "select".equals(cmd)) {
-					fireEvent(ureq, new SelectBusinessGroupEvent(row.getBusinessGroup()));	
+					doSelect(ureq, row.getBusinessGroup());
 				}
 			}
 		}
 		super.formInnerEvent(ureq, source, event);
 	}
+	
+	private void doSelect(UserRequest ureq, BusinessGroup businessGroup) {
+		if(stackPanel == null) {
+			fireEvent(ureq, new SelectBusinessGroupEvent(businessGroup));	
+		} else {
+			removeAsListenerAndDispose(coachingCtrl);
+			
+			coachingCtrl = new GTACoachController(ureq, getWindowControl(), courseEnv, gtaNode, businessGroup, true, true, true);
+			listenTo(coachingCtrl);
+			stackPanel.pushController(businessGroup.getName(), coachingCtrl);
+		}
+	}
 
 	@Override
 	protected void formOK(UserRequest ureq) {
diff --git a/src/main/java/org/olat/course/run/CourseRuntimeController.java b/src/main/java/org/olat/course/run/CourseRuntimeController.java
index b504857d94c..524169f1889 100644
--- a/src/main/java/org/olat/course/run/CourseRuntimeController.java
+++ b/src/main/java/org/olat/course/run/CourseRuntimeController.java
@@ -1352,9 +1352,12 @@ public class CourseRuntimeController extends RepositoryEntryRuntimeController im
 			boolean nonMembers = reSecurity.isEntryAdmin();
 			boolean repositoryEntryMembers = reSecurity.isCourseCoach();
 			boolean businessGoupMembers = reSecurity.isGroupCoach();
-			
+			List<BusinessGroup> coachedGroups = null;
+			if(businessGoupMembers) {
+				coachedGroups = getUserCourseEnvironment().getCoachedGroups();
+			}
 			AssessmentToolSecurityCallback secCallBack
-				= new AssessmentToolSecurityCallback(admin, nonMembers, repositoryEntryMembers, businessGoupMembers);
+				= new AssessmentToolSecurityCallback(admin, nonMembers, repositoryEntryMembers, businessGoupMembers, coachedGroups);
 
 			removeCustomCSS();
 			AssessmentToolController ctrl = new AssessmentToolController(ureq, swControl, toolbarPanel, getRepositoryEntry(), secCallBack);
diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java b/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java
index 6574d7ed59a..1fc86a91545 100644
--- a/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/QTI21RuntimeController.java
@@ -125,7 +125,8 @@ public class QTI21RuntimeController extends RepositoryEntryRuntimeController  {
 		
 		if (reSecurity.isEntryAdmin() || reSecurity.isCourseCoach() || reSecurity.isGroupCoach()) {
 			AssessmentToolSecurityCallback secCallback
-				= new AssessmentToolSecurityCallback(reSecurity.isEntryAdmin(), reSecurity.isEntryAdmin(), reSecurity.isCourseCoach(), reSecurity.isGroupCoach());
+				= new AssessmentToolSecurityCallback(reSecurity.isEntryAdmin(), reSecurity.isEntryAdmin(),
+						reSecurity.isCourseCoach(), reSecurity.isGroupCoach(), null);
 			
 			
 			AssessmentOverviewController ctrl = new AssessmentOverviewController(ureq, swControl, toolbarPanel,
diff --git a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryStatus.java b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryStatus.java
index 69fd90bc10b..31ab39949fa 100644
--- a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryStatus.java
+++ b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryStatus.java
@@ -30,6 +30,15 @@ public enum AssessmentEntryStatus {
 	notStarted,
 	inProgress,//student
 	inReview,//coach
-	done
-
+	done;
+	
+	public static final boolean isValueOf(String val) {
+		if(val == null) return false;
+		for(AssessmentEntryStatus value:values()) {
+			if(val.equals(value.name())) {
+				return true;
+			}
+		}
+		return false;
+	}
 }
diff --git a/src/main/java/org/olat/modules/assessment/ui/AssessmentToolSecurityCallback.java b/src/main/java/org/olat/modules/assessment/ui/AssessmentToolSecurityCallback.java
index 8b219eb5274..35892a8910d 100644
--- a/src/main/java/org/olat/modules/assessment/ui/AssessmentToolSecurityCallback.java
+++ b/src/main/java/org/olat/modules/assessment/ui/AssessmentToolSecurityCallback.java
@@ -19,6 +19,10 @@
  */
 package org.olat.modules.assessment.ui;
 
+import java.util.List;
+
+import org.olat.group.BusinessGroup;
+
 /**
  * 
  * Initial date: 07.10.2015<br>
@@ -32,13 +36,16 @@ public class AssessmentToolSecurityCallback {
 	private final boolean repositoryEntryMembers;
 	private final boolean businessGoupMembers;
 	
+	private final List<BusinessGroup> coachedGroups;
 	
 	public AssessmentToolSecurityCallback(boolean admin, boolean nonMembers,
-			boolean repositoryEntryMembers, boolean businessGoupMembers) {
+			boolean repositoryEntryMembers, boolean businessGoupMembers,
+			List<BusinessGroup> coachedGroups) {
 		this.admin = admin;
 		this.nonMembers = nonMembers;
 		this.repositoryEntryMembers = repositoryEntryMembers;
 		this.businessGoupMembers = businessGoupMembers;
+		this.coachedGroups = coachedGroups;
 	}
 
 
@@ -57,4 +64,8 @@ public class AssessmentToolSecurityCallback {
 	public boolean canAssessBusinessGoupMembers() {
 		return businessGoupMembers;
 	}
+
+	public List<BusinessGroup> getCoachedGroups() {
+		return coachedGroups;
+	}
 }
diff --git a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
index 484b7b5056b..c249edf6ca9 100644
--- a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
@@ -36,6 +36,7 @@ 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.FlexiTableSortOptions;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -388,7 +389,7 @@ public abstract class AbstractItemListController extends FormBasicController
 	}
 
 	@Override
-	public ResultInfos<ItemRow> getRows(String query, List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
+	public ResultInfos<ItemRow> getRows(String query, List<FlexiTableFilter> filters, List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
 		ResultInfos<QuestionItemView> items = itemsSource.getItems(query, condQueries, firstResult, maxResults, orderBy);
 		List<ItemRow> rows = new ArrayList<ItemRow>(items.getObjects().size());
 		for(QuestionItemView item:items.getObjects()) {
diff --git a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
index 191048b3c5d..3d6abacf059 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthoringEntryDataSource.java
@@ -30,6 +30,7 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DefaultResultInfos;
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate;
 import org.olat.core.util.StringHelper;
 import org.olat.repository.RepositoryEntryAuthorView;
@@ -92,11 +93,11 @@ public class AuthoringEntryDataSource implements FlexiTableDataSourceDelegate<Au
 	}
 
 	@Override
-	public final ResultInfos<AuthoringEntryRow> getRows(String query, List<String> condQueries,
-			int firstResult, int maxResults, SortKey... orderBy) {
+	public final ResultInfos<AuthoringEntryRow> getRows(String query, List<FlexiTableFilter> filters,
+			List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
 
-		if(condQueries != null && condQueries.size() > 0) {
-			String filter = condQueries.get(0);
+		if(filters != null && filters.size() > 0) {
+			String filter = filters.get(0).getFilter();
 			if(StringHelper.containsNonWhitespace(filter)) {
 				searchParams.setResourceTypes(Collections.singletonList(filter));
 			} else {
diff --git a/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java b/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
index 3b9c94c49b5..d2791cd6f4a 100644
--- a/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
+++ b/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
@@ -27,6 +27,7 @@ import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.persistence.DefaultResultInfos;
 import org.olat.core.commons.persistence.ResultInfos;
 import org.olat.core.commons.persistence.SortKey;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableFilter;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataSourceDelegate;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSLeaf;
@@ -102,16 +103,18 @@ public class DefaultRepositoryEntryDataSource implements FlexiTableDataSourceDel
 	}
 
 	@Override
-	public final ResultInfos<RepositoryEntryRow> getRows(String query, List<String> condQueries,
-			int firstResult, int maxResults, SortKey... orderBy) {
+	public final ResultInfos<RepositoryEntryRow> getRows(String query, List<FlexiTableFilter> filters, 
+			List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
 		
-		if(condQueries != null && condQueries.size() > 0) {
-			String filter = condQueries.get(0);
+		if(filters != null && filters.size() > 0) {
+			String filter = filters.get(0).getFilter();
 			if(StringHelper.containsNonWhitespace(filter)) {
 				searchParams.setFilters(Collections.singletonList(Filter.valueOf(filter)));
 			} else {
 				searchParams.setFilters(null);
 			}
+		} else {
+			searchParams.setFilters(null);
 		}
 		
 		if(orderBy != null && orderBy.length > 0 && orderBy[0] != null) {
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 339f24df606..270f5534bd4 100644
--- a/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml
+++ b/src/main/java/org/olat/user/propertyhandlers/_spring/userPropertiesContext.xml
@@ -819,14 +819,14 @@
 					<bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext">
 						<property name="propertyHandlers">
 							<list>
+								<ref bean="userPropertyLastName" />
 								<ref bean="userPropertyFirstName" />
-								<ref bean="userPropertyLastName" />														
 							</list>
 						</property>		
 						<property name="mandatoryProperties">
 							<set>
-								<ref bean="userPropertyFirstName" />
 								<ref bean="userPropertyLastName" />
+								<ref bean="userPropertyFirstName" />
 							</set>
 						</property>				
 					</bean>
@@ -836,8 +836,8 @@
 					<bean class="org.olat.user.propertyhandlers.UserPropertyUsageContext">
 						<property name="propertyHandlers">
 							<list>
+								<ref bean="userPropertyLastName" />
 								<ref bean="userPropertyFirstName" />
-								<ref bean="userPropertyLastName" />														
 							</list>
 						</property>		
 						<property name="mandatoryProperties">
-- 
GitLab