From c2e5d6135a026103871a7c924bd48dc67ae58f2b Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Thu, 18 Jul 2019 19:05:54 +0200
Subject: [PATCH] OO-4153: refactor the resources list of groups with a flexi
 table

---
 .../run/BusinessGroupMainRunController.java   |  53 +------
 .../run/BusinessGroupResourceController.java  | 138 ++++++++++++++++++
 .../ui/RepositoryFlexiTableSortDelegate.java  |  52 +++++++
 3 files changed, 197 insertions(+), 46 deletions(-)
 create mode 100644 src/main/java/org/olat/group/ui/run/BusinessGroupResourceController.java

diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
index 70a21c8cbda..4afeb0c10a4 100644
--- a/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupMainRunController.java
@@ -29,7 +29,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.olat.NewControllerFactory;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.collaboration.CollaborationTools;
 import org.olat.collaboration.CollaborationToolsFactory;
@@ -42,10 +41,6 @@ import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.panel.Panel;
 import org.olat.core.gui.components.stack.PopEvent;
 import org.olat.core.gui.components.stack.TooledStackedPanel;
-import org.olat.core.gui.components.table.Table;
-import org.olat.core.gui.components.table.TableController;
-import org.olat.core.gui.components.table.TableEvent;
-import org.olat.core.gui.components.table.TableGuiConfiguration;
 import org.olat.core.gui.components.tree.GenericTreeModel;
 import org.olat.core.gui.components.tree.GenericTreeNode;
 import org.olat.core.gui.components.tree.MenuTree;
@@ -58,7 +53,6 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.MainLayoutBasicController;
 import org.olat.core.gui.control.generic.dtabs.Activateable2;
 import org.olat.core.gui.control.generic.messages.MessageUIFactory;
-import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.context.BusinessControlFactory;
@@ -97,9 +91,6 @@ import org.olat.modules.portfolio.PortfolioV2Module;
 import org.olat.modules.wiki.WikiManager;
 import org.olat.modules.wiki.WikiModule;
 import org.olat.portfolio.PortfolioModule;
-import org.olat.repository.RepositoryEntry;
-import org.olat.repository.RepositoryService;
-import org.olat.repository.ui.RepositoryTableModel;
 import org.olat.resource.OLATResource;
 import org.olat.resource.accesscontrol.ACService;
 import org.olat.resource.accesscontrol.AccessControlModule;
@@ -177,9 +168,9 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 	public static final String ACTIVITY_MENUSELECT_AC = "MENU_SHOW_AC";
 
 	private Panel mainPanel;
-	private VelocityContainer main, vc_sendToChooserForm, resourcesVC;
+	private VelocityContainer main;
+	private VelocityContainer vc_sendToChooserForm;
 	private final TooledStackedPanel toolbarPanel;
-	private Translator resourceTrans;
 
 	private BusinessGroup businessGroup;
 
@@ -190,7 +181,7 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 	
 	private BusinessGroupEditController bgEditCntrllr;
 	private Controller bgACHistoryCtrl;
-	private TableController resourcesCtr;
+	private BusinessGroupResourceController resourcesCtr;
 	private GroupMembersRunController groupMembersToggleViewController;
 
 	private BusinessGroupSendToChooserForm sendToChooserForm;
@@ -325,7 +316,6 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 		// package translator with default group fallback translators and type
 		// translator
 		setTranslator(Util.createPackageTranslator(BGControllerFactory.class, getLocale(), getTranslator()));
-		resourceTrans = Util.createPackageTranslator(RepositoryService.class, getLocale(), getTranslator());
 
 		// main component layed out in panel
 		main = createVelocityContainer("bgrun");
@@ -470,23 +460,6 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 				mainPanel.setContent(main);
 			}
 
-		} else if (source == resourcesCtr) {
-			if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) {
-				TableEvent te = (TableEvent) event;
-				String actionid = te.getActionId();
-				int rowid = te.getRowId();
-				RepositoryTableModel repoTableModel = (RepositoryTableModel) resourcesCtr.getTableDataModel();
-				if (RepositoryTableModel.TABLE_ACTION_SELECT_LINK.equals(actionid)) {
-
-					RepositoryEntry currentRepoEntry = repoTableModel.getObject(rowid);
-					OLATResource ores = currentRepoEntry.getOlatResource();
-					if (ores == null) throw new AssertException("repoEntry had no olatresource, repoKey = " + currentRepoEntry.getKey());
-					addLoggingResourceable(LoggingResourceable.wrap(ores, OlatResourceableType.genRepoEntry));
-
-					String businessPath = "[RepositoryEntry:" + currentRepoEntry.getKey() + "]";
-					NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
-				}
-			}
 		} else if (source == sendToChooserForm) {
 			if (event == Event.DONE_EVENT) {
 				removeAsListenerAndDispose(collabToolCtr);
@@ -1072,25 +1045,13 @@ public class BusinessGroupMainRunController extends MainLayoutBasicController im
 	}
 
 	private void doShowResources(UserRequest ureq) {
-		// always refresh data model, maybe it has changed
-		RepositoryTableModel repoTableModel = new RepositoryTableModel(getLocale());
-		List<RepositoryEntry> repoTableModelEntries = businessGroupService.findRepositoryEntries(Collections.singletonList(businessGroup), 0, -1);
-		repoTableModel.setObjects(repoTableModelEntries);
-		// init table controller only once
 		if (resourcesCtr == null) {
-			TableGuiConfiguration tableConfig = new TableGuiConfiguration();
-			tableConfig.setTableEmptyMessage(translate("resources.noresources"));
-			//removeAsListenerAndDispose(resourcesCtr);
-			resourcesCtr = new TableController(tableConfig, ureq, getWindowControl(), resourceTrans);
+			resourcesCtr = new BusinessGroupResourceController(ureq, getWindowControl(), businessGroup);
 			listenTo(resourcesCtr);
-			
-			resourcesVC = createVelocityContainer("resources");
-			repoTableModel.addColumnDescriptors(resourcesCtr, true, false, false, false);
-			resourcesVC.put("resources", resourcesCtr.getInitialComponent());
+		} else {
+			resourcesCtr.loadModel();
 		}
-		// add table model to table
-		resourcesCtr.setTableDataModel(repoTableModel);
-		mainPanel.setContent(resourcesVC);
+		mainPanel.setContent(resourcesCtr.getInitialComponent());
 		addToHistory(ureq, ORES_TOOLRESOURCES, null);
 	}
 
diff --git a/src/main/java/org/olat/group/ui/run/BusinessGroupResourceController.java b/src/main/java/org/olat/group/ui/run/BusinessGroupResourceController.java
new file mode 100644
index 00000000000..fa8910d22b5
--- /dev/null
+++ b/src/main/java/org/olat/group/ui/run/BusinessGroupResourceController.java
@@ -0,0 +1,138 @@
+/**
+ * <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.run;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.olat.NewControllerFactory;
+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.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel;
+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.control.Controller;
+import org.olat.core.gui.control.WindowControl;
+import org.olat.core.logging.activity.OlatResourceableType;
+import org.olat.core.util.Util;
+import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupService;
+import org.olat.login.LoginModule;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.ui.RepositoryEntryACColumnDescriptor;
+import org.olat.repository.ui.RepositoryFlexiTableModel;
+import org.olat.repository.ui.RepositoryFlexiTableModel.RepoCols;
+import org.olat.repository.ui.author.AccessRenderer;
+import org.olat.repository.ui.author.GuestAccessRenderer;
+import org.olat.repository.ui.author.TypeRenderer;
+import org.olat.resource.OLATResource;
+import org.olat.util.logging.activity.LoggingResourceable;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 18 juil. 2019<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class BusinessGroupResourceController extends FormBasicController {
+	
+	private FlexiTableElement tableEl;
+	private RepositoryFlexiTableModel tableModel;
+	
+	private final BusinessGroup businessGroup;
+
+	@Autowired
+	private LoginModule loginModule;
+	@Autowired
+	private BusinessGroupService businessGroupService;
+	
+	public BusinessGroupResourceController(UserRequest ureq, WindowControl wControl, BusinessGroup businessGroup) {
+		super(ureq, wControl, "resources", Util.createPackageTranslator(RepositoryService.class, ureq.getLocale()));
+		this.businessGroup = businessGroup;
+		initForm(ureq);
+		loadModel();
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.ac, new RepositoryEntryACColumnDescriptor()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.repoEntry, new TypeRenderer()));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.externalRef));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.lifecycleLabel));// visible if lifecycle
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.displayname, "select"));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.author));
+		columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.access, new AccessRenderer(getLocale())));
+		if(loginModule.isGuestLoginEnabled()) {
+			columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(RepoCols.guests, new GuestAccessRenderer(getLocale())));
+		}
+		
+		tableModel = new RepositoryFlexiTableModel(columnsModel, getLocale());
+		tableEl = uifactory.addTableElement(getWindowControl(), "resources", tableModel, 24, false, getTranslator(), formLayout);
+		tableEl.setAndLoadPersistedPreferences(ureq, "group-resources");
+		tableEl.setEmtpyTableMessageKey("resources.noresources");
+		tableEl.setExportEnabled(true);
+	}
+	
+	protected void loadModel() {
+		List<RepositoryEntry> entries = businessGroupService.findRepositoryEntries(Collections.singletonList(businessGroup), 0, -1);
+		tableModel.setObjects(entries);
+		tableEl.reset(true, true, true);
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(tableEl == source) {
+			if(event instanceof SelectionEvent) {
+				SelectionEvent se = (SelectionEvent)event;
+				if("select".equals(se.getCommand())) {
+					RepositoryEntry entry = tableModel.getObject(se.getIndex());
+					doOpenEntry(ureq, entry);
+				}
+			}
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		//
+	}
+	
+	private void doOpenEntry(UserRequest ureq, RepositoryEntry entry) {
+		OLATResource ores = entry.getOlatResource();
+		addLoggingResourceable(LoggingResourceable.wrap(ores, OlatResourceableType.genRepoEntry));
+
+		String businessPath = "[RepositoryEntry:" + entry.getKey() + "]";
+		NewControllerFactory.getInstance().launch(businessPath, ureq, getWindowControl());
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+}
diff --git a/src/main/java/org/olat/repository/ui/RepositoryFlexiTableSortDelegate.java b/src/main/java/org/olat/repository/ui/RepositoryFlexiTableSortDelegate.java
index a7667a167ef..2d3ecff931a 100644
--- a/src/main/java/org/olat/repository/ui/RepositoryFlexiTableSortDelegate.java
+++ b/src/main/java/org/olat/repository/ui/RepositoryFlexiTableSortDelegate.java
@@ -19,11 +19,16 @@
  */
 package org.olat.repository.ui;
 
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
 import java.util.Locale;
 
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate;
 import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryStatusEnum;
+import org.olat.repository.ui.RepositoryFlexiTableModel.RepoCols;
 
 /**
  * 
@@ -36,5 +41,52 @@ public class RepositoryFlexiTableSortDelegate extends SortableFlexiTableModelDel
 	public RepositoryFlexiTableSortDelegate(SortKey orderBy, RepositoryFlexiTableModel tableModel, Locale locale) {
 		super(orderBy, tableModel, locale);
 	}
+	
+	@Override
+	protected void sort(List<RepositoryEntry> rows) {
+		int columnIndex = getColumnIndex();
+		RepoCols column = RepoCols.values()[columnIndex];
+		switch(column) {
+			case repoEntry: Collections.sort(rows, new TypeComparator()); break;
+			default: super.sort(rows); break;
+		}
+	}
+	
+	private class TypeComparator implements Comparator<RepositoryEntry> {
+
+		@Override
+		public int compare(RepositoryEntry o1, RepositoryEntry o2) {
+			if(o1 == null || o2 == null) {
+				return compareNullObjects(o1, o2);
+			}
+			RepositoryEntryStatusEnum s1 = o1.getEntryStatus();
+			RepositoryEntryStatusEnum s2 = o2.getEntryStatus();
+			
+			int st1 = getStatusScore(s1);
+			int st2 = getStatusScore(s2);
+			int c = Integer.compare(st1, st2);
+			if(c == 0) {
+				String r1 = o1.getOlatResource().getResourceableTypeName();
+				String r2 = o2.getOlatResource().getResourceableTypeName();
+				c = compareString(r1, r2);
+			}
+			if(c == 0) {
+				c = compareString(o1.getDisplayname(), o2.getDisplayname());
+			}
+			if(c == 0) {
+				c = compareLongs(o1.getKey(), o2.getKey());
+			}
+			return c;
+		}
+		
+		private int getStatusScore(RepositoryEntryStatusEnum status) {
+			switch(status) {
+				case closed: return 1;
+				case trash:
+				case deleted: return 2;
+				default: return 0;
+			}
+		}
+	}
 
 }
-- 
GitLab