Enable supervisors to get an overview of forum activity #3
@ -25,4 +25,5 @@ public interface ProjectForumService {
|
|||||||
// TODO: Get these away from here
|
// TODO: Get these away from here
|
||||||
List<Pair<ProjectThread, ForumPost>> latestPost(Project a, int amount);
|
List<Pair<ProjectThread, ForumPost>> latestPost(Project a, int amount);
|
||||||
|
|
||||||
|
boolean hasUnreadThreads(Project project, User user);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,17 @@ public class ProjectForumServiceImpl implements ProjectForumService {
|
|||||||
return postRepository.latestPost(project, amount);
|
return postRepository.latestPost(project, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasUnreadThreads(Project project, User user) {
|
||||||
|
List<ProjectThread> threads = getThreads(project);
|
||||||
|
for (ProjectThread thread : threads) {
|
||||||
|
if (!basicForumService.isThreadRead(user, thread.getForumThread())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProjectThread findOne(long threadId) {
|
public ProjectThread findOne(long threadId) {
|
||||||
return projectThreadRepository.findOne(threadId);
|
return projectThreadRepository.findOne(threadId);
|
||||||
|
@ -20,6 +20,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||||||
import static org.hamcrest.Matchers.hasItem;
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class ProjectForumServiceImplTest extends ForumModuleTest {
|
public class ProjectForumServiceImplTest extends ForumModuleTest {
|
||||||
|
|
||||||
@ -29,23 +30,24 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
|
|||||||
ProjectForumService service;
|
ProjectForumService service;
|
||||||
|
|
||||||
private Project project;
|
private Project project;
|
||||||
private User user;
|
private User author;
|
||||||
|
private User supervisor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
ProjectType projectType = new ProjectType(DegreeType.BACHELOR, "Some project type", "Some description");
|
ProjectType projectType = new ProjectType(DegreeType.BACHELOR, "Some project type", "Some description");
|
||||||
projectType.addModule(ProjectModule.FORUM);
|
projectType.addModule(ProjectModule.FORUM);
|
||||||
save(projectType);
|
save(projectType);
|
||||||
final User supervisor = save(User.builder().firstName("Bob").lastName("The Builder").emailAddress("bob@example.com").build());
|
supervisor = save(User.builder().firstName("Bob").lastName("The Builder").emailAddress("bob@example.com").build());
|
||||||
project = Project.builder().title("Some title").projectType(projectType).startDate(LocalDate.now()).headSupervisor(supervisor).build();
|
project = Project.builder().title("Some title").projectType(projectType).startDate(LocalDate.now()).headSupervisor(supervisor).build();
|
||||||
save(project);
|
save(project);
|
||||||
user = User.builder().firstName("Stina").lastName("Student").emailAddress("stina@example.com").build();
|
author = User.builder().firstName("Stina").lastName("Student").emailAddress("stina@example.com").build();
|
||||||
save(user);
|
save(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoadThread() {
|
public void testLoadThread() {
|
||||||
final ProjectThread thread = service.createThread(project, user, "subject", "content", Set.of());
|
final ProjectThread thread = service.createThread(project, author, "subject", "content", Set.of());
|
||||||
ProjectThread serviceThread = service.findOne(thread.getId());
|
ProjectThread serviceThread = service.findOne(thread.getId());
|
||||||
|
|
||||||
assertEquals(thread, serviceThread);
|
assertEquals(thread, serviceThread);
|
||||||
@ -55,17 +57,17 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
|
|||||||
public void testCreateThreadWithPostAttachment() throws Exception {
|
public void testCreateThreadWithPostAttachment() throws Exception {
|
||||||
final String file = "attachment.txt";
|
final String file = "attachment.txt";
|
||||||
try (var is = ProjectForumServiceImplTest.class.getResourceAsStream(file)) {
|
try (var is = ProjectForumServiceImplTest.class.getResourceAsStream(file)) {
|
||||||
final StreamingUpload upload = new StreamingUpload(file, "text/plain", user, 2, is);
|
final StreamingUpload upload = new StreamingUpload(file, "text/plain", author, 2, is);
|
||||||
final ProjectThread thread = service.createThread(project, user, SUBJECT, CONTENT, Set.of(Attachment.newUpload(upload)));
|
final ProjectThread thread = service.createThread(project, author, SUBJECT, CONTENT, Set.of(Attachment.newUpload(upload)));
|
||||||
|
|
||||||
assertNewForumThread(thread, project, user, SUBJECT, CONTENT, file);
|
assertNewForumThread(thread, project, author, SUBJECT, CONTENT, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetPostPageByForumThread() {
|
public void testGetPostPageByForumThread() {
|
||||||
final ProjectThread thread = service.createThread(project, user, "subject", "content", Set.of());
|
final ProjectThread thread = service.createThread(project, author, "subject", "content", Set.of());
|
||||||
final ForumPost reply = service.createReply(thread, user, "reply", Set.of());
|
final ForumPost reply = service.createReply(thread, author, "reply", Set.of());
|
||||||
|
|
||||||
|
|
||||||
List<ForumPost> servicePage = service.getPosts(thread);
|
List<ForumPost> servicePage = service.getPosts(thread);
|
||||||
@ -76,8 +78,8 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetThreadsByProject() {
|
public void testGetThreadsByProject() {
|
||||||
final ProjectThread thread1 = service.createThread(project, user, "subject 1", "content", Set.of());
|
final ProjectThread thread1 = service.createThread(project, author, "subject 1", "content", Set.of());
|
||||||
final ProjectThread thread2 = service.createThread(project, user, "subject 2", "content", Set.of());
|
final ProjectThread thread2 = service.createThread(project, author, "subject 2", "content", Set.of());
|
||||||
|
|
||||||
List<ProjectThread> serviceThreads = service.getThreads(project);
|
List<ProjectThread> serviceThreads = service.getThreads(project);
|
||||||
|
|
||||||
@ -86,6 +88,16 @@ public class ProjectForumServiceImplTest extends ForumModuleTest {
|
|||||||
assertThat(serviceThreads, hasSize(2));
|
assertThat(serviceThreads, hasSize(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void supervisor_has_unread_forum_threads_after_student_replies() {
|
||||||
|
final ProjectThread thread = service.createThread(project, supervisor, "subject", "content", Set.of());
|
||||||
|
service.createReply(thread, author, "reply", Set.of());
|
||||||
|
|
||||||
|
boolean hasUnreadThreads = service.hasUnreadThreads(project, supervisor);
|
||||||
|
|
||||||
|
assertTrue(hasUnreadThreads);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertNewForumThread(
|
private void assertNewForumThread(
|
||||||
ProjectThread thread, Project project, User user, String subject, String content, String attachmentFileName) {
|
ProjectThread thread, Project project, User user, String subject, String content, String attachmentFileName) {
|
||||||
assertEquals(project, thread.getProject(), "Thread created for the wrong project");
|
assertEquals(project, thread.getProject(), "Thread created for the wrong project");
|
||||||
|
@ -2,7 +2,9 @@ package se.su.dsv.scipro.supervisor.panels;
|
|||||||
|
|
||||||
import org.apache.wicket.ajax.AjaxRequestTarget;
|
import org.apache.wicket.ajax.AjaxRequestTarget;
|
||||||
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
|
import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
|
||||||
|
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.sort.SortOrder;
|
||||||
|
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
|
||||||
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
|
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
|
||||||
import org.apache.wicket.extensions.markup.html.repeater.data.table.LambdaColumn;
|
import org.apache.wicket.extensions.markup.html.repeater.data.table.LambdaColumn;
|
||||||
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
|
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
|
||||||
@ -10,6 +12,7 @@ import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
|
|||||||
import org.apache.wicket.markup.html.form.Form;
|
import org.apache.wicket.markup.html.form.Form;
|
||||||
import org.apache.wicket.markup.html.form.LambdaChoiceRenderer;
|
import org.apache.wicket.markup.html.form.LambdaChoiceRenderer;
|
||||||
import org.apache.wicket.markup.html.panel.Panel;
|
import org.apache.wicket.markup.html.panel.Panel;
|
||||||
|
import org.apache.wicket.markup.repeater.Item;
|
||||||
import org.apache.wicket.model.IModel;
|
import org.apache.wicket.model.IModel;
|
||||||
import org.apache.wicket.model.LambdaModel;
|
import org.apache.wicket.model.LambdaModel;
|
||||||
import org.apache.wicket.model.Model;
|
import org.apache.wicket.model.Model;
|
||||||
@ -19,6 +22,9 @@ import se.su.dsv.scipro.components.datatables.UserColumn;
|
|||||||
import se.su.dsv.scipro.dataproviders.FilteredDataProvider;
|
import se.su.dsv.scipro.dataproviders.FilteredDataProvider;
|
||||||
import se.su.dsv.scipro.datatables.project.ProjectStateColumn;
|
import se.su.dsv.scipro.datatables.project.ProjectStateColumn;
|
||||||
import se.su.dsv.scipro.datatables.project.ProjectTitleColumn;
|
import se.su.dsv.scipro.datatables.project.ProjectTitleColumn;
|
||||||
|
import se.su.dsv.scipro.forum.ProjectForumService;
|
||||||
|
import se.su.dsv.scipro.forum.pages.threaded.SupervisorThreadedForumPage;
|
||||||
|
import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel;
|
||||||
import se.su.dsv.scipro.project.Project;
|
import se.su.dsv.scipro.project.Project;
|
||||||
import se.su.dsv.scipro.project.ProjectService;
|
import se.su.dsv.scipro.project.ProjectService;
|
||||||
import se.su.dsv.scipro.project.ProjectStatus;
|
import se.su.dsv.scipro.project.ProjectStatus;
|
||||||
@ -51,6 +57,8 @@ public class SupervisorMyProjectsPanel extends Panel {
|
|||||||
private ProjectService projectService;
|
private ProjectService projectService;
|
||||||
@Inject
|
@Inject
|
||||||
private UserProfileService profileService;
|
private UserProfileService profileService;
|
||||||
|
@Inject
|
||||||
|
private ProjectForumService projectForumService;
|
||||||
|
|
||||||
private ExportableDataPanel dataPanel;
|
private ExportableDataPanel dataPanel;
|
||||||
private ProjectService.Filter filter = new ProjectService.Filter();
|
private ProjectService.Filter filter = new ProjectService.Filter();
|
||||||
@ -72,6 +80,7 @@ public class SupervisorMyProjectsPanel extends Panel {
|
|||||||
private List<IColumn<Project, String>> createColumns() {
|
private List<IColumn<Project, String>> createColumns() {
|
||||||
List<IColumn<Project, String>> columns = new ArrayList<>();
|
List<IColumn<Project, String>> columns = new ArrayList<>();
|
||||||
columns.add(new ProjectStateColumn(Model.of("State"), "stateOfMind"));
|
columns.add(new ProjectStateColumn(Model.of("State"), "stateOfMind"));
|
||||||
|
columns.add(new ProjectForumStateColumn(Model.of("Forum")));
|
||||||
columns.add(new TemporalColumn<>(Model.of("Started"), "startDate", Project::getStartDate));
|
columns.add(new TemporalColumn<>(Model.of("Started"), "startDate", Project::getStartDate));
|
||||||
columns.add(new LambdaColumn<>(Model.of("Type"), "projectType.name", Project::getProjectTypeName));
|
columns.add(new LambdaColumn<>(Model.of("Type"), "projectType.name", Project::getProjectTypeName));
|
||||||
columns.add(new ProjectTitleColumn(Model.of("Title"), "title"));
|
columns.add(new ProjectTitleColumn(Model.of("Title"), "title"));
|
||||||
@ -157,4 +166,29 @@ public class SupervisorMyProjectsPanel extends Panel {
|
|||||||
profileService.save(userProfile);
|
profileService.save(userProfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ProjectForumStateColumn extends AbstractColumn<Project, String> {
|
||||||
|
public ProjectForumStateColumn(IModel<String> label) {
|
||||||
|
super(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populateItem(Item<ICellPopulator<Project>> item, String id, IModel<Project> projectModel) {
|
||||||
|
item.add(new AbstractReadStatePanel(id) {
|
||||||
|
@Override
|
||||||
|
protected boolean isRead() {
|
||||||
|
return !projectForumService.hasUnreadThreads(
|
||||||
|
projectModel.getObject(),
|
||||||
|
SciProSession.get().getUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFlagClick(AjaxRequestTarget target) {
|
||||||
|
setResponsePage(
|
||||||
|
SupervisorThreadedForumPage.class,
|
||||||
|
SupervisorThreadedForumPage.getPageParameters(projectModel.getObject()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user