From ba9d2c8b671fc606da304040b300291d9c059e5f Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Mon, 5 Aug 2019 14:38:40 +0200 Subject: [PATCH] OO-4091: Use standard mechanism from FlexiTable to make the hierarchical view --- .../services/mark/impl/ui/MarkController.java | 9 +- .../services/mark/impl/ui/MarkedEvent.java | 10 +- .../services/mark/impl/ui/UnmarkedEvent.java | 16 +- .../table/AbstractFlexiTableRenderer.java | 2 +- .../table/DefaultFlexiTreeTableDataModel.java | 10 + .../table/FlexiTreeTableDataModel.java | 4 +- .../table/TreeNodeFlexiCellRenderer.java | 23 ++ .../org/olat/modules/fo/MessageLight.java | 3 - .../modules/fo/ui/ForumMessageDataModel.java | 25 +- .../fo/ui/ForumMessageListController.java | 292 ++++++++---------- .../modules/fo/ui/IndentCellRenderer.java | 67 ---- .../modules/fo/ui/MessageLightViewRow.java | 38 ++- .../modules/fo/ui/MessageListController.java | 15 +- .../fo/ui/MessageTreeRowComparator.java | 56 ++++ 14 files changed, 319 insertions(+), 251 deletions(-) delete mode 100644 src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java create mode 100644 src/main/java/org/olat/modules/fo/ui/MessageTreeRowComparator.java diff --git a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java index 5214b068817..fe9a648c113 100644 --- a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java +++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkController.java @@ -112,9 +112,9 @@ public class MarkController extends FormBasicController { Integer countI = stat.getCount(); if (mark!=null && mark.getCreator().equalsByPersistableKey(getIdentity())){ if (countI == 1) { - tooltip = getTranslator().translate("mark.stat.self.only"); + tooltip = getTranslator().translate("mark.stat.self.only"); } else { - tooltip = getTranslator().translate("mark.stat.self", new String[]{ new Integer(countI-1).toString() }); + tooltip = getTranslator().translate("mark.stat.self", new String[]{ new Integer(countI-1).toString() }); } } else { tooltip = getTranslator().translate("mark.stat", new String[]{ countI.toString() }); @@ -141,14 +141,15 @@ public class MarkController extends FormBasicController { if(marked) { if(mark == null) { markingService.getMarkManager().removeMark(ores, ureq.getIdentity(), subPath); + fireEvent(ureq, new UnmarkedEvent(ores, subPath)); } else { markingService.getMarkManager().removeMark(mark); + fireEvent(ureq, new UnmarkedEvent(mark.getOLATResourceable(), mark.getResSubPath())); mark = null; } - fireEvent(ureq, new UnmarkedEvent()); } else { mark = markingService.getMarkManager().setMark(ores, identity, subPath, businessPath); - fireEvent(ureq, new MarkedEvent()); + fireEvent(ureq, new MarkedEvent(mark)); } marked = !marked; markLink.setIconLeftCSS(marked ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE); diff --git a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java index 805d02505ed..7a86a2df5c7 100644 --- a/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java +++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java @@ -19,6 +19,7 @@ */ package org.olat.core.commons.services.mark.impl.ui; +import org.olat.core.commons.services.mark.Mark; import org.olat.core.gui.control.Event; /** @@ -31,8 +32,15 @@ public class MarkedEvent extends Event { private static final long serialVersionUID = -4104070726631981649L; - public MarkedEvent() { + private final Mark mark; + + public MarkedEvent(Mark mark) { super("marked"); + this.mark = mark; + } + + public Mark getMark() { + return mark; } } diff --git a/src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java b/src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java index 3fc40176532..885c2d4012d 100644 --- a/src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java +++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java @@ -20,6 +20,7 @@ package org.olat.core.commons.services.mark.impl.ui; import org.olat.core.gui.control.Event; +import org.olat.core.id.OLATResourceable; /** * @@ -31,8 +32,21 @@ public class UnmarkedEvent extends Event { private static final long serialVersionUID = 3503240359856342650L; - public UnmarkedEvent() { + private final OLATResourceable ores; + private final String subPath; + + public UnmarkedEvent(OLATResourceable ores, String subPath) { super("unmarked"); + this.ores = ores; + this.subPath = subPath; + } + + public OLATResourceable getOres() { + return ores; + } + + public String getSubPath() { + return subPath; } } 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 7939cfa1a0e..2551742adca 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 @@ -425,7 +425,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere .append("</span></a>"); } - if(ftE.getTreeTableDataModel() != null) { + if(ftE.getTreeTableDataModel() != null && ftE.getTreeTableDataModel().hasOpenCloseAll()) { sb.append("<a id='") .append(dispatchId).append("_toa' href=\"javascript:;\" onclick=\"") .append(FormJSHelper.getXHRFnCallFor(ftE.getRootForm(), dispatchId, 1, true, true, true, diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTreeTableDataModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTreeTableDataModel.java index 9a0dee965e3..feaf0ce9837 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTreeTableDataModel.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/DefaultFlexiTreeTableDataModel.java @@ -42,6 +42,7 @@ implements FlexiTreeTableDataModel<U>, FilterableFlexiTableModel { protected final Set<U> openedRows = new HashSet<>(); protected List<U> backupRows; protected U focusedNode; + private boolean hasOpenCloseAll = true; public DefaultFlexiTreeTableDataModel(FlexiTableColumnModel columnModel) { super(columnModel); @@ -187,6 +188,15 @@ implements FlexiTreeTableDataModel<U>, FilterableFlexiTableModel { return refreshedCrumbs; } + @Override + public boolean hasOpenCloseAll() { + return hasOpenCloseAll; + } + + protected void setHasOpenCloseAll(boolean hasOpenCloseAll) { + this.hasOpenCloseAll = hasOpenCloseAll; + } + @SuppressWarnings("unchecked") @Override public void openAll() { diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTreeTableDataModel.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTreeTableDataModel.java index cb6f50ac17a..2df9e76c22c 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTreeTableDataModel.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTreeTableDataModel.java @@ -48,6 +48,8 @@ public interface FlexiTreeTableDataModel<T extends FlexiTreeTableNode> extends F public void open(int row); + public boolean hasOpenCloseAll(); + /** * The table will call the openAll method and filter() right after. * @@ -61,5 +63,5 @@ public interface FlexiTreeTableDataModel<T extends FlexiTreeTableNode> extends F public void popBreadcrumb(FlexiTreeTableNode node); public List<FlexiTreeTableNode> reloadBreadcrumbs(List<FlexiTreeTableNode> crumbs); - + } diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/TreeNodeFlexiCellRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/TreeNodeFlexiCellRenderer.java index 232d9e2d353..33fc0b05c2b 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/TreeNodeFlexiCellRenderer.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/TreeNodeFlexiCellRenderer.java @@ -21,6 +21,7 @@ package org.olat.core.gui.components.form.flexible.impl.elements.table; import java.util.List; +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.Form; import org.olat.core.gui.components.form.flexible.impl.FormJSHelper; @@ -42,6 +43,7 @@ public class TreeNodeFlexiCellRenderer implements FlexiCellRenderer { private FlexiCellRenderer labelDelegate = new TextFlexiCellRenderer(); private boolean flatBySearchAndFilter; + private boolean flatBySort; private final String action; public TreeNodeFlexiCellRenderer() { @@ -60,6 +62,14 @@ public class TreeNodeFlexiCellRenderer implements FlexiCellRenderer { this.flatBySearchAndFilter = flatBySearchAndFilter; } + public boolean isFlatBySort() { + return flatBySort; + } + + public void setFlatBySort(boolean flatBySort) { + this.flatBySort = flatBySort; + } + @Override public void render(Renderer renderer, StringOutput target, Object cellValue, int row, FlexiTableComponent source, URLBuilder ubu, Translator translator) { @@ -77,10 +87,23 @@ public class TreeNodeFlexiCellRenderer implements FlexiCellRenderer { } private boolean isFlat(FlexiTableElementImpl ftE) { + return isFlatSearchAndFilter(ftE) || isFlatSort(ftE) ; + } + + private boolean isFlatSearchAndFilter(FlexiTableElementImpl ftE) { return flatBySearchAndFilter && (StringHelper.containsNonWhitespace(ftE.getQuickSearchString()) || isFiltered(ftE.getSelectedFilters())); } + private boolean isFlatSort(FlexiTableElementImpl ftE) { + return flatBySort && isSorted(ftE); + } + + private boolean isSorted(FlexiTableElementImpl ftE) { + SortKey[] keys = ftE.getOrderBy(); + return keys != null && keys.length > 0 && keys[0] != null && !"natural".equals(keys[0].getKey()); + } + private boolean isFiltered(List<FlexiTableFilter> filters) { if(filters == null || filters.isEmpty()) return false; diff --git a/src/main/java/org/olat/modules/fo/MessageLight.java b/src/main/java/org/olat/modules/fo/MessageLight.java index fcace6e0567..b81bad0ad9b 100644 --- a/src/main/java/org/olat/modules/fo/MessageLight.java +++ b/src/main/java/org/olat/modules/fo/MessageLight.java @@ -31,8 +31,6 @@ import org.olat.core.id.Identity; */ public interface MessageLight extends MessageRef { - public int getStatusCode(); - public String getTitle(); public String getBody(); @@ -49,7 +47,6 @@ public interface MessageLight extends MessageRef { public Date getLastModified(); - public Long getParentKey(); public MessageRef getThreadtop(); diff --git a/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java b/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java index eab2a128e4e..8085cba2356 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java @@ -23,7 +23,9 @@ import java.util.List; import java.util.Locale; 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.DefaultFlexiTableDataModel; +import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiTreeTableDataModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSortableColumnDef; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; @@ -32,13 +34,15 @@ import org.olat.core.gui.translator.Translator; import org.olat.core.util.StringHelper; import org.olat.group.ui.main.AbstractMemberListController; +import edu.emory.mathcs.backport.java.util.Collections; + /** * * Initial date: 12.11.2015<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLightViewRow> +public class ForumMessageDataModel extends DefaultFlexiTreeTableDataModel<MessageLightViewRow> implements SortableFlexiTableDataModel<MessageLightViewRow> { private Translator translator; @@ -48,14 +52,30 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig this.translator = translator; } + @Override + public void filter(String searchString, List<FlexiTableFilter> filters) { + // + } + + @Override + public boolean hasChildren(int row) { + MessageLightViewRow viewRow = getObject(row); + return viewRow.hasChildren(); + } + @Override public void sort(SortKey orderBy) { if(orderBy != null) { if("natural".equals(orderBy.getKey())) { - //System.out.println(); + List<MessageLightViewRow> objects = getObjects(); + Collections.sort(objects, new MessageTreeRowComparator()); + super.setObjects(objects); + setHasOpenCloseAll(true); } else { + openAll(); List<MessageLightViewRow> views = new ForumMessageDataModelSort(orderBy, this, null).sort(); super.setObjects(views); + setHasOpenCloseAll(false); } } } @@ -129,4 +149,5 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig super(orderBy, tableModel, locale); } } + } \ No newline at end of file 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 d3851ac74e3..8c6f62a032f 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java @@ -21,10 +21,7 @@ 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; import java.util.Set; @@ -51,6 +48,7 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTable import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.TextFlexiCellRenderer; +import org.olat.core.gui.components.form.flexible.impl.elements.table.TreeNodeFlexiCellRenderer; import org.olat.core.gui.components.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; @@ -61,7 +59,6 @@ import org.olat.core.util.mail.ui.BooleanCSSCellRenderer; import org.olat.core.util.resource.OresHelper; 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; @@ -72,18 +69,19 @@ import org.springframework.beans.factory.annotation.Autowired; /** * * Initial date: 12.11.2015<br> + * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class ForumMessageListController extends FormBasicController { - + protected static final String USER_PROPS_ID = ForumUserListController.class.getCanonicalName(); - + public static final int USER_PROPS_OFFSET = 500; - + private FlexiTableElement tableEl; private ForumMessageDataModel dataModel; - + private final Forum forum; private final boolean withType; private final boolean showMarks; @@ -93,7 +91,7 @@ public class ForumMessageListController extends FormBasicController { private final OLATResourceable forumOres; private final List<UserPropertyHandler> userPropertyHandlers; private MessageView userObject, selectView; - + @Autowired private UserManager userManager; @Autowired @@ -102,26 +100,26 @@ public class ForumMessageListController extends FormBasicController { private MarkingService markingService; @Autowired private BaseSecurityModule securityModule; - - public ForumMessageListController(UserRequest ureq, WindowControl wControl, - Forum forum, boolean withType, boolean showMarks, boolean showNew) { + + public ForumMessageListController(UserRequest ureq, WindowControl wControl, Forum forum, boolean withType, + boolean showMarks, boolean showNew) { super(ureq, wControl, LAYOUT_BAREBONE); setTranslator(Util.createPackageTranslator(Forum.class, getLocale(), getTranslator())); setTranslator(userManager.getPropertyHandlerTranslator(getTranslator())); - + this.forum = forum; this.withType = withType; this.showMarks = showMarks; this.showNew = showNew; this.guestOnly = ureq.getUserSession().getRoles().isGuestOnly(); forumOres = OresHelper.createOLATResourceableInstance("Forum", forum.getKey()); - + isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles()); userPropertyHandlers = userManager.getUserPropertyHandlersFor(USER_PROPS_ID, isAdministrativeUser); - + initForm(ureq); } - + public MessageView getUserObject() { return userObject; } @@ -139,11 +137,11 @@ public class ForumMessageListController extends FormBasicController { } public void loadAllMessages() { - Set<Long> readSet = !guestOnly? forumManager.getReadSet(getIdentity(), forum): Collections.emptySet(); + Set<Long> readSet = !guestOnly ? forumManager.getReadSet(getIdentity(), forum) : Collections.emptySet(); List<MessageLight> allMessages = forumManager.getLightMessagesByForum(forum); List<MessageLightView> views = new ArrayList<>(allMessages.size()); - Map<Long,MessageLightView> keyToViews = new HashMap<>(); - for(MessageLight message:allMessages) { + Map<Long, MessageLightView> keyToViews = new HashMap<>(); + for (MessageLight message : allMessages) { MessageLightView view = new MessageLightView(message, userPropertyHandlers, getLocale()); if (readSet.contains(message.getKey())) { view.setNewMessage(false); @@ -153,59 +151,68 @@ public class ForumMessageListController extends FormBasicController { views.add(view); keyToViews.put(view.getKey(), view); } - - //calculate depth + + // calculate depth Map<Long, List<Long>> keyToParentline = new HashMap<>(); - for(MessageLightView view:views) { - if(view.getParentKey() == null) { + 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())) { + 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 - List<MessageNode> threads = convertToThreadTrees(views); - Collections.sort(threads, new MessageNodeComparator()); - List<MessageLightView> orderedViews = new ArrayList<>(allMessages.size()); - flatTree(threads, orderedViews); - List<MessageLightViewRow> rows = appendLinks(orderedViews); + + List<MessageLightViewRow> rows = forgeRows(views); dataModel.setObjects(rows); } - + public void loadMessages(List<MessageLightView> views) { - List<MessageLightViewRow> rows = appendLinks(views); + List<MessageLightViewRow> rows = forgeRows(views); + Collections.sort(rows, new MessageTreeRowComparator()); dataModel.setObjects(rows); tableEl.reloadData(); tableEl.reset(); } - private List<MessageLightViewRow> appendLinks(List<MessageLightView> views) { - List<Mark> markList = !guestOnly - ? markingService.getMarkManager().getMarks(forumOres, getIdentity(), null) + private List<MessageLightViewRow> forgeRows(List<MessageLightView> views) { + List<Mark> markList = !guestOnly ? markingService.getMarkManager().getMarks(forumOres, getIdentity(), null) : Collections.emptyList(); - Map<String,Mark> marks = new HashMap<>(); + Map<String, Mark> marks = new HashMap<>(); for (Mark mark : markList) { marks.put(mark.getResSubPath(), mark); } - + List<MessageLightViewRow> rows = new ArrayList<>(views.size()); + Map<Long, MessageLightViewRow> keysToRows = new HashMap<>(); for (MessageLightView view : views) { Mark mark = marks.get(view.getKey().toString()); boolean marked = mark != null; - FormLink markLink = uifactory.addFormLink("mark_" + view.getKey(), "mark", "", null, null, Link.NONTRANSLATED); - markLink.setIconLeftCSS(marked? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE); - + FormLink markLink = uifactory.addFormLink("mark_" + view.getKey(), "mark", "", null, null, + Link.NONTRANSLATED); + markLink.setIconLeftCSS(marked ? Mark.MARK_CSS_LARGE : Mark.MARK_ADD_CSS_LARGE); + MessageLightViewRow row = new MessageLightViewRow(view, mark, markLink); markLink.setUserObject(row); rows.add(row); + keysToRows.put(view.getKey(), row); } + + // parent + for (MessageLightViewRow row : rows) { + Long parentKey = row.getView().getParentKey(); + if (parentKey != null) { + MessageLightViewRow parent = keysToRows.get(parentKey); + row.setParent(parent); + } + } + return rows; } @@ -213,34 +220,39 @@ public class ForumMessageListController extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { List<FlexiTableSort> sorts = new ArrayList<>(); sorts.add(new FlexiTableSort(translate("natural.sort"), "natural")); - + FlexiTableColumnModel columnsModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); - if(withType) { - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.type, new StatusTypeCellRenderer())); + if (withType) { + columnsModel.addFlexiColumnModel( + new DefaultFlexiColumnModel(ForumMessageCols.type, new StatusTypeCellRenderer())); sorts.add(new FlexiTableSort(translate(ForumMessageCols.type.i18nHeaderKey()), ForumMessageCols.type.name())); } - + if (showMarks) { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.mark)); } - - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.thread, - "select", new StaticFlexiCellRenderer("select", new IndentCellRenderer()))); + + TreeNodeFlexiCellRenderer treeNodeRenderer = new TreeNodeFlexiCellRenderer("select"); + treeNodeRenderer.setFlatBySearchAndFilter(true); + treeNodeRenderer.setFlatBySort(true); + columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.thread, "select", treeNodeRenderer)); sorts.add(new FlexiTableSort(translate(ForumMessageCols.thread.i18nHeaderKey()), ForumMessageCols.thread.name())); - + int colPos = USER_PROPS_OFFSET; for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) { - if (userPropertyHandler == null) continue; + if (userPropertyHandler == null) + continue; String propName = userPropertyHandler.getName(); - boolean visible = userManager.isMandatoryUserProperty(USER_PROPS_ID , userPropertyHandler); + boolean visible = userManager.isMandatoryUserProperty(USER_PROPS_ID, userPropertyHandler); FlexiColumnModel col; - if(UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { - col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, "select", true, propName, - new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer())); + if (UserConstants.FIRSTNAME.equals(propName) || UserConstants.LASTNAME.equals(propName)) { + col = new DefaultFlexiColumnModel(userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, "select", + true, propName, new StaticFlexiCellRenderer("select", new TextFlexiCellRenderer())); } else { - col = new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, true, propName); + col = new DefaultFlexiColumnModel(visible, userPropertyHandler.i18nColumnDescriptorLabelKey(), colPos, + true, propName); } sorts.add(new FlexiTableSort(translate(userPropertyHandler.i18nColumnDescriptorLabelKey()), propName)); @@ -249,29 +261,31 @@ public class ForumMessageListController extends FormBasicController { } columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.lastModified)); - sorts.add(new FlexiTableSort(translate(ForumMessageCols.lastModified.i18nHeaderKey()), ForumMessageCols.lastModified.name())); + sorts.add(new FlexiTableSort(translate(ForumMessageCols.lastModified.i18nHeaderKey()), + ForumMessageCols.lastModified.name())); - if(showNew && !guestOnly) { + if (showNew && !guestOnly) { FlexiCellRenderer newMessageRenderer = new BooleanCSSCellRenderer(getTranslator(), "o_icon o_forum_new_icon", null, "table.new.message.hover", null); - columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.newMessage, newMessageRenderer)); + columnsModel + .addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.newMessage, newMessageRenderer)); } dataModel = new ForumMessageDataModel(columnsModel, getTranslator()); tableEl = uifactory.addTableElement(getWindowControl(), "messages", dataModel, getTranslator(), formLayout); tableEl.setCssDelegate(new MessageCssDelegate()); - + FlexiTableSortOptions sortOptions = new FlexiTableSortOptions(); sortOptions.setFromColumnModel(false); sortOptions.setSorts(sorts); tableEl.setSortSettings(sortOptions); } - + @Override protected void doDispose() { // } - + @Override protected void formOK(UserRequest ureq) { // @@ -279,28 +293,25 @@ public class ForumMessageListController extends FormBasicController { @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { - if(tableEl == source) { - if(event instanceof SelectionEvent) { - SelectionEvent se = (SelectionEvent)event; + if (tableEl == source) { + if (event instanceof SelectionEvent) { + SelectionEvent se = (SelectionEvent) event; String cmd = se.getCommand(); - if("select".equals(cmd)) { + if ("select".equals(cmd)) { MessageLightView message = dataModel.getObject(se.getIndex()).getView(); fireEvent(ureq, new SelectMessageEvent(SelectMessageEvent.SELECT_MESSAGE, message.getKey())); } } - } else if(source instanceof FormLink) { - FormLink link = (FormLink)source; + } else if (source instanceof FormLink) { + FormLink link = (FormLink) source; String cmd = link.getCmd(); if ("mark".equals(cmd)) { MessageLightViewRow row = (MessageLightViewRow) link.getUserObject(); if (row.isMarked()) { doUnmark(row); - link.setIconLeftCSS(Mark.MARK_ADD_CSS_LARGE); } else { doMark(row); - link.setIconLeftCSS(Mark.MARK_CSS_LARGE); } - link.getComponent().setDirty(true); fireEvent(ureq, new MessageMarkedEvent(selectView.getKey(), row.getView().getKey())); } } @@ -310,115 +321,74 @@ public class ForumMessageListController extends FormBasicController { private void doMark(MessageLightViewRow row) { MessageLightView view = row.getView(); Mark currentMark = row.getMark(); - String businessPath = currentMark == null ? - getWindowControl().getBusinessControl().getAsString() + "[Message:" + view.getKey() + "]" + String businessPath = currentMark == null + ? getWindowControl().getBusinessControl().getAsString() + "[Message:" + view.getKey() + "]" : currentMark.getBusinessPath(); - Mark mark = markingService.getMarkManager().setMark(forumOres, getIdentity(), view.getKey().toString(), businessPath); + Mark mark = markingService.getMarkManager().setMark(forumOres, getIdentity(), view.getKey().toString(), + businessPath); + onMarked(row, mark); + } + + public void onMarked(Mark mark) { + String resSubPath = mark.getResSubPath(); + Long messageKey = toMessageKey(resSubPath); + if (messageKey != null) { + for (MessageLightViewRow row : dataModel.getObjects()) { + if (row.getView().getKey().equals(messageKey)) { + onMarked(row, mark); + return; + } + } + } + } + + private void onMarked(MessageLightViewRow row, Mark mark) { row.setMark(mark); + row.getMarkLink().setIconLeftCSS(Mark.MARK_CSS_LARGE); + row.getMarkLink().getComponent().setDirty(true); } private void doUnmark(MessageLightViewRow row) { MessageLightView view = row.getView(); - markingService.getMarkManager().removeMark(forumOres, getIdentity(), view.getKey().toString()); - row.setMark(null); + String resSubPath = view.getKey().toString(); + markingService.getMarkManager().removeMark(forumOres, getIdentity(), resSubPath); + onUnmarked(row); } - private void flatTree(List<MessageNode> nodes, List<MessageLightView> orderedViews) { - for(MessageNode node:nodes) { - orderedViews.add(node.getView()); - if(node.hasChildren()) { - flatTree(node.getChildren(), orderedViews); + public void onUnmarked(String resSubPath) { + Long messageKey = toMessageKey(resSubPath); + if (messageKey != null) { + for (MessageLightViewRow row : dataModel.getObjects()) { + if (row.getView().getKey().equals(messageKey)) { + onUnmarked(row); + return; + } } } } - - 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 onUnmarked(MessageLightViewRow row) { + row.setMark(null); + row.getMarkLink().setIconLeftCSS(Mark.MARK_ADD_CSS_LARGE); + row.getMarkLink().getComponent().setDirty(true); } - - 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 Long toMessageKey(String resSubPath) { + try { + return Long.parseLong(resSubPath); + } catch (NumberFormatException e) { + // } + return null; } - + private class MessageCssDelegate extends DefaultFlexiTableCssDelegate { @Override public String getRowCssClass(FlexiTableRendererType type, int pos) { MessageLightView row = dataModel.getObject(pos).getView(); - return row != null && selectView != null && row.getKey().equals(selectView.getKey()) ? "o_row_selected" : null; - } - } - - 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 - } + return row != null && selectView != null && row.getKey().equals(selectView.getKey()) ? "o_row_selected" + : null; } } + } \ 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 deleted file mode 100644 index a4bceb094b9..00000000000 --- a/src/main/java/org/olat/modules/fo/ui/IndentCellRenderer.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * <a href="http://www.openolat.org"> - * OpenOLAT - Online Learning and Training</a><br> - * <p> - * Licensed under the Apache License, Version 2.0 (the "License"); <br> - * you may not use this file except in compliance with the License.<br> - * You may obtain a copy of the License at the - * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> - * <p> - * Unless required by applicable law or agreed to in writing,<br> - * software distributed under the License is distributed on an "AS IS" BASIS, <br> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> - * See the License for the specific language governing permissions and <br> - * limitations under the License. - * <p> - * Initial code contributed and copyrighted by<br> - * frentix GmbH, http://www.frentix.com - * <p> - */ -package org.olat.modules.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; -import org.olat.core.gui.render.StringOutput; -import org.olat.core.gui.render.URLBuilder; -import org.olat.core.gui.translator.Translator; -import org.olat.core.util.Formatter; - -/** - * - * Initial date: 12.11.2015<br> - * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com - * - */ -public class IndentCellRenderer implements FlexiCellRenderer { - - private static final int MAXINDENTS = 20; - - @Override - public void render(Renderer renderer, StringOutput target, Object cellValue, int row, - FlexiTableComponent source, URLBuilder ubu, Translator translator) { - - SortKey[] keys = source.getFlexiTableElement().getOrderBy(); - if(keys != null && keys.length > 0 && keys[0] != null && !"natural".equals(keys[0].getKey())) { - 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); - } - } - } -} diff --git a/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java b/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java index beaa850b8cc..fe4aa20da23 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java @@ -19,8 +19,12 @@ */ package org.olat.modules.fo.ui; +import java.util.Date; + import org.olat.core.commons.services.mark.Mark; import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeTableNode; +import org.olat.modules.fo.Status; /** * @@ -28,11 +32,13 @@ import org.olat.core.gui.components.form.flexible.elements.FormLink; * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com * */ -public class MessageLightViewRow { +public class MessageLightViewRow implements FlexiTreeTableNode { private final MessageLightView view; private Mark mark; private final FormLink markLink; + private MessageLightViewRow parent; + private boolean hasChildren; public MessageLightViewRow(MessageLightView view, Mark mark, FormLink markLink) { this.view = view; @@ -59,4 +65,34 @@ public class MessageLightViewRow { public FormLink getMarkLink() { return markLink; } + + public boolean isSticky() { + return Status.getStatus(view.getStatusCode()).isSticky(); + } + + public Date getLastModified() { + return view.getLastModified(); + } + + public void setParent(MessageLightViewRow parent) { + this.parent = parent; + if (parent != null) { + parent.hasChildren = true; + } + } + + @Override + public FlexiTreeTableNode getParent() { + return parent; + } + + @Override + public String getCrump() { + return null; + } + + public boolean hasChildren() { + return hasChildren; + } + } diff --git a/src/main/java/org/olat/modules/fo/ui/MessageListController.java b/src/main/java/org/olat/modules/fo/ui/MessageListController.java index f5cb5726be3..614812011b4 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageListController.java @@ -913,8 +913,12 @@ public class MessageListController extends BasicController implements GenericEve MessageView splitedMessage = (MessageView)confirmSplitCtrl.getUserObject(); doSplitThread(ureq, splitedMessage); } - } else if(event instanceof MarkedEvent || event instanceof UnmarkedEvent) { - reloadMessageTable(ureq); + } else if(event instanceof MarkedEvent) { + MarkedEvent me = (MarkedEvent) event; + messageTableCtrl.onMarked(me.getMark()); + } else if(event instanceof UnmarkedEvent) { + UnmarkedEvent ue = (UnmarkedEvent)event; + messageTableCtrl.onUnmarked(ue.getSubPath()); } else if(source == cmc) { cleanUp(); } @@ -1289,13 +1293,6 @@ public class MessageListController extends BasicController implements GenericEve } } - private void reloadMessageTable(UserRequest ureq) { - String settings = getViewSettings(ureq); - if(VIEWMODE_MESSAGE.equals(settings)) { - doShowOne(ureq); - } - } - private String getViewSettings(UserRequest ureq) { Preferences prefs = ureq.getUserSession().getGuiPreferences(); Object setting = prefs.get(GUI_PREFS_VIEWMODE_CLASS, GUI_PREFS_VIEWMODE_KEY); diff --git a/src/main/java/org/olat/modules/fo/ui/MessageTreeRowComparator.java b/src/main/java/org/olat/modules/fo/ui/MessageTreeRowComparator.java new file mode 100644 index 00000000000..c91f45c2675 --- /dev/null +++ b/src/main/java/org/olat/modules/fo/ui/MessageTreeRowComparator.java @@ -0,0 +1,56 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.modules.fo.ui; + +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeNodeComparator; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTreeTableNode; + +/** + * + * Initial date: 5 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class MessageTreeRowComparator extends FlexiTreeNodeComparator { + + @Override + protected int compareNodes(FlexiTreeTableNode o1, FlexiTreeTableNode o2) { + if (o1 instanceof MessageLightViewRow && o2 instanceof MessageLightViewRow) { + MessageLightViewRow row1 = (MessageLightViewRow)o1; + MessageLightViewRow row2 = (MessageLightViewRow)o2; + return compare(row1, row2); + + } + return super.compareNodes(o1, o2); + } + + private int compare(final MessageLightViewRow m1, final MessageLightViewRow 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 + } + } + +} -- GitLab