From 959498532fdca4e875000325f3d0c4f6b30f3915 Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Mon, 5 Aug 2019 09:13:17 +0200 Subject: [PATCH] OO-4091: Mark and "new" columns in forum messages list --- .../commons/services/mark/impl/MarkImpl.java | 3 + .../services/mark/impl/ui/MarkController.java | 2 + .../services/mark/impl/ui/MarkedEvent.java | 38 +++++++ .../services/mark/impl/ui/UnmarkedEvent.java | 38 +++++++ .../course/run/preview/PreviewIdentity.java | 2 +- .../fo/_i18n/LocalStrings_de.properties | 15 ++- .../fo/_i18n/LocalStrings_en.properties | 3 + .../modules/fo/ui/ForumMessageDataModel.java | 36 +++--- .../fo/ui/ForumMessageListController.java | 106 ++++++++++++++++-- .../olat/modules/fo/ui/MessageLightView.java | 12 +- .../modules/fo/ui/MessageLightViewRow.java | 62 ++++++++++ .../modules/fo/ui/MessageListController.java | 28 +++-- .../modules/fo/ui/MessageMarkedEvent.java | 51 +++++++++ .../org/olat/modules/fo/ui/MessageView.java | 20 +--- 14 files changed, 359 insertions(+), 57 deletions(-) create mode 100644 src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java create mode 100644 src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java create mode 100644 src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java create mode 100644 src/main/java/org/olat/modules/fo/ui/MessageMarkedEvent.java diff --git a/src/main/java/org/olat/core/commons/services/mark/impl/MarkImpl.java b/src/main/java/org/olat/core/commons/services/mark/impl/MarkImpl.java index bc3081db0dd..b4725c01d61 100644 --- a/src/main/java/org/olat/core/commons/services/mark/impl/MarkImpl.java +++ b/src/main/java/org/olat/core/commons/services/mark/impl/MarkImpl.java @@ -78,6 +78,7 @@ public class MarkImpl extends PersistentObject implements Mark { this.resId = resId; } + @Override public String getResSubPath() { return resSubPath; } @@ -86,6 +87,7 @@ public class MarkImpl extends PersistentObject implements Mark { this.resSubPath = resSubPath; } + @Override public String getBusinessPath() { return businessPath; } @@ -94,6 +96,7 @@ public class MarkImpl extends PersistentObject implements Mark { this.businessPath = businessPath; } + @Override public Identity getCreator() { return creator; } 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 6be1096c3da..5214b068817 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 @@ -145,8 +145,10 @@ public class MarkController extends FormBasicController { markingService.getMarkManager().removeMark(mark); mark = null; } + fireEvent(ureq, new UnmarkedEvent()); } else { mark = markingService.getMarkManager().setMark(ores, identity, subPath, businessPath); + fireEvent(ureq, new MarkedEvent()); } 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 new file mode 100644 index 00000000000..805d02505ed --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/MarkedEvent.java @@ -0,0 +1,38 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.commons.services.mark.impl.ui; + +import org.olat.core.gui.control.Event; + +/** + * + * Initial date: 5 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class MarkedEvent extends Event { + + private static final long serialVersionUID = -4104070726631981649L; + + public MarkedEvent() { + super("marked"); + } + +} 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 new file mode 100644 index 00000000000..3fc40176532 --- /dev/null +++ b/src/main/java/org/olat/core/commons/services/mark/impl/ui/UnmarkedEvent.java @@ -0,0 +1,38 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.core.commons.services.mark.impl.ui; + +import org.olat.core.gui.control.Event; + +/** + * + * Initial date: 5 Aug 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class UnmarkedEvent extends Event { + + private static final long serialVersionUID = 3503240359856342650L; + + public UnmarkedEvent() { + super("unmarked"); + } + +} diff --git a/src/main/java/org/olat/course/run/preview/PreviewIdentity.java b/src/main/java/org/olat/course/run/preview/PreviewIdentity.java index 5bfdbd1b9df..071a1a43250 100644 --- a/src/main/java/org/olat/course/run/preview/PreviewIdentity.java +++ b/src/main/java/org/olat/course/run/preview/PreviewIdentity.java @@ -60,7 +60,7 @@ public final class PreviewIdentity implements Identity, User { } /** - * @see org.olat.core.commons.persistence.Persistable#getKey() + * @see org.olat.core.commons.persistence.Persistable#getSelectedMessageKey() */ @Override public Long getKey() { diff --git a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties index 2d634895c9d..e8c50bbff71 100644 --- a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_de.properties @@ -22,12 +22,12 @@ archive.thread.dialog=Wollen Sie dieses Diskussionsthema wirklich in Ihrem pers\ archive.thread.successfully=Das Diskussionsthema wurde in Ihrem pers\u00F6nlichen Ordner im Unterordner "private/archive" archiviert. attachments=Dateianh\u00E4nge attachments.too.big=Dateianhang ist zu gross. Es sind maximal {0} MB m\u00F6glich. -attachments.upload.successful=Die Datei {0} wurde erfolgreich hochgeladen. Bei Bedarf k\u00f6nnen noch weitere Dateien angeh\u00e4ngt werden. +attachments.upload.successful=Die Datei {0} wurde erfolgreich hochgeladen. Bei Bedarf k\u00F6nnen noch weitere Dateien angeh\u00E4ngt werden. attachments.error.file.exists=Diese Datei existiert bereits und kann nicht erneut hochgeladen werden. -attachments.remove.string=l\u00f6schen +attachments.remove.string=l\u00F6schen close.thread=Diskussion beenden -confirm.delete.pseudonym.title=Pseudonym l\u00f6schen -confirm.detele.pseudonym.msg=Wollen Sie wirklich den Pseudonym "{0}" mit {1} Forum Beitr\u00E4ge l\u00f6schen? +confirm.delete.pseudonym.title=Pseudonym l\u00F6schen +confirm.detele.pseudonym.msg=Wollen Sie wirklich den Pseudonym "{0}" mit {1} Forum Beitr\u00E4ge l\u00F6schen? create.pseudonym=Pseudonym erstellen delete.att.ok=Die Datei wurde gel\u00F6scht. deleteok=Der Beitrag wurde gel\u00F6scht @@ -110,14 +110,17 @@ remove.sticky= Entfernt Priorisierung (sticky) show.thread=Diskussion anzeigen table.closed=Beendet table.download=Tabelle downloaden -table.entries=Eintr\u00e4ge +table.entries=Eintr\u00E4ge table.entry=Eintrag +table.header.mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Favorit"> </i> +table.header.new.message=<i class\="o_icon o_forum_new_icon o_icon-lg" title\="$\:table.new.message.hover"> </i> table.header.state=Zustand table.header.typeimg=Typ table.hidden=Unsichtbar table.lastModified=Letzte \u00C4nderung table.marked=Markiert table.modified=\u00C4nderungsdatum +table.new.message.hover=Neuer Beitrag table.numOfCharacters=Zeichen table.numOfWords=W\u00F6rter table.row.new=Neu @@ -140,7 +143,7 @@ viewswitch.marked=markiert viewswitch.new=neu viewswitch.title=Beitr\u00E4ge anzeigen yes=Ja -may.not.move.message = Sie haben nicht gen\u00fcgend Berechtigungen, um diesen Beitrag zu verschieben. +may.not.move.message = Sie haben nicht gen\u00FCgend Berechtigungen, um diesen Beitrag zu verschieben. msg.move = Verschieben in anderes Thema msg.exile=Verschieben in anderes Forum msg.moved = Dieser Beitrag wurde aus einem anderen Thema hierhin verschoben. diff --git a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties index ebd9f691d7e..7cd154ccd0b 100644 --- a/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/fo/_i18n/LocalStrings_en.properties @@ -117,12 +117,15 @@ table.closed=Completed table.download=Download table table.entries=Entries table.entry=Entry +table.header.mark=<i class\="o_icon o_icon_bookmark_header o_icon-lg" title\="Favorit"> </i> +table.header.new.message=<i class\="o_icon o_forum_new_icon" title\="$\:table.new.message.hover"> </i> table.header.state=Status table.header.typeimg=Type table.hidden=Invisible table.lastModified=Last modified table.marked=Marked table.modified=Modified at +table.new.message.hover=New post table.numOfCharacters=Characters table.numOfWords=Words table.row.new=New 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 5cac682540a..eab2a128e4e 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageDataModel.java @@ -38,8 +38,8 @@ import org.olat.group.ui.main.AbstractMemberListController; * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ -public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLightView> - implements SortableFlexiTableDataModel<MessageLightView> { +public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLightViewRow> + implements SortableFlexiTableDataModel<MessageLightViewRow> { private Translator translator; @@ -54,7 +54,7 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig if("natural".equals(orderBy.getKey())) { //System.out.println(); } else { - List<MessageLightView> views = new ForumMessageDataModelSort(orderBy, this, null).sort(); + List<MessageLightViewRow> views = new ForumMessageDataModelSort(orderBy, this, null).sort(); super.setObjects(views); } } @@ -62,40 +62,44 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig @Override public Object getValueAt(int row, int col) { - MessageLightView view = getObject(row); + MessageLightViewRow view = getObject(row); return getValueAt(view, col); } @Override - public Object getValueAt(MessageLightView row, int col) { + public Object getValueAt(MessageLightViewRow row, int col) { if(col >= 0 && col < ForumMessageCols.values().length) { switch(ForumMessageCols.values()[col]) { - case type: return row.getStatusCode(); - case thread: return StringHelper.escapeHtml(row.getTitle()); - case lastModified: return row.getLastModified(); + case type: return row.getView().getStatusCode(); + case mark: return row.getMarkLink(); + case thread: return StringHelper.escapeHtml(row.getView().getTitle()); + case lastModified: return row.getView().getLastModified(); + case newMessage: return row.getView().isNewMessage()? Boolean.TRUE: null; default: return "ERROR"; } } int propPos = col - AbstractMemberListController.USER_PROPS_OFFSET; - if(StringHelper.containsNonWhitespace(row.getPseudonym())) { - return propPos == 0 ? row.getPseudonym() : null; + if(StringHelper.containsNonWhitespace(row.getView().getPseudonym())) { + return propPos == 0 ? row.getView().getPseudonym() : null; } - if(row.isGuest()) { + if(row.getView().isGuest()) { return propPos == 0 ? translator.translate("guest") : null; } - return row.getIdentityProp(propPos); + return row.getView().getIdentityProp(propPos); } @Override - public DefaultFlexiTableDataModel<MessageLightView> createCopyWithEmptyList() { + public DefaultFlexiTableDataModel<MessageLightViewRow> createCopyWithEmptyList() { return new ForumMessageDataModel(getTableColumnModel(), translator); } public enum ForumMessageCols implements FlexiSortableColumnDef { type("table.header.typeimg"), + mark("table.header.mark"), thread("table.thread"), - lastModified("table.lastModified"); + lastModified("table.lastModified"), + newMessage("table.header.new.message"); private final String i18nKey; @@ -119,9 +123,9 @@ public class ForumMessageDataModel extends DefaultFlexiTableDataModel<MessageLig } } - public class ForumMessageDataModelSort extends SortableFlexiTableModelDelegate<MessageLightView> { + public class ForumMessageDataModelSort extends SortableFlexiTableModelDelegate<MessageLightViewRow> { - public ForumMessageDataModelSort(SortKey orderBy, SortableFlexiTableDataModel<MessageLightView> tableModel, Locale locale) { + public ForumMessageDataModelSort(SortKey orderBy, SortableFlexiTableDataModel<MessageLightViewRow> tableModel, Locale locale) { super(orderBy, tableModel, locale); } } 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 1d86d5168a5..d3851ac74e3 100644 --- a/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/ForumMessageListController.java @@ -27,18 +27,23 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import org.olat.basesecurity.BaseSecurityModule; +import org.olat.core.commons.services.mark.Mark; +import org.olat.core.commons.services.mark.MarkingService; 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.elements.FlexiTableSort; import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions; +import org.olat.core.gui.components.form.flexible.elements.FormLink; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; 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.DefaultFlexiTableCssDelegate; +import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; @@ -46,10 +51,14 @@ 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.link.Link; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; +import org.olat.core.id.OLATResourceable; import org.olat.core.id.UserConstants; import org.olat.core.util.Util; +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; @@ -77,7 +86,11 @@ public class ForumMessageListController extends FormBasicController { private final Forum forum; private final boolean withType; + private final boolean showMarks; + private final boolean showNew; + private final boolean guestOnly; private final boolean isAdministrativeUser; + private final OLATResourceable forumOres; private final List<UserPropertyHandler> userPropertyHandlers; private MessageView userObject, selectView; @@ -86,16 +99,22 @@ public class ForumMessageListController extends FormBasicController { @Autowired private ForumManager forumManager; @Autowired + private MarkingService markingService; + @Autowired private BaseSecurityModule securityModule; public ForumMessageListController(UserRequest ureq, WindowControl wControl, - Forum forum, boolean withType) { + 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); @@ -120,15 +139,21 @@ public class ForumMessageListController extends FormBasicController { } public void loadAllMessages() { + 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) { MessageLightView view = new MessageLightView(message, userPropertyHandlers, getLocale()); + if (readSet.contains(message.getKey())) { + view.setNewMessage(false); + } else { + view.setNewMessage(true); + } views.add(view); keyToViews.put(view.getKey(), view); } - + //calculate depth Map<Long, List<Long>> keyToParentline = new HashMap<>(); for(MessageLightView view:views) { @@ -150,15 +175,40 @@ public class ForumMessageListController extends FormBasicController { Collections.sort(threads, new MessageNodeComparator()); List<MessageLightView> orderedViews = new ArrayList<>(allMessages.size()); flatTree(threads, orderedViews); - dataModel.setObjects(orderedViews); + List<MessageLightViewRow> rows = appendLinks(orderedViews); + dataModel.setObjects(rows); } public void loadMessages(List<MessageLightView> views) { - dataModel.setObjects(views); + List<MessageLightViewRow> rows = appendLinks(views); + dataModel.setObjects(rows); tableEl.reloadData(); tableEl.reset(); } + private List<MessageLightViewRow> appendLinks(List<MessageLightView> views) { + List<Mark> markList = !guestOnly + ? markingService.getMarkManager().getMarks(forumOres, getIdentity(), null) + : Collections.emptyList(); + Map<String,Mark> marks = new HashMap<>(); + for (Mark mark : markList) { + marks.put(mark.getResSubPath(), mark); + } + + List<MessageLightViewRow> rows = new ArrayList<>(views.size()); + 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); + + MessageLightViewRow row = new MessageLightViewRow(view, mark, markLink); + markLink.setUserObject(row); + rows.add(row); + } + return rows; + } + @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { List<FlexiTableSort> sorts = new ArrayList<>(); @@ -169,6 +219,11 @@ public class ForumMessageListController extends FormBasicController { 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()))); sorts.add(new FlexiTableSort(translate(ForumMessageCols.thread.i18nHeaderKey()), ForumMessageCols.thread.name())); @@ -196,6 +251,12 @@ public class ForumMessageListController extends FormBasicController { columnsModel.addFlexiColumnModel(new DefaultFlexiColumnModel(ForumMessageCols.lastModified)); sorts.add(new FlexiTableSort(translate(ForumMessageCols.lastModified.i18nHeaderKey()), ForumMessageCols.lastModified.name())); + 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)); + } + dataModel = new ForumMessageDataModel(columnsModel, getTranslator()); tableEl = uifactory.addTableElement(getWindowControl(), "messages", dataModel, getTranslator(), formLayout); tableEl.setCssDelegate(new MessageCssDelegate()); @@ -223,14 +284,45 @@ public class ForumMessageListController extends FormBasicController { SelectionEvent se = (SelectionEvent)event; String cmd = se.getCommand(); if("select".equals(cmd)) { - MessageLightView message = dataModel.getObject(se.getIndex()); + 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; + 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())); + } } super.formInnerEvent(ureq, source, event); } - + + private void doMark(MessageLightViewRow row) { + MessageLightView view = row.getView(); + Mark currentMark = row.getMark(); + String businessPath = currentMark == null ? + getWindowControl().getBusinessControl().getAsString() + "[Message:" + view.getKey() + "]" + : currentMark.getBusinessPath(); + Mark mark = markingService.getMarkManager().setMark(forumOres, getIdentity(), view.getKey().toString(), businessPath); + row.setMark(mark); + } + + private void doUnmark(MessageLightViewRow row) { + MessageLightView view = row.getView(); + markingService.getMarkManager().removeMark(forumOres, getIdentity(), view.getKey().toString()); + row.setMark(null); + } + private void flatTree(List<MessageNode> nodes, List<MessageLightView> orderedViews) { for(MessageNode node:nodes) { orderedViews.add(node.getView()); @@ -269,7 +361,7 @@ public class ForumMessageListController extends FormBasicController { private class MessageCssDelegate extends DefaultFlexiTableCssDelegate { @Override public String getRowCssClass(FlexiTableRendererType type, int pos) { - MessageLightView row = dataModel.getObject(pos); + MessageLightView row = dataModel.getObject(pos).getView(); return row != null && selectView != null && row.getKey().equals(selectView.getKey()) ? "o_row_selected" : null; } } diff --git a/src/main/java/org/olat/modules/fo/ui/MessageLightView.java b/src/main/java/org/olat/modules/fo/ui/MessageLightView.java index ba4d21a3714..016f7495ebf 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageLightView.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageLightView.java @@ -48,9 +48,11 @@ public class MessageLightView extends UserPropertiesRow implements MessageRef { private final Long threadtopKey; - private int depth; + private int depth = -1; private int numOfChildren = 0; + private boolean newMessage; + public MessageLightView(MessageLight message, List<UserPropertyHandler> userPropertyHandlers, Locale locale) { super(message.getCreator(), userPropertyHandlers, locale); key = message.getKey(); @@ -120,4 +122,12 @@ public class MessageLightView extends UserPropertiesRow implements MessageRef { public boolean isThreadTop() { return threadtopKey != null; } + + public boolean isNewMessage() { + return newMessage; + } + + public void setNewMessage(boolean newMessage) { + this.newMessage = newMessage; + } } diff --git a/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java b/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java new file mode 100644 index 00000000000..beaa850b8cc --- /dev/null +++ b/src/main/java/org/olat/modules/fo/ui/MessageLightViewRow.java @@ -0,0 +1,62 @@ +/** + * <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.services.mark.Mark; +import org.olat.core.gui.components.form.flexible.elements.FormLink; + +/** + * + * Initial date: 31 Jul 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class MessageLightViewRow { + + private final MessageLightView view; + private Mark mark; + private final FormLink markLink; + + public MessageLightViewRow(MessageLightView view, Mark mark, FormLink markLink) { + this.view = view; + this.mark = mark; + this.markLink = markLink; + } + + public MessageLightView getView() { + return view; + } + + public void setMark(Mark mark) { + this.mark = mark; + } + + public Mark getMark() { + return mark; + } + + public boolean isMarked() { + return mark != null; + } + + public FormLink getMarkLink() { + return markLink; + } +} 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 453cb2fd2ad..f5cb5726be3 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageListController.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageListController.java @@ -35,6 +35,8 @@ import org.olat.core.commons.persistence.DBFactory; import org.olat.core.commons.services.mark.Mark; import org.olat.core.commons.services.mark.MarkResourceStat; import org.olat.core.commons.services.mark.MarkingService; +import org.olat.core.commons.services.mark.impl.ui.MarkedEvent; +import org.olat.core.commons.services.mark.impl.ui.UnmarkedEvent; import org.olat.core.commons.services.vfs.VFSMetadata; import org.olat.core.commons.services.vfs.VFSRepositoryService; import org.olat.core.dispatcher.mapper.Mapper; @@ -207,7 +209,7 @@ public class MessageListController extends BasicController implements GenericEve mainVC.contextPut("thumbMapper", thumbnailMapper); mainVC.contextPut("guestOnly", new Boolean(guestOnly)); - messageTableCtrl = new ForumMessageListController(ureq, getWindowControl(), forum, false); + messageTableCtrl = new ForumMessageListController(ureq, getWindowControl(), forum, false, true, true); listenTo(messageTableCtrl); mainVC.put("singleThreadTable", messageTableCtrl.getInitialComponent()); @@ -522,9 +524,7 @@ public class MessageListController extends BasicController implements GenericEve if (messages == null || orderedList == null || startMessage == null) return; Map<Long, MessageNode> messagesMap = new HashMap<>(); - if(startMessage != null) { - messagesMap.put(startMessage.getKey(), new MessageNode(startMessage)); - } + messagesMap.put(startMessage.getKey(), new MessageNode(startMessage)); for(MessageLight message:messages) { if(message.getParentKey() != null) { messagesMap.put(message.getKey(), new MessageNode(message)); @@ -708,6 +708,7 @@ public class MessageListController extends BasicController implements GenericEve getWindowControl().getBusinessControl().getAsString() + "[Message:" + m.getKey() + "]" : currentMark.getBusinessPath(); Controller markCtrl = markingService.getMarkController(ureq, getWindowControl(), currentMark, stat, forumOres, keyString, businessPath); + listenTo(markCtrl); mainVC.put("mark_".concat(keyString), markCtrl.getInitialComponent()); } @@ -896,6 +897,10 @@ public class MessageListController extends BasicController implements GenericEve if(event instanceof SelectMessageEvent) { SelectMessageEvent sme = (SelectMessageEvent)event; doSelectTheOne(ureq, sme.getMessageKey()); + } else if (event instanceof MessageMarkedEvent) { + MessageMarkedEvent mme = (MessageMarkedEvent) event; + Message message = forumManager.getMessageById(mme.getSelectedMessageKey()); + reloadModel(ureq, message); } } else if(moveCtrl == source) { if(event instanceof SelectMessageEvent) { @@ -908,6 +913,8 @@ 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(source == cmc) { cleanUp(); } @@ -947,7 +954,7 @@ public class MessageListController extends BasicController implements GenericEve } String reString = ""; - if(parent != null && parent.isThreadTop()) { + if(parent.isThreadTop()) { //add reString only for the first answer reString = translate("msg.title.re"); } @@ -1242,7 +1249,7 @@ public class MessageListController extends BasicController implements GenericEve case VIEWMODE_MESSAGE: doShowOne(ureq); break; default: doShowAll(ureq); } - return viewSettings == null ? VIEWMODE_THREAD : viewSettings; + return viewSettings; } private void doShowAll(UserRequest ureq) { @@ -1281,6 +1288,13 @@ public class MessageListController extends BasicController implements GenericEve messageTableCtrl.loadMessages(new ArrayList<>(backupViews)); } } + + 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(); @@ -1369,7 +1383,7 @@ public class MessageListController extends BasicController implements GenericEve removeAsListenerAndDispose(cmc); if (foCallback.mayEditMessageAsModerator()) { - moveCtrl = new ForumMessageListController(ureq, getWindowControl(), forum, true); + moveCtrl = new ForumMessageListController(ureq, getWindowControl(), forum, true, false, false); moveCtrl.loadAllMessages(); moveCtrl.setSelectView(message); listenTo(moveCtrl); diff --git a/src/main/java/org/olat/modules/fo/ui/MessageMarkedEvent.java b/src/main/java/org/olat/modules/fo/ui/MessageMarkedEvent.java new file mode 100644 index 00000000000..5c9905a7fe0 --- /dev/null +++ b/src/main/java/org/olat/modules/fo/ui/MessageMarkedEvent.java @@ -0,0 +1,51 @@ +/** + * <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.control.Event; + +/** + * + * Initial date: 31 Jul 2019<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class MessageMarkedEvent extends Event { + + private static final long serialVersionUID = -5957284132557840893L; + + private final Long selectedMessageKey; + private final Long markedMessageKey; + + public MessageMarkedEvent(Long selectedMessageKey, Long markedMessageKey) { + super("message-maked"); + this.selectedMessageKey = selectedMessageKey; + this.markedMessageKey = markedMessageKey; + } + + public Long getSelectedMessageKey() { + return selectedMessageKey; + } + + public Long getMarkedMessageKey() { + return markedMessageKey; + } + +} diff --git a/src/main/java/org/olat/modules/fo/ui/MessageView.java b/src/main/java/org/olat/modules/fo/ui/MessageView.java index 55d307d3869..7848a3dc4cd 100644 --- a/src/main/java/org/olat/modules/fo/ui/MessageView.java +++ b/src/main/java/org/olat/modules/fo/ui/MessageView.java @@ -54,10 +54,7 @@ public class MessageView extends MessageLightView { private boolean threadTop; private boolean closed; private boolean moved; - - private int depth = -1; - private boolean newMessage; private List<VFSItem> attachments; private VFSContainer messageContainer; @@ -89,14 +86,6 @@ public class MessageView extends MessageLightView { this.formattedLastModified = formattedLastModified; } - public boolean isNewMessage() { - return newMessage; - } - - public void setNewMessage(boolean newMessage) { - this.newMessage = newMessage; - } - public String getCreatorFirstname() { return creatorFirstname; } @@ -112,14 +101,6 @@ public class MessageView extends MessageLightView { public void setCreatorLastname(String creatorLastname) { this.creatorLastname = creatorLastname; } - - public int getDepth() { - return depth; - } - - public void setDepth(int depth) { - this.depth = depth; - } public boolean isMoved() { return moved; @@ -169,6 +150,7 @@ public class MessageView extends MessageLightView { this.author = author; } + @Override public boolean isThreadTop() { return threadTop; } -- GitLab