From 27204cba5e9088e33cf0ff5b9baaaf478f6c384a Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Tue, 18 Mar 2025 15:58:27 +0100 Subject: [PATCH] Start of the big epic refactor The end purpose is to enable removal of entire threads. Previous attempts have failed, all because of something JPA/Hibernate related such as not-null constraint, transient/detached entities, or something else. The approach is to get rid of @Entitys throughout the system and use data transfer objects (DTOs) and to make the thread more of a central concept rather than an empty container with an "initial" post. This should allow a more dedicated "delete thread" method that can take care of all the issues instead of "is this the last post then do extra steps" which is causing the problems. Changing to DTOs will also align better with the technical future that the current developers want and have decided on "Never return @Entity classes from services" (https://gitea.dsv.su.se/DMC/scipro/wiki/Technical-future). --- .../dsv/scipro/forum/GroupForumService.java | 2 + .../scipro/forum/GroupForumServiceImpl.java | 5 ++ .../dsv/scipro/forum/IndexedForumService.java | 12 ++++ .../dsv/scipro/forum/ProjectForumService.java | 2 + .../scipro/forum/ProjectForumServiceImpl.java | 5 ++ .../su/dsv/scipro/forum/ThreadOverview.java | 15 ++++ .../se/su/dsv/scipro/forum/Discussable.java | 9 --- .../threaded/ForumThreadDiscussable.java | 15 ---- .../threaded/ProjectThreadedForumPage.java | 17 ++--- .../threaded/SupervisorThreadedForumPage.java | 22 ++---- .../panels/threaded/ThreadReadStatePanel.java | 18 +++-- .../panels/threaded/ThreadsOverviewPanel.java | 68 ++++++------------- .../su/dsv/scipro/group/AuthorGroupPage.java | 22 ++---- .../scipro/group/GroupThreadDiscussable.java | 14 ---- .../supervisor/pages/SupervisorGroupPage.java | 23 ++----- .../java/se/su/dsv/scipro/SciProTest.java | 4 ++ .../threaded/ThreadReadStatePanelTest.java | 21 +++--- .../threaded/ThreadsOverviewPanelTest.java | 30 +++----- 18 files changed, 109 insertions(+), 195 deletions(-) create mode 100644 core/src/main/java/se/su/dsv/scipro/forum/IndexedForumService.java create mode 100644 core/src/main/java/se/su/dsv/scipro/forum/ThreadOverview.java delete mode 100644 view/src/main/java/se/su/dsv/scipro/forum/Discussable.java delete mode 100644 view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ForumThreadDiscussable.java delete mode 100644 view/src/main/java/se/su/dsv/scipro/group/GroupThreadDiscussable.java diff --git a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumService.java b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumService.java index 5d43341f3c..158c241ee2 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumService.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumService.java @@ -18,4 +18,6 @@ public interface GroupForumService { ForumPost createReply(GroupThread groupThread, User poster, String content, Set<Attachment> attachments); List<ForumPost> getPosts(GroupThread groupThread); + + IndexedForumService getForumService(Group group); } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java index 00c48751cd..092fa0820b 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/GroupForumServiceImpl.java @@ -81,4 +81,9 @@ public class GroupForumServiceImpl implements GroupForumService { public List<ForumPost> getPosts(final GroupThread groupThread) { return basicForumService.getPosts(groupThread.getForumThread()); } + + @Override + public IndexedForumService getForumService(Group group) { + return null; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/IndexedForumService.java b/core/src/main/java/se/su/dsv/scipro/forum/IndexedForumService.java new file mode 100644 index 0000000000..53c6b2c2fd --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/forum/IndexedForumService.java @@ -0,0 +1,12 @@ +package se.su.dsv.scipro.forum; + +import java.util.List; +import se.su.dsv.scipro.system.User; + +public interface IndexedForumService { + List<ThreadOverview> getThreads(); + + boolean isThreadRead(User user, Long threadId); + + void setThreadRead(User user, Long threadId, boolean read); +} diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java index 9269f37f49..0adc4a2402 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumService.java @@ -28,4 +28,6 @@ public interface ProjectForumService { boolean canDelete(ProjectThread projectThread, ForumPost forumPost); void deletePost(ProjectThread projectThread, ForumPost forumPost); + + IndexedForumService getForumService(Project project); } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java index 5850bffdc0..3c8bdbca4f 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java @@ -139,4 +139,9 @@ public class ProjectForumServiceImpl implements ProjectForumService { public ProjectThread findOne(long threadId) { return projectThreadRepository.findOne(threadId); } + + @Override + public IndexedForumService getForumService(Project project) { + return null; + } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ThreadOverview.java b/core/src/main/java/se/su/dsv/scipro/forum/ThreadOverview.java new file mode 100644 index 0000000000..ba73dddde2 --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/forum/ThreadOverview.java @@ -0,0 +1,15 @@ +package se.su.dsv.scipro.forum; + +import java.time.Instant; +import se.su.dsv.scipro.forum.dataobjects.ForumPost; +import se.su.dsv.scipro.system.User; + +public record ThreadOverview( + Long id, + boolean hasAttachments, + String subject, + User author, + Instant createdAt, + int numberOfReplies, + ForumPost latestPost +) {} diff --git a/view/src/main/java/se/su/dsv/scipro/forum/Discussable.java b/view/src/main/java/se/su/dsv/scipro/forum/Discussable.java deleted file mode 100644 index d6f69b8780..0000000000 --- a/view/src/main/java/se/su/dsv/scipro/forum/Discussable.java +++ /dev/null @@ -1,9 +0,0 @@ -package se.su.dsv.scipro.forum; - -import org.apache.wicket.model.IModel; -import org.apache.wicket.util.io.IClusterable; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; - -public interface Discussable<A> extends IClusterable { - IModel<ForumThread> discussion(IModel<A> a); -} diff --git a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ForumThreadDiscussable.java b/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ForumThreadDiscussable.java deleted file mode 100644 index 170bdddb5f..0000000000 --- a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ForumThreadDiscussable.java +++ /dev/null @@ -1,15 +0,0 @@ -package se.su.dsv.scipro.forum.pages.threaded; - -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; -import se.su.dsv.scipro.forum.Discussable; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; -import se.su.dsv.scipro.forum.dataobjects.ProjectThread; - -public class ForumThreadDiscussable implements Discussable<ProjectThread> { - - @Override - public IModel<ForumThread> discussion(final IModel<ProjectThread> a) { - return LambdaModel.of(a, ProjectThread::getForumThread, ProjectThread::setForumThread); - } -} diff --git a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ProjectThreadedForumPage.java b/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ProjectThreadedForumPage.java index e42a52aaed..49083cdda8 100644 --- a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ProjectThreadedForumPage.java +++ b/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/ProjectThreadedForumPage.java @@ -11,6 +11,7 @@ import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAuthorMyProjects; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightForum; +import se.su.dsv.scipro.forum.IndexedForumService; import se.su.dsv.scipro.forum.ProjectForumService; import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; @@ -34,29 +35,19 @@ public class ProjectThreadedForumPage public ProjectThreadedForumPage(final PageParameters pp) { super(pp); add(new BookmarkablePageLink<Void>(CREATE_THREAD_LINK, ProjectCreateForumThreadPage.class, pp)); + IModel<IndexedForumService> forumService = projectModel.map(projectForumService::getForumService); add(new FeedbackPanel(FEEDBACK)); add( - new ThreadsOverviewPanel<>(FORUM, getThreads(), new ForumThreadDiscussable(), (id, thread) -> { + new ThreadsOverviewPanel(FORUM, forumService, (id, thread) -> { PageParameters parameters = new PageParameters(pp).set( PageParameterKeys.MAP.get(ForumThread.class), - thread.getObject().getId() + thread.getObject().id() ); return new BookmarkablePageLink<>(id, ProjectViewForumThreadPage.class, parameters); }) ); } - private IModel<List<ProjectThread>> getThreads() { - return new LoadableDetachableModel<>() { - @Override - protected List<ProjectThread> load() { - List<ProjectThread> threads = projectForumService.getThreads(projectModel.getObject()); - threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified()))); - return threads; - } - }; - } - static final String CREATE_THREAD_LINK = "createThread"; static final String FEEDBACK = "feedback"; static final String FORUM = "forum"; diff --git a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/SupervisorThreadedForumPage.java b/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/SupervisorThreadedForumPage.java index ffbf9664d9..41f82c8270 100644 --- a/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/SupervisorThreadedForumPage.java +++ b/view/src/main/java/se/su/dsv/scipro/forum/pages/threaded/SupervisorThreadedForumPage.java @@ -3,19 +3,15 @@ package se.su.dsv.scipro.forum.pages.threaded; import static se.su.dsv.scipro.security.auth.roles.Roles.SUPERVISOR; import jakarta.inject.Inject; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightForum; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightSupervisorMyProjects; +import se.su.dsv.scipro.forum.IndexedForumService; import se.su.dsv.scipro.forum.ProjectForumService; import se.su.dsv.scipro.forum.dataobjects.ForumThread; -import se.su.dsv.scipro.forum.dataobjects.ProjectThread; import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel; import se.su.dsv.scipro.security.auth.Authorization; import se.su.dsv.scipro.security.auth.ProjectModuleComponent; @@ -36,28 +32,18 @@ public class SupervisorThreadedForumPage super(pp); add(new BookmarkablePageLink<Void>(CREATE_THREAD_LINK, SupervisorCreateForumThreadPage.class, pp)); add(new FeedbackPanel(FEEDBACK)); + IModel<IndexedForumService> forumService = projectModel.map(projectForumService::getForumService); add( - new ThreadsOverviewPanel<>(FORUM, getThreads(), new ForumThreadDiscussable(), (id, thread) -> { + new ThreadsOverviewPanel(FORUM, forumService, (id, thread) -> { PageParameters parameters = new PageParameters(pp).set( PageParameterKeys.MAP.get(ForumThread.class), - thread.getObject().getId() + thread.getObject().id() ); return new BookmarkablePageLink<>(id, SupervisorViewForumThreadPage.class, parameters); }) ); } - private IModel<List<ProjectThread>> getThreads() { - return new LoadableDetachableModel<>() { - @Override - protected List<ProjectThread> load() { - List<ProjectThread> threads = projectForumService.getThreads(projectModel.getObject()); - threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified()))); - return threads; - } - }; - } - static final String CREATE_THREAD_LINK = "createThread"; static final String FEEDBACK = "feedback"; static final String FORUM = "forum"; diff --git a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java index 482b3e601c..422b39851b 100644 --- a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java +++ b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanel.java @@ -1,10 +1,9 @@ package se.su.dsv.scipro.forum.panels.threaded; -import jakarta.inject.Inject; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.model.IModel; -import se.su.dsv.scipro.forum.BasicForumService; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; +import se.su.dsv.scipro.forum.IndexedForumService; +import se.su.dsv.scipro.forum.ThreadOverview; import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel; import se.su.dsv.scipro.session.SciProSession; @@ -14,24 +13,23 @@ import se.su.dsv.scipro.session.SciProSession; */ public class ThreadReadStatePanel extends AbstractReadStatePanel { - @Inject - private BasicForumService basicForumService; + private final IModel<IndexedForumService> forumService; + private final IModel<ThreadOverview> model; - private final IModel<ForumThread> model; - - public ThreadReadStatePanel(String id, IModel<ForumThread> model) { + public ThreadReadStatePanel(String id, IModel<IndexedForumService> forumService, IModel<ThreadOverview> model) { super(id); + this.forumService = forumService; this.model = model; } @Override protected boolean isRead() { - return basicForumService.isThreadRead(SciProSession.get().getUser(), model.getObject()); + return forumService.getObject().isThreadRead(SciProSession.get().getUser(), model.getObject().id()); } @Override protected void onFlagClick(final AjaxRequestTarget target) { boolean read = isRead(); - basicForumService.setThreadRead(SciProSession.get().getUser(), model.getObject(), !read); + forumService.getObject().setThreadRead(SciProSession.get().getUser(), model.getObject().id(), !read); } } diff --git a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanel.java b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanel.java index d0e7e1c55d..46dc4ae154 100644 --- a/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanel.java @@ -1,8 +1,6 @@ package se.su.dsv.scipro.forum.panels.threaded; -import jakarta.inject.Inject; import java.io.Serializable; -import java.util.List; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; @@ -11,46 +9,39 @@ import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LambdaModel; -import org.apache.wicket.model.LoadableDetachableModel; import se.su.dsv.scipro.components.DateLabel; import se.su.dsv.scipro.data.enums.DateStyle; -import se.su.dsv.scipro.forum.BasicForumService; -import se.su.dsv.scipro.forum.Discussable; +import se.su.dsv.scipro.forum.IndexedForumService; +import se.su.dsv.scipro.forum.ThreadOverview; import se.su.dsv.scipro.forum.dataobjects.ForumPost; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.profile.UserLinkPanel; import se.su.dsv.scipro.system.User; -public class ThreadsOverviewPanel<A> extends Panel { - - @Inject - private BasicForumService basicForumService; +public class ThreadsOverviewPanel extends Panel { public ThreadsOverviewPanel( final String id, - final IModel<List<A>> model, - final Discussable<A> discussable, - final ThreadLinkSupplier<A> threadLinkSupplier + final IModel<IndexedForumService> forumService, + final ThreadLinkSupplier threadLinkSupplier ) { - super(id, model); + super(id, forumService); add( - new ListView<>("threads", model) { + new ListView<>("threads", forumService.map(IndexedForumService::getThreads)) { @Override - protected void populateItem(final ListItem<A> item) { - final IModel<ForumThread> discussion = discussable.discussion(item.getModel()); - item.add(new ThreadReadStatePanel("readState", discussion)); + protected void populateItem(final ListItem<ThreadOverview> item) { + item.add(new ThreadReadStatePanel("readState", forumService, item.getModel())); item.add( new WebMarkupContainer("attachmentIcon") { @Override protected void onConfigure() { super.onConfigure(); - setVisibilityAllowed(basicForumService.hasAttachments(discussion.getObject())); + setVisibilityAllowed(item.getModelObject().hasAttachments()); } } ); - item.add(new ThreadTitleColumn<>("threadTitle", discussion, item.getModel(), threadLinkSupplier)); - item.add(new Label("replies", discussion.map(ForumThread::getPostCount))); - item.add(new LastPostColumn("lastPost", discussion)); + item.add(new ThreadTitleColumn<>("threadTitle", item.getModel(), threadLinkSupplier)); + item.add(new Label("replies", item.getModel().map(ThreadOverview::numberOfReplies))); + item.add(new LastPostColumn("lastPost", item.getModel().map(ThreadOverview::latestPost))); } } ); @@ -60,34 +51,26 @@ public class ThreadsOverviewPanel<A> extends Panel { public ThreadTitleColumn( final String id, - final IModel<ForumThread> thread, - final IModel<A> model, - final ThreadLinkSupplier<A> threadLinkSupplier + final IModel<ThreadOverview> model, + final ThreadLinkSupplier threadLinkSupplier ) { super(id); final BookmarkablePageLink<Void> threadLink = threadLinkSupplier.newThreadLink("threadLink", model); - threadLink.setBody(LambdaModel.of(thread, ForumThread::getSubject, ForumThread::setSubject)); + threadLink.setBody(model.map(ThreadOverview::subject)); add(threadLink); - add(new Label("createdBy", thread.map(ForumThread::getCreatedBy).map(User::getFullName).orElse("SciPro"))); - add( - new DateLabel( - "dateCreated", - LambdaModel.of(thread, ForumThread::getDateCreated, ForumThread::setDateCreated), - DateStyle.DATETIME - ) - ); + add(new Label("createdBy", model.map(ThreadOverview::author).map(User::getFullName).orElse("SciPro"))); + add(new Label("dateCreated", model.map(ThreadOverview::createdAt))); } } - public interface ThreadLinkSupplier<A> extends Serializable { - BookmarkablePageLink<Void> newThreadLink(String id, IModel<A> thread); + public interface ThreadLinkSupplier extends Serializable { + BookmarkablePageLink<Void> newThreadLink(String id, IModel<ThreadOverview> thread); } private class LastPostColumn extends WebMarkupContainer { - public LastPostColumn(String id, final IModel<ForumThread> model) { + public LastPostColumn(String id, final IModel<ForumPost> postModel) { super(id); - IModel<ForumPost> postModel = getLastPost(model); add( new UserLinkPanel("postedBy", LambdaModel.of(postModel, ForumPost::getPostedBy, ForumPost::setPostedBy)) ); @@ -108,14 +91,5 @@ public class ThreadsOverviewPanel<A> extends Panel { ) ); } - - private IModel<ForumPost> getLastPost(final IModel<ForumThread> model) { - return new LoadableDetachableModel<>() { - @Override - protected ForumPost load() { - return basicForumService.getLastPost(model.getObject()); - } - }; - } } } diff --git a/view/src/main/java/se/su/dsv/scipro/group/AuthorGroupPage.java b/view/src/main/java/se/su/dsv/scipro/group/AuthorGroupPage.java index cfcac3c98d..31ac2335c8 100644 --- a/view/src/main/java/se/su/dsv/scipro/group/AuthorGroupPage.java +++ b/view/src/main/java/se/su/dsv/scipro/group/AuthorGroupPage.java @@ -1,18 +1,14 @@ package se.su.dsv.scipro.group; import jakarta.inject.Inject; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAuthorMyGroups; import se.su.dsv.scipro.forum.GroupForumService; +import se.su.dsv.scipro.forum.IndexedForumService; import se.su.dsv.scipro.forum.dataobjects.ForumThread; -import se.su.dsv.scipro.forum.dataobjects.GroupThread; import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel; import se.su.dsv.scipro.util.PageParameterKeys; @@ -25,25 +21,15 @@ public class AuthorGroupPage extends AbstractAuthorGroupPage implements MenuHigh super(pp); add(new FeedbackPanel("feedback")); add(new BookmarkablePageLink<Void>("createThread", CreateThreadPage.class, pp)); + IModel<IndexedForumService> forumService = getGroup().map(groupForumService::getForumService); add( - new ThreadsOverviewPanel<>("threads", getThreads(), new GroupThreadDiscussable(), (id, thread) -> { + new ThreadsOverviewPanel("threads", forumService, (id, thread) -> { PageParameters parameters = new PageParameters(pp).set( PageParameterKeys.MAP.get(ForumThread.class), - thread.getObject().getId() + thread.getObject().id() ); return new BookmarkablePageLink<>(id, ViewThreadPage.class, parameters); }) ); } - - private IModel<List<GroupThread>> getThreads() { - return new LoadableDetachableModel<>() { - @Override - protected List<GroupThread> load() { - List<GroupThread> threads = groupForumService.getThreads(getGroup().getObject()); - threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified()))); - return threads; - } - }; - } } diff --git a/view/src/main/java/se/su/dsv/scipro/group/GroupThreadDiscussable.java b/view/src/main/java/se/su/dsv/scipro/group/GroupThreadDiscussable.java deleted file mode 100644 index bbc44715b7..0000000000 --- a/view/src/main/java/se/su/dsv/scipro/group/GroupThreadDiscussable.java +++ /dev/null @@ -1,14 +0,0 @@ -package se.su.dsv.scipro.group; - -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LambdaModel; -import se.su.dsv.scipro.forum.Discussable; -import se.su.dsv.scipro.forum.dataobjects.*; - -public class GroupThreadDiscussable implements Discussable<GroupThread> { - - @Override - public IModel<ForumThread> discussion(final IModel<GroupThread> a) { - return LambdaModel.of(a, GroupThread::getForumThread, GroupThread::setForumThread); - } -} diff --git a/view/src/main/java/se/su/dsv/scipro/supervisor/pages/SupervisorGroupPage.java b/view/src/main/java/se/su/dsv/scipro/supervisor/pages/SupervisorGroupPage.java index 4307836a19..616c6e0b92 100644 --- a/view/src/main/java/se/su/dsv/scipro/supervisor/pages/SupervisorGroupPage.java +++ b/view/src/main/java/se/su/dsv/scipro/supervisor/pages/SupervisorGroupPage.java @@ -1,20 +1,15 @@ package se.su.dsv.scipro.supervisor.pages; import jakarta.inject.Inject; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.model.IModel; -import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.request.mapper.parameter.PageParameters; import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightSupervisorMyGroups; import se.su.dsv.scipro.forum.GroupForumService; +import se.su.dsv.scipro.forum.IndexedForumService; import se.su.dsv.scipro.forum.dataobjects.ForumThread; -import se.su.dsv.scipro.forum.dataobjects.GroupThread; import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel; -import se.su.dsv.scipro.group.GroupThreadDiscussable; import se.su.dsv.scipro.util.PageParameterKeys; public class SupervisorGroupPage extends AbstractSupervisorGroupPage implements MenuHighlightSupervisorMyGroups { @@ -26,25 +21,15 @@ public class SupervisorGroupPage extends AbstractSupervisorGroupPage implements super(pp); add(new FeedbackPanel("feedback")); add(new BookmarkablePageLink<Void>("createThread", SupervisorGroupCreateThreadPage.class, pp)); + IModel<IndexedForumService> forumService = groupModel.map(groupForumService::getForumService); add( - new ThreadsOverviewPanel<>("threads", getThreads(), new GroupThreadDiscussable(), (id, thread) -> { + new ThreadsOverviewPanel("threads", forumService, (id, thread) -> { PageParameters parameters = new PageParameters(pp).set( PageParameterKeys.MAP.get(ForumThread.class), - thread.getObject().getId() + thread.getObject().id() ); return new BookmarkablePageLink<>(id, SupervisorViewGroupThreadPage.class, parameters); }) ); } - - private IModel<List<GroupThread>> getThreads() { - return new LoadableDetachableModel<>() { - @Override - protected List<GroupThread> load() { - List<GroupThread> threads = groupForumService.getThreads(groupModel.getObject()); - threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified()))); - return threads; - } - }; - } } diff --git a/view/src/test/java/se/su/dsv/scipro/SciProTest.java b/view/src/test/java/se/su/dsv/scipro/SciProTest.java index d83e739cb0..51be665c86 100755 --- a/view/src/test/java/se/su/dsv/scipro/SciProTest.java +++ b/view/src/test/java/se/su/dsv/scipro/SciProTest.java @@ -50,6 +50,7 @@ import se.su.dsv.scipro.finalthesis.FinalThesisService; import se.su.dsv.scipro.finalthesis.PublishingConsentService; import se.su.dsv.scipro.forum.BasicForumService; import se.su.dsv.scipro.forum.GroupForumService; +import se.su.dsv.scipro.forum.IndexedForumService; import se.su.dsv.scipro.forum.ProjectForumService; import se.su.dsv.scipro.gdpr.Reporter; import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettings; @@ -219,6 +220,9 @@ public abstract class SciProTest { @Mock protected GroupForumService groupForumService; + @Mock + protected IndexedForumService indexedForumService; + @Mock protected GeneralSystemSettingsService generalSystemSettingsService; diff --git a/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanelTest.java b/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanelTest.java index 89f646f576..ffbeb764f3 100644 --- a/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanelTest.java +++ b/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadReadStatePanelTest.java @@ -4,22 +4,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.*; -import org.apache.wicket.model.Model; +import java.time.Instant; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import se.su.dsv.scipro.SciProTest; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; +import se.su.dsv.scipro.forum.ThreadOverview; +import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel; import se.su.dsv.scipro.system.User; -import se.su.dsv.scipro.test.ForumBuilder; import se.su.dsv.scipro.test.UserBuilder; public class ThreadReadStatePanelTest extends SciProTest { ThreadReadStatePanel panel; User user; - ForumThread forumThread; + ThreadOverview forumThread; @BeforeEach public void setUp() throws Exception { @@ -27,8 +27,7 @@ public class ThreadReadStatePanelTest extends SciProTest { setLoggedIn(true); setLoggedInAs(user); - forumThread = new ForumBuilder().createThread().getForumThread(); - forumThread.addPost(new ForumBuilder().createPost(forumThread)); + forumThread = new ThreadOverview(1L, false, "Subject", user, Instant.now(), 0, new ForumPost()); } @Test @@ -40,22 +39,24 @@ public class ThreadReadStatePanelTest extends SciProTest { @Test public void testTogglingCallsCorrectService() { // given - when(basicForumService.isThreadRead(eq(user), eq(forumThread))).thenReturn(true); + when(indexedForumService.isThreadRead(eq(user), eq(forumThread.id()))).thenReturn(true); // when startPanel(); tester.executeAjaxEvent(path(panel.getId(), AbstractReadStatePanel.TOGGLE), "click"); - verify(basicForumService, times(1)).setThreadRead(eq(user), eq(forumThread), eq(false)); + verify(indexedForumService, times(1)).setThreadRead(eq(user), eq(forumThread.id()), eq(false)); // then ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class); - verify(basicForumService).setThreadRead(eq(user), eq(forumThread), captor.capture()); + verify(indexedForumService).setThreadRead(eq(user), eq(forumThread.id()), captor.capture()); assertEquals(false, captor.getValue(), "Does not toggle to the correct state"); } private void startPanel() { - panel = tester.startComponentInPage(new ThreadReadStatePanel("panel", Model.of(forumThread))); + panel = tester.startComponentInPage( + new ThreadReadStatePanel("panel", () -> indexedForumService, () -> forumThread) + ); } } diff --git a/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanelTest.java b/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanelTest.java index 614f92e7cd..aad5c17b7d 100644 --- a/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanelTest.java +++ b/view/src/test/java/se/su/dsv/scipro/forum/panels/threaded/ThreadsOverviewPanelTest.java @@ -1,33 +1,28 @@ package se.su.dsv.scipro.forum.panels.threaded; -import java.util.Arrays; +import java.time.Instant; import java.util.List; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.pages.InternalErrorPage; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import se.su.dsv.scipro.SciProTest; -import se.su.dsv.scipro.forum.Discussable; +import se.su.dsv.scipro.forum.ThreadOverview; import se.su.dsv.scipro.forum.dataobjects.ForumPost; -import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.system.User; @ExtendWith(MockitoExtension.class) public class ThreadsOverviewPanelTest extends SciProTest { - private List<ForumThread> threads; private ForumPost post; @BeforeEach public void setUp() throws Exception { - ForumThread forumThread = createThread(); - threads = Arrays.asList(forumThread); - Mockito.when(basicForumService.getLastPost(forumThread)).thenReturn(post); + ThreadOverview forumThread = createThread(); + Mockito.when(indexedForumService.getThreads()).thenReturn(List.of(forumThread)); } @Test @@ -36,17 +31,10 @@ public class ThreadsOverviewPanelTest extends SciProTest { } private void startPanel() { - IModel<List<ForumThread>> listIModel = Model.ofList(threads); tester.startComponentInPage( - new ThreadsOverviewPanel<>( + new ThreadsOverviewPanel( "id", - listIModel, - new Discussable<ForumThread>() { - @Override - public IModel<ForumThread> discussion(final IModel<ForumThread> a) { - return a; - } - }, + () -> indexedForumService, (id, thread) -> { final BookmarkablePageLink<Void> link = new BookmarkablePageLink<>(id, InternalErrorPage.class); return link; @@ -55,12 +43,10 @@ public class ThreadsOverviewPanelTest extends SciProTest { ); } - private ForumThread createThread() { + private ThreadOverview createThread() { User bob = User.builder().firstName("Bob").lastName("the Builder").emailAddress("bob@building.com").build(); post = new ForumPost(); post.setPostedBy(bob); - ForumThread groupForumThread = new ForumThread(); - groupForumThread.addPost(post); - return groupForumThread; + return new ThreadOverview(1L, true, "Subject", bob, Instant.now(), 1, post); } }