feat: sharing labels for series

This commit is contained in:
Gauthier Roebroeck 2022-02-24 17:55:36 +08:00
parent 3a218c0afa
commit 496ebb0aac
6 changed files with 83 additions and 16 deletions

View file

@ -0,0 +1,9 @@
CREATE TABLE SERIES_METADATA_SHARING
(
LABEL varchar NOT NULL,
SERIES_ID varchar NOT NULL,
FOREIGN KEY (SERIES_ID) REFERENCES SERIES (ID)
);
alter table SERIES_METADATA
add column SHARING_LABELS_LOCK boolean NOT NULL DEFAULT 0;

View file

@ -1,5 +1,6 @@
package org.gotson.komga.domain.model
import org.gotson.komga.language.lowerNotBlank
import java.time.LocalDateTime
class SeriesMetadata(
@ -14,6 +15,7 @@ class SeriesMetadata(
genres: Set<String> = emptySet(),
tags: Set<String> = emptySet(),
val totalBookCount: Int? = null,
sharingLabels: Set<String> = emptySet(),
val statusLock: Boolean = false,
val titleLock: Boolean = false,
@ -26,6 +28,7 @@ class SeriesMetadata(
val genresLock: Boolean = false,
val tagsLock: Boolean = false,
val totalBookCountLock: Boolean = false,
val sharingLabelsLock: Boolean = false,
val seriesId: String = "",
@ -37,8 +40,9 @@ class SeriesMetadata(
val summary = summary.trim()
val publisher = publisher.trim()
val language = language.trim().lowercase()
val tags = tags.map { it.lowercase().trim() }.filter { it.isNotBlank() }.toSet()
val genres = genres.map { it.lowercase().trim() }.filter { it.isNotBlank() }.toSet()
val tags = tags.lowerNotBlank().toSet()
val genres = genres.lowerNotBlank().toSet()
val sharingLabels = sharingLabels.lowerNotBlank().toSet()
fun copy(
status: Status = this.status,
@ -52,6 +56,7 @@ class SeriesMetadata(
genres: Set<String> = this.genres,
tags: Set<String> = this.tags,
totalBookCount: Int? = this.totalBookCount,
sharingLabels: Set<String> = this.sharingLabels,
statusLock: Boolean = this.statusLock,
titleLock: Boolean = this.titleLock,
titleSortLock: Boolean = this.titleSortLock,
@ -63,6 +68,7 @@ class SeriesMetadata(
genresLock: Boolean = this.genresLock,
tagsLock: Boolean = this.tagsLock,
totalBookCountLock: Boolean = this.totalBookCountLock,
sharingLabelsLock: Boolean = this.sharingLabelsLock,
seriesId: String = this.seriesId,
createdDate: LocalDateTime = this.createdDate,
lastModifiedDate: LocalDateTime = this.lastModifiedDate,
@ -79,6 +85,7 @@ class SeriesMetadata(
genres = genres,
tags = tags,
totalBookCount = totalBookCount,
sharingLabels = sharingLabels,
statusLock = statusLock,
titleLock = titleLock,
titleSortLock = titleSortLock,
@ -90,6 +97,7 @@ class SeriesMetadata(
genresLock = genresLock,
tagsLock = tagsLock,
totalBookCountLock = totalBookCountLock,
sharingLabelsLock = sharingLabelsLock,
seriesId = seriesId,
createdDate = createdDate,
lastModifiedDate = lastModifiedDate,
@ -106,7 +114,6 @@ class SeriesMetadata(
WEBTOON
}
override fun toString(): String {
return "SeriesMetadata(status=$status, readingDirection=$readingDirection, ageRating=$ageRating, language='$language', totalBookCount=$totalBookCount, statusLock=$statusLock, titleLock=$titleLock, titleSortLock=$titleSortLock, summaryLock=$summaryLock, readingDirectionLock=$readingDirectionLock, publisherLock=$publisherLock, ageRatingLock=$ageRatingLock, languageLock=$languageLock, genresLock=$genresLock, tagsLock=$tagsLock, totalBookCountLock=$totalBookCountLock, seriesId='$seriesId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', titleSort='$titleSort', summary='$summary', publisher='$publisher', tags=$tags, genres=$genres)"
}
override fun toString(): String =
"SeriesMetadata(status=$status, readingDirection=$readingDirection, ageRating=$ageRating, totalBookCount=$totalBookCount, statusLock=$statusLock, titleLock=$titleLock, titleSortLock=$titleSortLock, summaryLock=$summaryLock, readingDirectionLock=$readingDirectionLock, publisherLock=$publisherLock, ageRatingLock=$ageRatingLock, languageLock=$languageLock, genresLock=$genresLock, tagsLock=$tagsLock, totalBookCountLock=$totalBookCountLock, sharingLabelsLock=$sharingLabelsLock, seriesId='$seriesId', createdDate=$createdDate, lastModifiedDate=$lastModifiedDate, title='$title', titleSort='$titleSort', summary='$summary', publisher='$publisher', language='$language', tags=$tags, genres=$genres, sharingLabels=$sharingLabels)"
}

View file

@ -54,6 +54,7 @@ class SeriesDtoDao(
private val cs = Tables.COLLECTION_SERIES
private val g = Tables.SERIES_METADATA_GENRE
private val st = Tables.SERIES_METADATA_TAG
private val sl = Tables.SERIES_METADATA_SHARING
private val bma = Tables.BOOK_METADATA_AGGREGATION
private val bmaa = Tables.BOOK_METADATA_AGGREGATION_AUTHOR
private val bmat = Tables.BOOK_METADATA_AGGREGATION_TAG
@ -235,6 +236,11 @@ class SeriesDtoDao(
.where(st.SERIES_ID.eq(sr.id))
.fetchSet(st.TAG)
val sharingLabels = dsl.select(sl.LABEL)
.from(sl)
.where(sl.SERIES_ID.eq(sr.id))
.fetchSet(sl.LABEL)
val aggregatedAuthors = dsl.selectFrom(bmaa)
.where(bmaa.SERIES_ID.eq(sr.id))
.fetchInto(bmaa)
@ -250,7 +256,7 @@ class SeriesDtoDao(
booksReadCount,
booksUnreadCount,
booksInProgressCount,
dr.toDto(genres, tags),
dr.toDto(genres, tags, sharingLabels),
bmar.toDto(aggregatedAuthors, aggregatedTags),
)
}
@ -346,7 +352,7 @@ class SeriesDtoDao(
deleted = deletedDate != null,
)
private fun SeriesMetadataRecord.toDto(genres: Set<String>, tags: Set<String>) =
private fun SeriesMetadataRecord.toDto(genres: Set<String>, tags: Set<String>, sharingLabels: Set<String>) =
SeriesMetadataDto(
status = status,
statusLock = statusLock,
@ -372,6 +378,8 @@ class SeriesDtoDao(
tagsLock = tagsLock,
totalBookCount = totalBookCount,
totalBookCountLock = totalBookCountLock,
sharingLabels = sharingLabels,
sharingLabelsLock = sharingLabelsLock,
)
private fun BookMetadataAggregationRecord.toDto(authors: List<AuthorDto>, tags: Set<String>) =

View file

@ -20,12 +20,13 @@ class SeriesMetadataDao(
private val d = Tables.SERIES_METADATA
private val g = Tables.SERIES_METADATA_GENRE
private val st = Tables.SERIES_METADATA_TAG
private val sl = Tables.SERIES_METADATA_SHARING
override fun findById(seriesId: String): SeriesMetadata =
findOne(seriesId)!!.toDomain(findGenres(seriesId), findTags(seriesId))
findOne(seriesId)!!.toDomain(findGenres(seriesId), findTags(seriesId), findSharingLabels(seriesId))
override fun findByIdOrNull(seriesId: String): SeriesMetadata? =
findOne(seriesId)?.toDomain(findGenres(seriesId), findTags(seriesId))
findOne(seriesId)?.toDomain(findGenres(seriesId), findTags(seriesId), findSharingLabels(seriesId))
private fun findOne(seriesId: String) =
dsl.selectFrom(d)
@ -36,17 +37,19 @@ class SeriesMetadataDao(
dsl.select(g.GENRE)
.from(g)
.where(g.SERIES_ID.eq(seriesId))
.fetchInto(g)
.mapNotNull { it.genre }
.toSet()
.fetchSet(g.GENRE)
private fun findTags(seriesId: String) =
dsl.select(st.TAG)
.from(st)
.where(st.SERIES_ID.eq(seriesId))
.fetchInto(st)
.mapNotNull { it.tag }
.toSet()
.fetchSet(st.TAG)
private fun findSharingLabels(seriesId: String) =
dsl.select(sl.LABEL)
.from(sl)
.where(sl.SERIES_ID.eq(seriesId))
.fetchSet(sl.LABEL)
@Transactional
override fun insert(metadata: SeriesMetadata) {
@ -72,10 +75,12 @@ class SeriesMetadataDao(
.set(d.TAGS_LOCK, metadata.tagsLock)
.set(d.TOTAL_BOOK_COUNT, metadata.totalBookCount)
.set(d.TOTAL_BOOK_COUNT_LOCK, metadata.totalBookCountLock)
.set(d.SHARING_LABELS_LOCK, metadata.sharingLabelsLock)
.execute()
insertGenres(metadata)
insertTags(metadata)
insertSharingLabels(metadata)
}
@Transactional
@ -101,6 +106,7 @@ class SeriesMetadataDao(
.set(d.TAGS_LOCK, metadata.tagsLock)
.set(d.TOTAL_BOOK_COUNT, metadata.totalBookCount)
.set(d.TOTAL_BOOK_COUNT_LOCK, metadata.totalBookCountLock)
.set(d.SHARING_LABELS_LOCK, metadata.sharingLabelsLock)
.set(d.LAST_MODIFIED_DATE, LocalDateTime.now(ZoneId.of("Z")))
.where(d.SERIES_ID.eq(metadata.seriesId))
.execute()
@ -113,8 +119,13 @@ class SeriesMetadataDao(
.where(st.SERIES_ID.eq(metadata.seriesId))
.execute()
dsl.deleteFrom(sl)
.where(sl.SERIES_ID.eq(metadata.seriesId))
.execute()
insertGenres(metadata)
insertTags(metadata)
insertSharingLabels(metadata)
}
private fun insertGenres(metadata: SeriesMetadata) {
@ -147,10 +158,26 @@ class SeriesMetadataDao(
}
}
private fun insertSharingLabels(metadata: SeriesMetadata) {
if (metadata.sharingLabels.isNotEmpty()) {
metadata.sharingLabels.chunked(batchSize).forEach { chunk ->
dsl.batch(
dsl.insertInto(sl, sl.SERIES_ID, sl.LABEL)
.values(null as String?, null),
).also { step ->
chunk.forEach {
step.bind(metadata.seriesId, it)
}
}.execute()
}
}
}
@Transactional
override fun delete(seriesId: String) {
dsl.deleteFrom(g).where(g.SERIES_ID.eq(seriesId)).execute()
dsl.deleteFrom(st).where(st.SERIES_ID.eq(seriesId)).execute()
dsl.deleteFrom(sl).where(sl.SERIES_ID.eq(seriesId)).execute()
dsl.deleteFrom(d).where(d.SERIES_ID.eq(seriesId)).execute()
}
@ -160,12 +187,13 @@ class SeriesMetadataDao(
dsl.deleteFrom(g).where(g.SERIES_ID.`in`(dsl.selectTempStrings())).execute()
dsl.deleteFrom(st).where(st.SERIES_ID.`in`(dsl.selectTempStrings())).execute()
dsl.deleteFrom(sl).where(sl.SERIES_ID.`in`(dsl.selectTempStrings())).execute()
dsl.deleteFrom(d).where(d.SERIES_ID.`in`(dsl.selectTempStrings())).execute()
}
override fun count(): Long = dsl.fetchCount(d).toLong()
private fun SeriesMetadataRecord.toDomain(genres: Set<String>, tags: Set<String>) =
private fun SeriesMetadataRecord.toDomain(genres: Set<String>, tags: Set<String>, sharingLabels: Set<String>) =
SeriesMetadata(
status = SeriesMetadata.Status.valueOf(status),
title = title,
@ -180,6 +208,7 @@ class SeriesMetadataDao(
genres = genres,
tags = tags,
totalBookCount = totalBookCount,
sharingLabels = sharingLabels,
statusLock = statusLock,
titleLock = titleLock,
@ -192,6 +221,7 @@ class SeriesMetadataDao(
genresLock = genresLock,
tagsLock = tagsLock,
totalBookCountLock = totalBookCountLock,
sharingLabelsLock = sharingLabelsLock,
seriesId = seriesId,

View file

@ -50,6 +50,8 @@ data class SeriesMetadataDto(
val tagsLock: Boolean,
val totalBookCount: Int?,
val totalBookCountLock: Boolean,
val sharingLabels: Set<String>,
val sharingLabelsLock: Boolean,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val created: LocalDateTime,

View file

@ -62,6 +62,7 @@ class SeriesMetadataDaoTest(
tags = setOf("tag", "another"),
language = "en",
totalBookCount = 5,
sharingLabels = setOf("kids"),
titleLock = true,
titleSortLock = true,
summaryLock = true,
@ -72,6 +73,7 @@ class SeriesMetadataDaoTest(
languageLock = true,
tagsLock = true,
totalBookCountLock = true,
sharingLabelsLock = true,
seriesId = series.id,
)
@ -93,6 +95,7 @@ class SeriesMetadataDaoTest(
assertThat(created.genres).containsAll(metadata.genres)
assertThat(created.tags).containsAll(metadata.tags)
assertThat(created.totalBookCount).isEqualTo(metadata.totalBookCount)
assertThat(created.sharingLabels).containsAll(metadata.sharingLabels)
assertThat(created.titleLock).isEqualTo(metadata.titleLock)
assertThat(created.titleSortLock).isEqualTo(metadata.titleSortLock)
@ -105,6 +108,7 @@ class SeriesMetadataDaoTest(
assertThat(created.languageLock).isEqualTo(metadata.languageLock)
assertThat(created.tagsLock).isEqualTo(metadata.tagsLock)
assertThat(created.totalBookCountLock).isEqualTo(metadata.totalBookCountLock)
assertThat(created.sharingLabelsLock).isEqualTo(metadata.sharingLabelsLock)
}
@Test
@ -135,6 +139,7 @@ class SeriesMetadataDaoTest(
assertThat(created.genres).isEmpty()
assertThat(created.tags).isEmpty()
assertThat(created.totalBookCount).isNull()
assertThat(created.sharingLabels).isEmpty()
assertThat(created.titleLock).isFalse
assertThat(created.titleSortLock).isFalse
@ -147,6 +152,7 @@ class SeriesMetadataDaoTest(
assertThat(created.languageLock).isFalse
assertThat(created.tagsLock).isFalse
assertThat(created.totalBookCountLock).isFalse
assertThat(created.sharingLabelsLock).isFalse
}
@Test
@ -198,6 +204,7 @@ class SeriesMetadataDaoTest(
genres = setOf("Action"),
tags = setOf("tag"),
totalBookCount = 3,
sharingLabels = setOf("kids"),
seriesId = series.id,
)
seriesMetadataDao.insert(metadata)
@ -218,6 +225,7 @@ class SeriesMetadataDaoTest(
genres = setOf("Adventure"),
tags = setOf("Another"),
totalBookCount = 8,
sharingLabels = setOf("adult"),
statusLock = true,
titleLock = true,
titleSortLock = true,
@ -229,6 +237,7 @@ class SeriesMetadataDaoTest(
genresLock = true,
tagsLock = true,
totalBookCountLock = true,
sharingLabelsLock = true,
)
}
@ -251,6 +260,7 @@ class SeriesMetadataDaoTest(
assertThat(modified.genres).containsAll(updated.genres)
assertThat(modified.tags).containsAll(updated.tags)
assertThat(modified.totalBookCount).isEqualTo(updated.totalBookCount)
assertThat(modified.sharingLabels).containsAll(updated.sharingLabels)
assertThat(modified.titleLock).isTrue
assertThat(modified.titleSortLock).isTrue
@ -263,5 +273,6 @@ class SeriesMetadataDaoTest(
assertThat(modified.publisherLock).isTrue
assertThat(modified.tagsLock).isTrue
assertThat(modified.totalBookCountLock).isTrue
assertThat(modified.sharingLabelsLock).isTrue
}
}