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 910a4210ac8a2bceeb8120a367fe62d21bf919d3..c81a11ee3e23c56d76ffc5bbfe7cf542dc794df8 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 @@ -28,6 +28,7 @@ package org.olat.core.gui.components.form.flexible.elements; import java.util.List; import java.util.Set; +import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.impl.elements.table.ExtendedFlexiTableSearchController; @@ -235,6 +236,12 @@ public interface FlexiTableElement extends FormItem { */ public void setSortSettings(FlexiTableSortOptions options); + /** + * Return the current sorting if any. + * @return + */ + public SortKey[] getOrderBy(); + /** * Enable export * @return True if export is enabled diff --git a/src/main/java/org/olat/modules/fo/ForumHelper.java b/src/main/java/org/olat/modules/fo/ForumHelper.java index 31e7e62bf9f70683ae1059e4f539aa15fbe42f92..b1ad9a0b4f98ab070805c8709b206f98e45098d4 100644 --- a/src/main/java/org/olat/modules/fo/ForumHelper.java +++ b/src/main/java/org/olat/modules/fo/ForumHelper.java @@ -28,7 +28,6 @@ package org.olat.modules.fo; import java.io.File; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Comparator; import java.util.Date; import org.olat.core.commons.modules.bc.FolderConfig; @@ -36,7 +35,6 @@ import org.olat.core.commons.modules.bc.vfs.OlatRootFolderImpl; import org.olat.core.gui.UserRequest; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; -import org.olat.modules.fo.archiver.MessageNode; /** * @@ -65,33 +63,4 @@ public class ForumHelper { container = (VFSContainer) vfsItem; return container; } - - - /** - * Comparators can be passed to a sort method (such as Collections.sort) - * to allow precise control over the sort order. - * <p> - * Sticky threads first, last modified first. - * - * @return a MessageNode comparator. - * @see java.util.Comparator - */ - public static Comparator<MessageNode> getMessageNodeComparator() { - return new MessageNodeComparator(); - } - - private static class MessageNodeComparator implements Comparator<MessageNode> { - @Override - public int compare(final MessageNode m1, final MessageNode m2) { - if(m1.isSticky() && m2.isSticky()) { - return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first - } else if(m1.isSticky()) { - return -1; - } else if(m2.isSticky()){ - return 1; - } else { - return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first - } - } - } } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java b/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java index 56eeeb5439f432a2770c61a7960705df91a6e1ae..54843950fcce86005c6224ddc9d644ac03a0e54f 100644 --- a/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java +++ b/src/main/java/org/olat/modules/fo/archiver/ForumArchiveManager.java @@ -36,7 +36,6 @@ import org.olat.core.logging.Tracing; import org.olat.core.util.tree.TreeVisitor; import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumCallback; -import org.olat.modules.fo.ForumHelper; import org.olat.modules.fo.Message; import org.olat.modules.fo.archiver.formatters.ForumFormatter; import org.olat.modules.fo.manager.ForumManager; @@ -117,19 +116,24 @@ public class ForumArchiveManager { topNodeList.add(topNode); } } - } - return getMessagesSorted(topNodeList); + } + Collections.sort(topNodeList, new MessageNodeComparator()); + return topNodeList; } - /** - * Sorts the input list by adding the sticky messages first. - * @param topNodeList - * @return the sorted list. - */ - private List<MessageNode> getMessagesSorted(List<MessageNode> topNodeList) { - Comparator<MessageNode> messageNodeComparator = ForumHelper.getMessageNodeComparator(); - Collections.sort(topNodeList, messageNodeComparator); - return topNodeList; + public static class MessageNodeComparator implements Comparator<MessageNode> { + @Override + public int compare(final MessageNode m1, final MessageNode m2) { + if(m1.isSticky() && m2.isSticky()) { + return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first + } else if(m1.isSticky()) { + return -1; + } else if(m2.isSticky()){ + return 1; + } else { + return m2.getModifiedDate().compareTo(m1.getModifiedDate()); //last first + } + } } /** diff --git a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java index f56811de6e97183fd34d47ee65ab9f36ec074c78..83bfd0c0cccdcd5f3cbbcb9ba559529941f940a0 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java @@ -20,7 +20,11 @@ package org.olat.modules.fo.ui; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -46,6 +50,7 @@ import org.olat.core.id.UserConstants; import org.olat.core.util.Util; import org.olat.modules.fo.Forum; import org.olat.modules.fo.MessageLight; +import org.olat.modules.fo.Status; import org.olat.modules.fo.manager.ForumManager; import org.olat.modules.fo.ui.ForumMessageDataModel.ForumMessageCols; import org.olat.modules.fo.ui.events.SelectMessageEvent; @@ -128,40 +133,29 @@ public class ForumMessageListController extends FormBasicController implements F keyToViews.put(view.getKey(), view); } - //TODO forum: implement a reorder method which works on threads and parent line - /*calculate depth - + //calculate depth + Map<Long, List<Long>> keyToParentline = new HashMap<>(); for(MessageLightView view:views) { if(view.getParentKey() == null) { view.setDepth(0); } else { + List<Long> parentLine = new ArrayList<>(5); view.setDepth(1); for(MessageLightView parent = keyToViews.get(view.getParentKey()); parent != null; parent = keyToViews.get(parent.getParentKey())) { view.setDepth(view.getDepth() + 1); + parentLine.add(parent.getKey()); } + keyToParentline.put(view.getKey(), parentLine); } } //order - */ - - dataModel.setObjects(views); - } - /* - private class MessageComparator implements Comparator<MessageLightView> { - - @Override - public int compare(MessageLightView v1, MessageLightView v2) { - Long tt1 = v1.getThreadtopKey() == null ? v1.getKey() : v1.getThreadtopKey(); - Long tt2 = v2.getThreadtopKey() == null ? v2.getKey() : v2.getThreadtopKey(); - int c = Long.compare(tt1.longValue(), tt2.longValue()); - if(c == 0) { - - } - return c; - } + List<MessageNode> threads = convertToThreadTrees(views); + Collections.sort(threads, new MessageNodeComparator()); + List<MessageLightView> orderedViews = new ArrayList<>(allMessages.size()); + flatTree(threads, orderedViews); + dataModel.setObjects(orderedViews); } - */ public void loadMessages(List<MessageLightView> views) { dataModel.setObjects(views); @@ -229,4 +223,95 @@ public class ForumMessageListController extends FormBasicController implements F } super.formInnerEvent(ureq, source, event); } + + private void flatTree(List<MessageNode> nodes, List<MessageLightView> orderedViews) { + for(MessageNode node:nodes) { + orderedViews.add(node.getView()); + if(node.hasChildren()) { + flatTree(node.getChildren(), orderedViews); + } + } + } + + private List<MessageNode> convertToThreadTrees(List<MessageLightView> messages){ + List<MessageNode> topNodeList = new ArrayList<>(); + + for (Iterator<MessageLightView> iterTop = messages.iterator(); iterTop.hasNext();) { + MessageLightView msg = iterTop.next(); + if (msg.getParentKey() == null) { + iterTop.remove(); + MessageNode topNode = new MessageNode(msg); + addChildren(messages, topNode); + topNodeList.add(topNode); + } + } + return topNodeList; + } + + private void addChildren(List<MessageLightView> messages, MessageNode mn){ + for(Iterator<MessageLightView> iterMsg = messages.iterator(); iterMsg.hasNext(); ) { + MessageLightView msg = iterMsg.next(); + if ((msg.getParentKey() != null) && (msg.getParentKey().equals(mn.getKey()))){ + MessageNode childNode = new MessageNode(msg); + mn.addChild(childNode); + addChildren(messages, childNode); + } + } + } + + private static class MessageNode { + + private final MessageLightView view; + private List<MessageNode> children; + + public MessageNode(MessageLightView view) { + this.view = view; + } + + public Long getKey() { + return view.getKey(); + } + + public boolean isSticky() { + return Status.getStatus(view.getStatusCode()).isSticky(); + } + + public Date getLastModified() { + return view.getLastModified(); + } + + public MessageLightView getView() { + return view; + } + + public boolean hasChildren() { + return children != null && children.size() > 0; + } + + public void addChild(MessageNode child) { + if(children == null) { + children = new ArrayList<>(); + } + children.add(child); + } + + public List<MessageNode> getChildren() { + return children; + } + } + + public static class MessageNodeComparator implements Comparator<MessageNode> { + @Override + public int compare(final MessageNode m1, final MessageNode m2) { + if(m1.isSticky() && m2.isSticky()) { + return m2.getLastModified().compareTo(m1.getLastModified()); //last first + } else if(m1.isSticky()) { + return -1; + } else if(m2.isSticky()){ + return 1; + } else { + return m2.getLastModified().compareTo(m1.getLastModified()); //last first + } + } + } } \ No newline at end of file diff --git a/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java b/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java index d4bdcf7de56348c34d6021d27d91a39d10826cb4..4578b8f352cc5fefa424ec0eee066d0349c75738 100644 --- a/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java +++ b/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java @@ -19,6 +19,7 @@ */ package org.olat.modules.fo.ui; +import org.olat.core.commons.persistence.SortKey; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableComponent; import org.olat.core.gui.render.Renderer; @@ -41,19 +42,26 @@ public class IndentCellRenderer implements FlexiCellRenderer { public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, URLBuilder ubu, Translator translator) { - Object m = source.getFlexiTableElement().getTableDataModel().getObject(row); - if(m instanceof MessageLightView && cellValue instanceof String) { - MessageLightView message = (MessageLightView)m; - int indent = message.getDepth(); - if (indent > MAXINDENTS) { - indent = MAXINDENTS; + SortKey[] keys = source.getFlexiTableElement().getOrderBy(); + if(keys != null && keys.length > 0 && keys[0] != null) { + if(cellValue instanceof String) { + target.append((String)cellValue); + } + } else { + Object m = source.getFlexiTableElement().getTableDataModel().getObject(row); + if(m instanceof MessageLightView && cellValue instanceof String) { + MessageLightView message = (MessageLightView)m; + int indent = message.getDepth(); + if (indent > MAXINDENTS) { + indent = MAXINDENTS; + } + target.append("<div style=\"white-space: nowrap;") + .append("padding-left: ").append(indent).append("em;\">") + .append(Formatter.truncate((String)cellValue, 50 - indent)) + .append("</div>"); + } else if(cellValue instanceof String) { + target.append((String)cellValue); } - target.append("<div style=\"white-space: nowrap;") - .append("padding-left: ").append(indent).append("em;\">") - .append(Formatter.truncate((String)cellValue, 50 - indent)) - .append("</div>"); - } else if(cellValue instanceof String) { - target.append((String)cellValue); } } }