Skip to content

Commit

Permalink
Fixed marking comics as read [#1059]
Browse files Browse the repository at this point in the history
 * Dropped vestigial "created_on" column.
 * Added comic state events for setting the read state.
  • Loading branch information
mcpierce committed Oct 26, 2021
1 parent 73a31ff commit c521304
Show file tree
Hide file tree
Showing 65 changed files with 855 additions and 1,111 deletions.
Expand Up @@ -37,6 +37,7 @@ public class PublishLastReadRemovedAction extends AbstractPublishAction<LastRead
@Override
public void publish(final LastRead lastRead) throws PublishingException {
log.trace("Publishing last read remove");
this.doPublish(Constants.LAST_READ_REMOVAL_TOPIC, lastRead, View.LastReadList.class);
this.doPublish(
lastRead.getUser(), Constants.LAST_READ_REMOVED_TOPIC, lastRead, View.LastReadList.class);
}
}
Expand Up @@ -27,16 +27,17 @@
import org.springframework.stereotype.Component;

/**
* <code>PublishLastReadUpdateAction</code> publishes updates to {@link LastRead} instances.
* <code>PublishLastReadUpdatedAction</code> publishes updates to {@link LastRead} instances.
*
* @author Darryl L. Pierce
*/
@Component
@Log4j2
public class PublishLastReadUpdateAction extends AbstractPublishAction<LastRead> {
public class PublishLastReadUpdatedAction extends AbstractPublishAction<LastRead> {
@Override
public void publish(final LastRead lastRead) throws PublishingException {
log.trace("Publishing last read update");
this.doPublish(Constants.LAST_READ_UPDATE_TOPIC, lastRead, View.LastReadList.class);
this.doPublish(
lastRead.getUser(), Constants.LAST_READ_UPDATED_TOPIC, lastRead, View.LastReadList.class);
}
}
Expand Up @@ -24,6 +24,7 @@
import org.comixedproject.messaging.PublishingException;
import org.comixedproject.model.library.LastRead;
import org.comixedproject.model.messaging.Constants;
import org.comixedproject.model.user.ComiXedUser;
import org.comixedproject.views.View;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -37,17 +38,21 @@
@RunWith(MockitoJUnitRunner.class)
public class PublishLastReadRemovedActionTest {
private static final String TEST_LAST_READ_AS_JSON = "Object as JSON";
private static final String TEST_EMAIL = "reader@comixedproject.org";

@InjectMocks private PublishLastReadRemovedAction action;
@Mock private SimpMessagingTemplate messagingTemplate;
@Mock private ObjectMapper objectMapper;
@Mock private ObjectWriter objectWriter;
@Mock private LastRead lastRead;
@Mock private ComiXedUser user;

@Before
public void setUp() throws JsonProcessingException {
Mockito.when(objectMapper.writerWithView(Mockito.any())).thenReturn(objectWriter);
Mockito.when(objectWriter.writeValueAsString(Mockito.any())).thenReturn(TEST_LAST_READ_AS_JSON);
Mockito.when(lastRead.getUser()).thenReturn(user);
Mockito.when(user.getEmail()).thenReturn(TEST_EMAIL);
}

@Test(expected = PublishingException.class)
Expand All @@ -72,6 +77,7 @@ public void testPublish() throws PublishingException, JsonProcessingException {
Mockito.verify(objectMapper, Mockito.times(1)).writerWithView(View.LastReadList.class);
Mockito.verify(objectWriter, Mockito.times(1)).writeValueAsString(lastRead);
Mockito.verify(messagingTemplate, Mockito.times(1))
.convertAndSend(Constants.LAST_READ_REMOVAL_TOPIC, TEST_LAST_READ_AS_JSON);
.convertAndSendToUser(
TEST_EMAIL, Constants.LAST_READ_REMOVED_TOPIC, TEST_LAST_READ_AS_JSON);
}
}
Expand Up @@ -24,6 +24,7 @@
import org.comixedproject.messaging.PublishingException;
import org.comixedproject.model.library.LastRead;
import org.comixedproject.model.messaging.Constants;
import org.comixedproject.model.user.ComiXedUser;
import org.comixedproject.views.View;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -35,19 +36,23 @@
import org.springframework.messaging.simp.SimpMessagingTemplate;

@RunWith(MockitoJUnitRunner.class)
public class PublishLastReadUpdateActionTest {
public class PublishLastReadUpdatedActionTest {
private static final String TEST_LAST_READ_AS_JSON = "Object as JSON";
private static final String TEST_EMAIL = "read@comixedproject.org";

@InjectMocks private PublishLastReadUpdateAction action;
@InjectMocks private PublishLastReadUpdatedAction action;
@Mock private SimpMessagingTemplate messagingTemplate;
@Mock private ObjectMapper objectMapper;
@Mock private ObjectWriter objectWriter;
@Mock private LastRead lastRead;
@Mock private ComiXedUser user;

@Before
public void setUp() throws JsonProcessingException {
Mockito.when(objectMapper.writerWithView(Mockito.any())).thenReturn(objectWriter);
Mockito.when(objectWriter.writeValueAsString(Mockito.any())).thenReturn(TEST_LAST_READ_AS_JSON);
Mockito.when(lastRead.getUser()).thenReturn(user);
Mockito.when(user.getEmail()).thenReturn(TEST_EMAIL);
}

@Test(expected = PublishingException.class)
Expand All @@ -72,6 +77,7 @@ public void testPublish() throws PublishingException, JsonProcessingException {
Mockito.verify(objectMapper, Mockito.times(1)).writerWithView(View.LastReadList.class);
Mockito.verify(objectWriter, Mockito.times(1)).writeValueAsString(lastRead);
Mockito.verify(messagingTemplate, Mockito.times(1))
.convertAndSend(Constants.LAST_READ_UPDATE_TOPIC, TEST_LAST_READ_AS_JSON);
.convertAndSendToUser(
TEST_EMAIL, Constants.LAST_READ_UPDATED_TOPIC, TEST_LAST_READ_AS_JSON);
}
}
Expand Up @@ -27,7 +27,6 @@
import org.comixedproject.model.user.ComiXedUser;
import org.comixedproject.views.View;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

/**
* <code>LastRead</code> holds the date and time for when a user last read a specific comic.
Expand Down Expand Up @@ -76,13 +75,6 @@ public class LastRead {
@JsonView({View.LastReadList.class, View.AuditLogEntryDetail.class})
private Date createdOn = new Date();

@Column(name = "LastModifiedOn", nullable = false, updatable = true)
@LastModifiedDate
@Getter
@Setter
@JsonView({View.LastReadList.class, View.AuditLogEntryDetail.class})
private Date lastModifiedOn = new Date();

@Override
public boolean equals(final Object o) {
if (this == o) return true;
Expand Down
Expand Up @@ -40,10 +40,10 @@ public interface Constants {
String CURRENT_USER_UPDATE_TOPIC = "/topic/user/current";

/** Topic which receives notices when last read entries are updated. */
String LAST_READ_UPDATE_TOPIC = "/topic/last-read-list.update";
String LAST_READ_UPDATED_TOPIC = "/topic/last-read-list.update";

/** Topic which receives notices when last read entries are removed. */
String LAST_READ_REMOVAL_TOPIC = "/topic/last-read-list.removal";
String LAST_READ_REMOVED_TOPIC = "/topic/last-read-list.remove";

/** Topic which receives notices when the duplicate page list is updated. */
String DUPLICATE_PAGE_LIST_TOPIC = "/topic/duplicate-page-list.update";
Expand Down
Expand Up @@ -16,23 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.model.net.library;
package org.comixedproject.model.net.library.library;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

/**
* <code>GetLastReadDatesRequest</code> represents the payload for a single request for last read
* dates for a user.
* <code>SetComicsReadRequest</code> represents the request body when marking multiple comics as
* read.
*
* @author Darryl L. Pierce
*/
@NoArgsConstructor
@AllArgsConstructor
public class GetLastReadDatesRequest {
@JsonProperty("lastId")
public class SetComicsReadRequest {
@JsonProperty("ids")
@Getter
private long lastId;
private List<Long> ids;

@JsonProperty("read")
@Getter()
private boolean read;
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="009_1059_removed_dates_from_last_read.xml"
author="mcpierce">

<dropColumn tableName="LastReadDates"
columnName="created_on"/>
<dropColumn tableName="LastReadDates"
columnName="LastModifiedOn"/>

</changeSet>
</databaseChangeLog>
Expand Up @@ -14,5 +14,6 @@
<include file="/db/migrations/0.11.0/006_801_rename_scraping_rules_table.xml"/>
<include file="/db/migrations/0.11.0/007_1046_make_comicvineid_a_number.xml"/>
<include file="/db/migrations/0.11.0/008_1053_remove_comic_file_entries.xml"/>
<include file="/db/migrations/0.11.0/009_1059_removed_dates_from_last_read.xml"/>

</databaseChangeLog>
Expand Up @@ -35,24 +35,24 @@
*/
public interface LastReadRepository extends CrudRepository<LastRead, Long> {
/**
* Retrieves a batch of last read entries.
* Loads a batch of last read entries.
*
* @param user the user
* @param threshold the threshold id
* @param pageRequest the request constraints
* @return the entries
*/
@Query("SELECT e FROM LastRead e WHERE e.id > :threshold AND e.user = :user ORDER BY e.id")
List<LastRead> getEntriesForUser(
List<LastRead> loadEntriesForUser(
@Param("user") ComiXedUser user, @Param("threshold") long threshold, Pageable pageRequest);

/**
* Retrieves the last read entry for the given user and comic.
* Retrieves the last read entry for the given comic and user.
*
* @param user the user
* @param comic the comic
* @param user the user
* @return the entry, or null if non exists
*/
@Query("SELECT e FROM LastRead e WHERE e.user = :user AND e.comic = :comic")
LastRead findEntryForUserAndComic(@Param("user") ComiXedUser user, @Param("comic") Comic comic);
@Query("SELECT e FROM LastRead e WHERE e.comic = :comic AND e.user = :user")
LastRead loadEntryForComicAndUser(@Param("comic") Comic comic, @Param("user") ComiXedUser user);
}
Expand Up @@ -73,18 +73,18 @@ public void setUp() {
}

@Test
public void testGetEntriesForUserNoEntries() {
public void testLoadEntriesForUserNoEntries() {
final List<LastRead> result =
this.repository.getEntriesForUser(userWithoutEntries, 0, PageRequest.of(0, TEST_MAXIMUM));
this.repository.loadEntriesForUser(userWithoutEntries, 0, PageRequest.of(0, TEST_MAXIMUM));

assertNotNull(result);
assertTrue(result.isEmpty());
}

@Test
public void testGetEntriesForUser() {
public void testLoadEntriesForUser() {
final List<LastRead> result =
this.repository.getEntriesForUser(user, 0, PageRequest.of(0, TEST_MAXIMUM));
this.repository.loadEntriesForUser(user, 0, PageRequest.of(0, TEST_MAXIMUM));

assertNotNull(result);
assertFalse(result.isEmpty());
Expand All @@ -96,9 +96,9 @@ public void testGetEntriesForUser() {
}

@Test
public void testGetEntriesForUserNoMoreEntries() {
public void testLoadEntriesForUserNoMoreEntries() {
final List<LastRead> result =
this.repository.getEntriesForUser(user, 1000L, PageRequest.of(0, TEST_MAXIMUM));
this.repository.loadEntriesForUser(user, 1000L, PageRequest.of(0, TEST_MAXIMUM));

assertNotNull(result);
assertTrue(result.isEmpty());
Expand All @@ -107,21 +107,21 @@ public void testGetEntriesForUserNoMoreEntries() {
@Test
public void testFindEntryForUserAndComicForUserWithNoEntries() {
final LastRead result =
this.repository.findEntryForUserAndComic(userWithoutEntries, comicWithEntries);
this.repository.loadEntryForComicAndUser(comicWithEntries, userWithoutEntries);

assertNull(result);
}

@Test
public void testFindEntryForUserAndComicForUserWithEntriesButNoThisComic() {
final LastRead result = this.repository.findEntryForUserAndComic(user, comicWithNoEntries);
final LastRead result = this.repository.loadEntryForComicAndUser(comicWithNoEntries, user);

assertNull(result);
}

@Test
public void testFindEntryForUserAndComic() {
final LastRead result = this.repository.findEntryForUserAndComic(user, comicWithEntries);
final LastRead result = this.repository.loadEntryForComicAndUser(comicWithEntries, user);

assertNotNull(result);
assertEquals(user, result.getUser());
Expand Down
30 changes: 10 additions & 20 deletions comixed-repositories/src/test/resources/test-database.xml
Expand Up @@ -405,62 +405,52 @@
UserId="1000"
ComicId="1000"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="2"
UserId="1000"
ComicId="1001"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="3"
UserId="1000"
ComicId="1002"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="4"
UserId="1000"
ComicId="1003"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="5"
UserId="1000"
ComicId="1004"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="6"
UserId="1000"
ComicId="1005"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="7"
UserId="1000"
ComicId="1006"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="8"
UserId="1000"
ComicId="1010"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="9"
UserId="1000"
ComicId="1020"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<LastReadDates Id="10"
UserId="1000"
ComicId="1021"
CreatedOn="[now-1d]"
LastReadOn="[now]"
LastModifiedOn="[now-1d]"/>
LastReadOn="[now]"/>
<ReadingLists Id="1000"
ReadingListState="STABLE"
Name="First Reading List"
Expand Down

0 comments on commit c521304

Please sign in to comment.