Forum Message UI Improvement (Thesis Board #3470) #61
@ -5,10 +5,10 @@ import se.su.dsv.scipro.forum.dataobjects.ForumThread;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface BasicForumService extends Serializable {
|
||||
|
||||
ForumPost createReply(ForumThread forumThread, User poster, String content, Set<Attachment> attachments);
|
||||
|
||||
boolean setRead(User user, ForumPost post, boolean read);
|
||||
|
@ -1,20 +1,18 @@
|
||||
package se.su.dsv.scipro.forum;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import se.su.dsv.scipro.system.JpaRepository;
|
||||
import se.su.dsv.scipro.system.QueryDslPredicateExecutor;
|
||||
import java.util.List;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.JpaRepository;
|
||||
import se.su.dsv.scipro.system.QueryDslPredicateExecutor;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
import se.su.dsv.scipro.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Transactional
|
||||
public interface ForumPostRepository extends JpaRepository<ForumPost, Long>, QueryDslPredicateExecutor<ForumPost> {
|
||||
|
||||
List<ForumPost> findByThread(ForumThread forumThread);
|
||||
|
||||
List<Pair<ProjectThread, ForumPost>> latestPost(Project project, int amount);
|
||||
|
@ -1,10 +1,13 @@
|
||||
package se.su.dsv.scipro.forum;
|
||||
|
||||
import static com.querydsl.core.types.dsl.Expressions.allOf;
|
||||
|
||||
import com.querydsl.jpa.JPAExpressions;
|
||||
import com.querydsl.jpa.impl.JPAQuery;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.List;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
|
||||
@ -17,11 +20,8 @@ import se.su.dsv.scipro.system.GenericRepo;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
import se.su.dsv.scipro.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.querydsl.core.types.dsl.Expressions.allOf;
|
||||
|
||||
public class ForumPostRepositoryImpl extends GenericRepo<ForumPost, Long> implements ForumPostRepository {
|
||||
|
||||
@Inject
|
||||
public ForumPostRepositoryImpl(Provider<EntityManager> em) {
|
||||
super(em, ForumPost.class, QForumPost.forumPost);
|
||||
@ -44,9 +44,7 @@ public class ForumPostRepositoryImpl extends GenericRepo<ForumPost, Long> implem
|
||||
.limit(amount)
|
||||
.fetch()
|
||||
.stream()
|
||||
.map(tuple -> new Pair<>(
|
||||
tuple.get(QProjectThread.projectThread),
|
||||
tuple.get(QForumPost.forumPost)))
|
||||
.map(tuple -> new Pair<>(tuple.get(QProjectThread.projectThread), tuple.get(QForumPost.forumPost)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@ -56,12 +54,17 @@ public class ForumPostRepositoryImpl extends GenericRepo<ForumPost, Long> implem
|
||||
.select(QForumThread.forumThread.id.countDistinct())
|
||||
.from(QForumThread.forumThread)
|
||||
.leftJoin(QForumThread.forumThread.posts, QForumPost.forumPost)
|
||||
.where(QForumPost.forumPost.notIn(
|
||||
.where(
|
||||
QForumPost.forumPost.notIn(
|
||||
JPAExpressions.select(QForumPostReadState.forumPostReadState.id.post)
|
||||
.from(QForumPostReadState.forumPostReadState)
|
||||
.where(QForumPostReadState.forumPostReadState.read.isTrue(),
|
||||
QForumPostReadState.forumPostReadState.id.user.eq(user))
|
||||
), QForumThread.forumThread.in(forumThreadList)
|
||||
).fetchOne();
|
||||
.where(
|
||||
QForumPostReadState.forumPostReadState.read.isTrue(),
|
||||
QForumPostReadState.forumPostReadState.id.user.eq(user)
|
||||
)
|
||||
),
|
||||
QForumThread.forumThread.in(forumThreadList)
|
||||
)
|
||||
.fetchOne();
|
||||
}
|
||||
}
|
||||
|
@ -127,9 +127,7 @@ public class ProjectForumServiceImpl implements ProjectForumService {
|
||||
@Override
|
||||
public long getUnreadThreadsCount(Project project, User user) {
|
||||
List<ProjectThread> threads = getThreads(project);
|
||||
List<ForumThread> list = threads.stream()
|
||||
.map(ProjectThread::getForumThread)
|
||||
.toList();
|
||||
List<ForumThread> list = threads.stream().map(ProjectThread::getForumThread).toList();
|
||||
return basicForumService.countUnreadThreads(list, user);
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,14 @@
|
||||
package se.su.dsv.scipro.forum;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.JpaRepository;
|
||||
import se.su.dsv.scipro.system.QueryDslPredicateExecutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Transactional
|
||||
public interface ProjectThreadRepository extends JpaRepository<ProjectThread, Long>, QueryDslPredicateExecutor<ProjectThread> {
|
||||
|
||||
public interface ProjectThreadRepository
|
||||
extends JpaRepository<ProjectThread, Long>, QueryDslPredicateExecutor<ProjectThread> {
|
||||
List<ProjectThread> findByProject(Project project);
|
||||
|
||||
}
|
||||
|
@ -3,14 +3,14 @@ package se.su.dsv.scipro.forum;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.List;
|
||||
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
|
||||
import se.su.dsv.scipro.forum.dataobjects.QProjectThread;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.GenericRepo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProjectThreadRepositoryImpl extends GenericRepo<ProjectThread, Long> implements ProjectThreadRepository {
|
||||
|
||||
@Inject
|
||||
public ProjectThreadRepositoryImpl(Provider<EntityManager> em) {
|
||||
super(em, ProjectThread.class, QProjectThread.projectThread);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package se.su.dsv.scipro.forum.panels;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.apache.wicket.Component;
|
||||
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
|
||||
@ -7,8 +8,6 @@ import org.apache.wicket.markup.ComponentTag;
|
||||
import org.apache.wicket.markup.html.WebComponent;
|
||||
import org.apache.wicket.markup.html.panel.Panel;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class AbstractReadStatePanel extends Panel {
|
||||
|
||||
public static final String TOGGLE = "toggle";
|
||||
@ -16,7 +15,6 @@ public abstract class AbstractReadStatePanel extends Panel {
|
||||
|
||||
public AbstractReadStatePanel(final String id) {
|
||||
super(id);
|
||||
|
||||
Component icon = new UpdatingImage(ICON);
|
||||
icon.setOutputMarkupId(true);
|
||||
|
||||
@ -35,9 +33,11 @@ public abstract class AbstractReadStatePanel extends Panel {
|
||||
}
|
||||
|
||||
protected abstract boolean isRead();
|
||||
|
||||
protected abstract void onFlagClick(final AjaxRequestTarget target);
|
||||
|
||||
private class UpdatingImage extends WebComponent {
|
||||
|
||||
public UpdatingImage(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ public abstract class NumberOfMessagesPanel extends Panel {
|
||||
|
||||
public NumberOfMessagesPanel(final String id) {
|
||||
super(id);
|
||||
|
||||
add(new Label("msgCount", model));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,10 +1,14 @@
|
||||
package se.su.dsv.scipro.supervisor.panels;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.wicket.AttributeModifier;
|
||||
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||
import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
|
||||
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
|
||||
import org.apache.wicket.AttributeModifier;
|
||||
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
|
||||
import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
|
||||
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
|
||||
@ -47,11 +51,6 @@ import se.su.dsv.scipro.system.ProjectType;
|
||||
import se.su.dsv.scipro.system.ProjectTypeService;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
public static final String FILTER_FORM = "filterForm";
|
||||
@ -63,10 +62,13 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
@Inject
|
||||
private ProjectTypeService projectTypeService;
|
||||
|
||||
@Inject
|
||||
private ProjectService projectService;
|
||||
|
||||
@Inject
|
||||
private UserProfileService profileService;
|
||||
|
||||
@Inject
|
||||
private ProjectForumService projectForumService;
|
||||
|
||||
@ -82,7 +84,10 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
}
|
||||
|
||||
private void dataViewSetup() {
|
||||
SortableDataProvider<Project, String> provider = new FilteredDataProvider<>(projectService, Model.of(this.filter));
|
||||
SortableDataProvider<Project, String> provider = new FilteredDataProvider<>(
|
||||
projectService,
|
||||
Model.of(this.filter)
|
||||
);
|
||||
provider.setSort("dateCreated", SortOrder.DESCENDING);
|
||||
dataPanel = new ExportableDataPanel<>(DATA_PANEL, createColumns(), provider);
|
||||
add(dataPanel);
|
||||
@ -95,14 +100,24 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
columns.add(new TemporalColumn<>(Model.of("Started"), "startDate", Project::getStartDate));
|
||||
columns.add(new LambdaColumn<>(Model.of("Type"), "projectType.name", Project::getProjectTypeName));
|
||||
columns.add(new ProjectTitleColumn(Model.of("Title"), "title"));
|
||||
columns.add(new MultipleUsersColumn<>(Model.of("Authors")) {
|
||||
columns.add(
|
||||
new MultipleUsersColumn<>(Model.of("Authors")) {
|
||||
@Override
|
||||
public ListAdapterModel<User> getUsers(final IModel<Project> rowModel) {
|
||||
return new ListAdapterModel<>(rowModel.map(Project::getProjectParticipants));
|
||||
}
|
||||
});
|
||||
columns.add(new ProjectNoteColumn(Model.of("Note"), LoadableDetachableModel.of(this::currentUser), supervisorProjectNoteDisplayModel));
|
||||
columns.add(new UserColumn<>(Model.of("Head supervisor"), "headSupervisor.fullName", Project::getHeadSupervisor));
|
||||
}
|
||||
);
|
||||
columns.add(
|
||||
new ProjectNoteColumn(
|
||||
Model.of("Note"),
|
||||
LoadableDetachableModel.of(this::currentUser),
|
||||
supervisorProjectNoteDisplayModel
|
||||
)
|
||||
);
|
||||
columns.add(
|
||||
new UserColumn<>(Model.of("Head supervisor"), "headSupervisor.fullName", Project::getHeadSupervisor)
|
||||
);
|
||||
return columns;
|
||||
}
|
||||
|
||||
@ -139,47 +154,87 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
public FilterForm(String id, IModel<ProjectService.Filter> filterParams) {
|
||||
super(id, filterParams);
|
||||
|
||||
add(new AjaxCheckBox(SUPERVISOR, LambdaModel.of(filterParams, ProjectService.Filter::isFilterSupervisor, ProjectService.Filter::setFilterSupervisor)) {
|
||||
add(
|
||||
new AjaxCheckBox(
|
||||
SUPERVISOR,
|
||||
LambdaModel.of(
|
||||
filterParams,
|
||||
ProjectService.Filter::isFilterSupervisor,
|
||||
ProjectService.Filter::setFilterSupervisor
|
||||
)
|
||||
) {
|
||||
@Override
|
||||
protected void onUpdate(AjaxRequestTarget target) {
|
||||
target.add(dataPanel);
|
||||
updateProfileWithCurrentFilter();
|
||||
}
|
||||
});
|
||||
add(new AjaxCheckBoxMultipleChoice<>(ROLE_FILTER, LambdaModel.of(filterParams, ProjectService.Filter::getRoles, ProjectService.Filter::setRoles), List.of(ProjectTeamMemberRoles.CO_SUPERVISOR), new EnumChoiceRenderer<>(this)) {
|
||||
}
|
||||
);
|
||||
add(
|
||||
new AjaxCheckBoxMultipleChoice<>(
|
||||
ROLE_FILTER,
|
||||
LambdaModel.of(filterParams, ProjectService.Filter::getRoles, ProjectService.Filter::setRoles),
|
||||
List.of(ProjectTeamMemberRoles.CO_SUPERVISOR),
|
||||
new EnumChoiceRenderer<>(this)
|
||||
) {
|
||||
@Override
|
||||
public void onUpdate(AjaxRequestTarget target) {
|
||||
target.add(dataPanel);
|
||||
updateProfileWithCurrentFilter();
|
||||
}
|
||||
});
|
||||
add(new AjaxCheckBoxMultipleChoice<>(STATUS_FILTER, LambdaModel.of(filterParams, ProjectService.Filter::getStatuses, ProjectService.Filter::setStatuses), asList(ProjectStatus.values()), new EnumChoiceRenderer<>(this)) {
|
||||
}
|
||||
);
|
||||
add(
|
||||
new AjaxCheckBoxMultipleChoice<>(
|
||||
STATUS_FILTER,
|
||||
LambdaModel.of(
|
||||
filterParams,
|
||||
ProjectService.Filter::getStatuses,
|
||||
ProjectService.Filter::setStatuses
|
||||
),
|
||||
asList(ProjectStatus.values()),
|
||||
new EnumChoiceRenderer<>(this)
|
||||
) {
|
||||
@Override
|
||||
public void onUpdate(AjaxRequestTarget target) {
|
||||
target.add(dataPanel);
|
||||
updateProfileWithCurrentFilter();
|
||||
}
|
||||
});
|
||||
add(new AjaxCheckBoxMultipleChoice<>(TYPE_FILTER, LambdaModel.of(filterParams, ProjectService.Filter::getProjectTypes, ProjectService.Filter::setProjectTypes), projectTypeService.findBySupervisorProjects(SciProSession.get().getUser()), new LambdaChoiceRenderer<>(ProjectType::getName, ProjectType::getId)) {
|
||||
}
|
||||
);
|
||||
add(
|
||||
new AjaxCheckBoxMultipleChoice<>(
|
||||
TYPE_FILTER,
|
||||
LambdaModel.of(
|
||||
filterParams,
|
||||
ProjectService.Filter::getProjectTypes,
|
||||
ProjectService.Filter::setProjectTypes
|
||||
),
|
||||
projectTypeService.findBySupervisorProjects(SciProSession.get().getUser()),
|
||||
new LambdaChoiceRenderer<>(ProjectType::getName, ProjectType::getId)
|
||||
) {
|
||||
@Override
|
||||
public void onUpdate(AjaxRequestTarget target) {
|
||||
target.add(dataPanel);
|
||||
updateProfileWithCurrentFilter();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
BootstrapRadioChoice<SupervisorProjectNoteDisplay> noteDisplay = new BootstrapRadioChoice<>(
|
||||
"note_display",
|
||||
supervisorProjectNoteDisplayModel,
|
||||
List.of(SupervisorProjectNoteDisplay.values()),
|
||||
new EnumChoiceRenderer<>(this));
|
||||
noteDisplay.add(new AjaxFormChoiceComponentUpdatingBehavior() {
|
||||
new EnumChoiceRenderer<>(this)
|
||||
);
|
||||
noteDisplay.add(
|
||||
new AjaxFormChoiceComponentUpdatingBehavior() {
|
||||
@Override
|
||||
public void onUpdate(AjaxRequestTarget target) {
|
||||
target.add(dataPanel);
|
||||
updateProfileWithCurrentFilter();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
add(noteDisplay);
|
||||
}
|
||||
|
||||
@ -195,6 +250,7 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
}
|
||||
|
||||
private class ProjectForumStateColumn extends AbstractColumn<Project, String> {
|
||||
|
||||
public ProjectForumStateColumn(IModel<String> label) {
|
||||
super(label);
|
||||
}
|
||||
@ -206,8 +262,10 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
Fragment fragment = new Fragment(id, "readStateColumnMarkupId", SupervisorMyProjectsPanel.this);
|
||||
|
||||
long msgCount = projectForumService.getUnreadThreadsCount(projectModel.getObject(),
|
||||
SciProSession.get().getUser());
|
||||
long msgCount = projectForumService.getUnreadThreadsCount(
|
||||
projectModel.getObject(),
|
||||
SciProSession.get().getUser()
|
||||
);
|
||||
boolean isRead = msgCount == 0;
|
||||
|
||||
AbstractReadStatePanel readStatePanel = new AbstractReadStatePanel("flag") {
|
||||
@ -218,8 +276,10 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
@Override
|
||||
protected void onFlagClick(AjaxRequestTarget target) {
|
||||
setResponsePage(SupervisorThreadedForumPage.class,
|
||||
SupervisorThreadedForumPage.getPageParameters(projectModel.getObject()));
|
||||
setResponsePage(
|
||||
SupervisorThreadedForumPage.class,
|
||||
SupervisorThreadedForumPage.getPageParameters(projectModel.getObject())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -229,12 +289,14 @@ public class SupervisorMyProjectsPanel extends Panel {
|
||||
|
||||
fragment.add(readStatePanel);
|
||||
|
||||
fragment.add(new NumberOfMessagesPanel("counter") {
|
||||
fragment.add(
|
||||
new NumberOfMessagesPanel("counter") {
|
||||
@Override
|
||||
public long getMessageCount() {
|
||||
return msgCount;
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
item.add(fragment);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user