From 0ad54b9b718ab75d329b8a7de9a8f30aea9ae5cd Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Tue, 30 Apr 2013 09:07:55 +0200
Subject: [PATCH] OO-591: implement sort by role in the different list of
 groups, add missing i18n key in "User mamangement" and fix the role renderer
 there

---
 .../AbstractBusinessGroupListController.java  |  4 +-
 .../main/AdminBusinessGroupsController.java   | 13 +++-
 .../group/ui/main/BGRoleCellRenderer.java     |  8 +++
 .../ui/main/BusinessGroupListController.java  | 13 +++-
 .../BusinessGroupMembershipComparator.java    | 63 +++++++++++++++++++
 .../FavoritBusinessGroupListController.java   | 13 +++-
 .../main/OpenBusinessGroupListController.java | 13 +++-
 .../OwnedBusinessGroupListController.java     | 13 +++-
 .../SearchBusinessGroupListController.java    | 13 +++-
 ...SearchOpenBusinessGroupListController.java | 13 +++-
 .../ui/main/_i18n/LocalStrings_de.properties  |  1 -
 .../ui/wizard/BGUserManagementController.java |  4 +-
 .../wizard/_i18n/LocalStrings_de.properties   |  1 +
 .../wizard/_i18n/LocalStrings_en.properties   |  1 +
 14 files changed, 163 insertions(+), 10 deletions(-)
 create mode 100644 src/main/java/org/olat/group/ui/main/BusinessGroupMembershipComparator.java

diff --git a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
index 5b1c86f6572..10d6bf141f3 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
@@ -116,6 +116,8 @@ public abstract class AbstractBusinessGroupListController extends BasicControlle
 	protected static final String TABLE_ACTION_DELETE = "bgTblDelete";
 	protected static final String TABLE_ACTION_SELECT = "bgTblSelect";
 	
+	protected static final BusinessGroupMembershipComparator MEMBERSHIP_COMPARATOR = new BusinessGroupMembershipComparator();
+	
 	protected final VelocityContainer mainVC;
 
 	protected final TableController groupListCtr;
@@ -132,7 +134,7 @@ public abstract class AbstractBusinessGroupListController extends BasicControlle
 	private BusinessGroupDeleteDialogBoxController deleteDialogBox;
 	private StepsMainRunController businessGroupWizard;
 	protected CloseableModalController cmc;
-	
+
 	private final boolean admin;
 	protected final MarkManager markManager;
 	protected final BaseSecurity securityManager;
diff --git a/src/main/java/org/olat/group/ui/main/AdminBusinessGroupsController.java b/src/main/java/org/olat/group/ui/main/AdminBusinessGroupsController.java
index 1005f237a2b..d7b5585be05 100644
--- a/src/main/java/org/olat/group/ui/main/AdminBusinessGroupsController.java
+++ b/src/main/java/org/olat/group/ui/main/AdminBusinessGroupsController.java
@@ -34,6 +34,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -85,7 +86,17 @@ public class AdminBusinessGroupsController extends AbstractBusinessGroupListCont
 		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastUsage.i18n(), Cols.lastUsage.ordinal(), null, getLocale()));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(false, new BooleanColumnDescriptor(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowDelete.i18n(), Cols.allowDelete.ordinal(), TABLE_ACTION_DELETE, translate("table.header.delete"), null));
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.accessControlLaunch.i18n(), Cols.accessControlLaunch.ordinal(), TABLE_ACTION_ACCESS, getLocale()));
diff --git a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
index d42b377a0d1..acf5b04452c 100644
--- a/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
+++ b/src/main/java/org/olat/group/ui/main/BGRoleCellRenderer.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.render.StringOutput;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.Util;
 import org.olat.group.BusinessGroupMembership;
+import org.olat.group.model.BGMembership;
 
 /**
  * 
@@ -58,6 +59,13 @@ public class BGRoleCellRenderer implements CustomCellRenderer {
 				and = and(sb, and);
 				sb.append(translator.translate("search.waiting"));
 			}
+		} else if (val instanceof BGMembership) {
+			BGMembership membership = (BGMembership)val;
+			switch(membership) {
+				case owner: sb.append(translator.translate("owned.groups")); break;
+				case participant: sb.append(translator.translate("search.attendee")); break;
+				case waiting: sb.append(translator.translate("search.waiting")); break;
+			}
 		}
 	}
 	
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java
index ccb99943f58..61e0ba10ffc 100644
--- a/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupListController.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.components.table.CustomCssCellRenderer;
 import org.olat.core.gui.components.table.CustomRenderColumnDescriptor;
 import org.olat.core.gui.components.table.DefaultColumnDescriptor;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -61,7 +62,17 @@ public class BusinessGroupListController extends AbstractBusinessGroupListContro
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
 		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor(Cols.lastUsage.i18n(), Cols.lastUsage.ordinal(), null, getLocale()));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
 		return 11;
 	}
diff --git a/src/main/java/org/olat/group/ui/main/BusinessGroupMembershipComparator.java b/src/main/java/org/olat/group/ui/main/BusinessGroupMembershipComparator.java
new file mode 100644
index 00000000000..9d401a5fa06
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/main/BusinessGroupMembershipComparator.java
@@ -0,0 +1,63 @@
+/**
+ * <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.group.ui.main;
+
+import java.util.Comparator;
+
+import org.olat.group.BusinessGroupMembership;
+
+/**
+ * 
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class BusinessGroupMembershipComparator implements Comparator<BusinessGroupMembership> {
+
+	@Override
+	public int compare(BusinessGroupMembership m1, BusinessGroupMembership m2) {
+		if(m1.isOwner()) {
+			if(m2.isOwner()) {
+				return 0;
+			}
+			return 1;
+		} else if(m2.isOwner()) {
+			return -1;
+		}
+		
+		if(m1.isParticipant() || m1.isParticipant()) {
+			if(m2.isParticipant() || m2.isParticipant()) {
+				return 0;
+			}
+			return 1;
+		} else if(m2.isParticipant() || m2.isParticipant()) {
+			return -1;
+		}
+		
+		if(m1.isWaiting()) {
+			if(m2.isWaiting()) {
+				return 0;
+			}
+			return 1;
+		} else if(m2.isWaiting()) {
+			return -1;
+		}
+		return 0;
+	}
+}
diff --git a/src/main/java/org/olat/group/ui/main/FavoritBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/FavoritBusinessGroupListController.java
index cf38232a6c9..b45c7b55620 100644
--- a/src/main/java/org/olat/group/ui/main/FavoritBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/FavoritBusinessGroupListController.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.components.table.CustomCssCellRenderer;
 import org.olat.core.gui.components.table.CustomRenderColumnDescriptor;
 import org.olat.core.gui.components.table.DefaultColumnDescriptor;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -61,7 +62,17 @@ public class FavoritBusinessGroupListController extends AbstractBusinessGroupLis
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
 		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor(Cols.lastUsage.i18n(), Cols.lastUsage.ordinal(), null, getLocale()));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
 		return 11;
 	}
diff --git a/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java
index 48be5060598..ac1f2b0fd7f 100644
--- a/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/OpenBusinessGroupListController.java
@@ -31,6 +31,7 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.resource.OresHelper;
 import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 import org.olat.util.logging.activity.LoggingResourceable;
@@ -64,7 +65,17 @@ public class OpenBusinessGroupListController extends AbstractBusinessGroupListCo
 		CustomCellRenderer acRenderer = new BGAccessControlledCellRenderer();
 		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.accessTypes.i18n(), Cols.accessTypes.ordinal(), null, getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, acRenderer));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new AccessActionColumnDescriptor(Cols.accessControlLaunch.i18n(), Cols.accessControlLaunch.ordinal(), getTranslator()));
 		return 8;
 	}
diff --git a/src/main/java/org/olat/group/ui/main/OwnedBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/OwnedBusinessGroupListController.java
index 1e0f79b4105..a28288c7aab 100644
--- a/src/main/java/org/olat/group/ui/main/OwnedBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/OwnedBusinessGroupListController.java
@@ -27,6 +27,7 @@ import org.olat.core.gui.components.table.CustomCssCellRenderer;
 import org.olat.core.gui.components.table.CustomRenderColumnDescriptor;
 import org.olat.core.gui.components.table.DefaultColumnDescriptor;
 import org.olat.core.gui.control.WindowControl;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -73,7 +74,17 @@ public class OwnedBusinessGroupListController extends AbstractBusinessGroupListC
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
 		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor(Cols.lastUsage.i18n(), Cols.lastUsage.ordinal(), null, getLocale()));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowDelete.i18n(), Cols.allowDelete.ordinal(), TABLE_ACTION_DELETE, translate("table.header.delete"), null));
 		return 12;
diff --git a/src/main/java/org/olat/group/ui/main/SearchBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/SearchBusinessGroupListController.java
index 0e926263faa..3ff29215784 100644
--- a/src/main/java/org/olat/group/ui/main/SearchBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/SearchBusinessGroupListController.java
@@ -33,6 +33,7 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -88,7 +89,17 @@ public class SearchBusinessGroupListController extends AbstractBusinessGroupList
 		groupListCtr.addColumnDescriptor(new DefaultColumnDescriptor(Cols.lastTime.i18n(), Cols.lastTime.ordinal(), null, getLocale()));
 		groupListCtr.addColumnDescriptor(false, new DefaultColumnDescriptor(Cols.lastUsage.i18n(), Cols.lastUsage.ordinal(), null, getLocale()));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new BooleanColumnDescriptor(Cols.allowLeave.i18n(), Cols.allowLeave.ordinal(), TABLE_ACTION_LEAVE, translate("table.header.leave"), null));
 		return 11;
 	}
diff --git a/src/main/java/org/olat/group/ui/main/SearchOpenBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/SearchOpenBusinessGroupListController.java
index 3638956cc58..d14a8074af0 100644
--- a/src/main/java/org/olat/group/ui/main/SearchOpenBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/SearchOpenBusinessGroupListController.java
@@ -34,6 +34,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.id.context.StateEntry;
 import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupMembership;
 import org.olat.group.model.SearchBusinessGroupParams;
 import org.olat.group.ui.main.BusinessGroupTableModelWithType.Cols;
 
@@ -71,7 +72,17 @@ public class SearchOpenBusinessGroupListController extends AbstractBusinessGroup
 		CustomCellRenderer acRenderer = new BGAccessControlledCellRenderer();
 		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.accessTypes.i18n(), Cols.accessTypes.ordinal(), null, getLocale(), ColumnDescriptor.ALIGNMENT_LEFT, acRenderer));
 		CustomCellRenderer roleRenderer = new BGRoleCellRenderer(getLocale());
-		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer));
+		groupListCtr.addColumnDescriptor(new CustomRenderColumnDescriptor(Cols.role.i18n(), Cols.role.ordinal(), null, getLocale(),  ColumnDescriptor.ALIGNMENT_LEFT, roleRenderer){
+			@Override
+			public int compareTo(final int rowa, final int rowb) {
+				Object a = table.getTableDataModel().getValueAt(rowa,dataColumn);
+				Object b = table.getTableDataModel().getValueAt(rowb,dataColumn);
+				if(a instanceof BusinessGroupMembership && b instanceof BusinessGroupMembership) {
+					return MEMBERSHIP_COMPARATOR.compare((BusinessGroupMembership)a, (BusinessGroupMembership)b);
+				}
+				return super.compareTo(rowa, rowb);
+			}
+		});
 		groupListCtr.addColumnDescriptor(new AccessActionColumnDescriptor(Cols.accessControlLaunch.i18n(), Cols.accessControlLaunch.ordinal(), getTranslator()));
 		return 8;
 	}
diff --git a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
index e376c097f5b..c6ce0385810 100644
--- a/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/group/ui/main/_i18n/LocalStrings_de.properties
@@ -29,7 +29,6 @@ index.intro=In der untenstehenden Liste finden Sie alle Gruppen, an denen Sie te
 index.table.nogroup=Sie sind in keiner Gruppe eingetragen.
 info.group.deleted=Die Gruppe wurde gel\u00F6scht.
 
-
 menu.group.admin=Gruppenverwaltung
 menu.group.admin.alt=Gruppenverwaltung
 menu.index=Gruppen
diff --git a/src/main/java/org/olat/group/ui/wizard/BGUserManagementController.java b/src/main/java/org/olat/group/ui/wizard/BGUserManagementController.java
index d1279c91a93..2477f2038fa 100644
--- a/src/main/java/org/olat/group/ui/wizard/BGUserManagementController.java
+++ b/src/main/java/org/olat/group/ui/wizard/BGUserManagementController.java
@@ -53,6 +53,7 @@ import org.olat.group.BusinessGroup;
 import org.olat.group.model.BGMembership;
 import org.olat.group.model.MembershipModification;
 import org.olat.group.ui.main.BGRoleCellRenderer;
+import org.olat.group.ui.main.BusinessGroupMembershipComparator;
 import org.olat.user.UserManager;
 import org.olat.user.propertyhandlers.UserPropertyHandler;
 
@@ -67,6 +68,7 @@ public class BGUserManagementController extends BasicController {
 	protected static final String COMMAND_REMOVEUSER = "removesubjectofgroup";
 	protected static final String COMMAND_VCARD = "show.vcard";
 	protected static final String COMMAND_SELECTUSER = "select.user";
+	protected static final BusinessGroupMembershipComparator MEMBERSHIP_COMPARATOR = new BusinessGroupMembershipComparator();
 	
 	private VelocityContainer mainVC;
 	private Link addOwner, addParticipant, addToWaitingList;
@@ -94,7 +96,7 @@ public class BGUserManagementController extends BasicController {
 
 		Translator userTrans = UserManager.getInstance().getPropertyHandlerTranslator(getTranslator());;
 		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
-		tableConfig.setTableEmptyMessage(translate("resources.noresources"));
+		tableConfig.setTableEmptyMessage(translate("resources.nomembers"));
 		usersCtrl = new TableController(tableConfig, ureq, getWindowControl(), userTrans);
 		listenTo(usersCtrl);
 
diff --git a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_de.properties
index 43bfe20dc2d..812dc3a6e92 100644
--- a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_de.properties
@@ -81,6 +81,7 @@ table.subject.action=Aktion
 table.status=Status
 table.role=Rolle
 
+resources.nomembers=Es wurde keine Mitglieder für diese Gruppe gefunden.
 mailtemplateform.defaultTemplate=Standard Email Vorlage
 mailnotification.title=$org.olat.core.util.mail\:mailnotification.title
 mailtemplateform.sendMailSwitchElem=$org.olat.core.util.mail\:mailtemplateform.sendMailSwitchElem
diff --git a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_en.properties
index 9b376510af3..8a827ccc587 100644
--- a/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/group/ui/wizard/_i18n/LocalStrings_en.properties
@@ -74,6 +74,7 @@ merge.target.group=Target group
 merge.target.title=Choose the target group
 merge.wizard.title=Merge groups
 remove=Remove
+resources.nomembers=No course found for these groups.
 showfile=Download file
 table.role=Role
 table.status=Status
-- 
GitLab