mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2025-12-21 12:02:35 +01:00
Add default category to the database (#561)
* Add default category to the database * Fix getCategorySize
This commit is contained in:
@@ -12,6 +12,7 @@ import org.dataloader.DataLoader
|
|||||||
import org.dataloader.DataLoaderFactory
|
import org.dataloader.DataLoaderFactory
|
||||||
import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
|
import org.jetbrains.exposed.sql.Slf4jSqlDebugLogger
|
||||||
import org.jetbrains.exposed.sql.addLogger
|
import org.jetbrains.exposed.sql.addLogger
|
||||||
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import suwayomi.tachidesk.graphql.types.MangaNodeList
|
import suwayomi.tachidesk.graphql.types.MangaNodeList
|
||||||
@@ -42,10 +43,23 @@ class MangaForCategoryDataLoader : KotlinDataLoader<Int, MangaNodeList> {
|
|||||||
future {
|
future {
|
||||||
transaction {
|
transaction {
|
||||||
addLogger(Slf4jSqlDebugLogger)
|
addLogger(Slf4jSqlDebugLogger)
|
||||||
val itemsByRef = CategoryMangaTable.innerJoin(MangaTable).select { CategoryMangaTable.category inList ids }
|
val itemsByRef = if (ids.contains(0)) {
|
||||||
|
MangaTable
|
||||||
|
.leftJoin(CategoryMangaTable)
|
||||||
|
.select { MangaTable.inLibrary eq true }
|
||||||
|
.andWhere { CategoryMangaTable.manga.isNull() }
|
||||||
|
.map { MangaType(it) }
|
||||||
|
.let {
|
||||||
|
mapOf(0 to it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyMap()
|
||||||
|
} + CategoryMangaTable.innerJoin(MangaTable)
|
||||||
|
.select { CategoryMangaTable.category inList ids }
|
||||||
.map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) }
|
.map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) }
|
||||||
.groupBy { it.first }
|
.groupBy { it.first }
|
||||||
.mapValues { it.value.map { pair -> pair.second } }
|
.mapValues { it.value.map { pair -> pair.second } }
|
||||||
|
|
||||||
ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() }
|
ids.map { (itemsByRef[it] ?: emptyList()).toNodeList() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package suwayomi.tachidesk.manga.impl
|
|||||||
import org.jetbrains.exposed.sql.SortOrder
|
import org.jetbrains.exposed.sql.SortOrder
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||||
import org.jetbrains.exposed.sql.and
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
import org.jetbrains.exposed.sql.deleteWhere
|
import org.jetbrains.exposed.sql.deleteWhere
|
||||||
import org.jetbrains.exposed.sql.insert
|
import org.jetbrains.exposed.sql.insert
|
||||||
import org.jetbrains.exposed.sql.insertAndGetId
|
import org.jetbrains.exposed.sql.insertAndGetId
|
||||||
@@ -19,7 +20,6 @@ import org.jetbrains.exposed.sql.transactions.transaction
|
|||||||
import org.jetbrains.exposed.sql.update
|
import org.jetbrains.exposed.sql.update
|
||||||
import suwayomi.tachidesk.manga.impl.CategoryManga.removeMangaFromCategory
|
import suwayomi.tachidesk.manga.impl.CategoryManga.removeMangaFromCategory
|
||||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||||
import suwayomi.tachidesk.manga.model.dataclass.IncludeInUpdate
|
|
||||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||||
import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
|
import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
|
||||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||||
@@ -54,7 +54,7 @@ object Category {
|
|||||||
transaction {
|
transaction {
|
||||||
CategoryTable.update({ CategoryTable.id eq categoryId }) {
|
CategoryTable.update({ CategoryTable.id eq categoryId }) {
|
||||||
if (name != null && !name.equals(DEFAULT_CATEGORY_NAME, ignoreCase = true)) it[CategoryTable.name] = name
|
if (name != null && !name.equals(DEFAULT_CATEGORY_NAME, ignoreCase = true)) it[CategoryTable.name] = name
|
||||||
if (isDefault != null) it[CategoryTable.isDefault] = isDefault
|
if (isDefault != null && categoryId != DEFAULT_CATEGORY_ID) it[CategoryTable.isDefault] = isDefault
|
||||||
if (includeInUpdate != null) it[CategoryTable.includeInUpdate] = includeInUpdate
|
if (includeInUpdate != null) it[CategoryTable.includeInUpdate] = includeInUpdate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,7 @@ object Category {
|
|||||||
* Move the category from order number `from` to `to`
|
* Move the category from order number `from` to `to`
|
||||||
*/
|
*/
|
||||||
fun reorderCategory(from: Int, to: Int) {
|
fun reorderCategory(from: Int, to: Int) {
|
||||||
|
if (from == 0 || to == 0) return
|
||||||
transaction {
|
transaction {
|
||||||
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList()
|
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList()
|
||||||
categories.add(to - 1, categories.removeAt(from - 1))
|
categories.add(to - 1, categories.removeAt(from - 1))
|
||||||
@@ -76,6 +77,7 @@ object Category {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeCategory(categoryId: Int) {
|
fun removeCategory(categoryId: Int) {
|
||||||
|
if (categoryId == DEFAULT_CATEGORY_ID) return
|
||||||
transaction {
|
transaction {
|
||||||
CategoryMangaTable.select { CategoryMangaTable.category eq categoryId }.forEach {
|
CategoryMangaTable.select { CategoryMangaTable.category eq categoryId }.forEach {
|
||||||
removeMangaFromCategory(it[CategoryMangaTable.manga].value, categoryId)
|
removeMangaFromCategory(it[CategoryMangaTable.manga].value, categoryId)
|
||||||
@@ -97,24 +99,32 @@ object Category {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun needsDefaultCategory() = transaction {
|
||||||
|
MangaTable
|
||||||
|
.leftJoin(CategoryMangaTable)
|
||||||
|
.select { MangaTable.inLibrary eq true }
|
||||||
|
.andWhere { CategoryMangaTable.manga.isNull() }
|
||||||
|
.empty()
|
||||||
|
.not()
|
||||||
|
}
|
||||||
|
|
||||||
const val DEFAULT_CATEGORY_ID = 0
|
const val DEFAULT_CATEGORY_ID = 0
|
||||||
const val DEFAULT_CATEGORY_NAME = "Default"
|
const val DEFAULT_CATEGORY_NAME = "Default"
|
||||||
private fun addDefaultIfNecessary(categories: List<CategoryDataClass>): List<CategoryDataClass> {
|
|
||||||
val defaultCategorySize = MangaTable.select { (MangaTable.inLibrary eq true) and (MangaTable.defaultCategory eq true) }.count().toInt()
|
|
||||||
return if (defaultCategorySize > 0) {
|
|
||||||
listOf(CategoryDataClass(DEFAULT_CATEGORY_ID, 0, DEFAULT_CATEGORY_NAME, true, defaultCategorySize, IncludeInUpdate.UNSET)) + categories
|
|
||||||
} else {
|
|
||||||
categories
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCategoryList(): List<CategoryDataClass> {
|
fun getCategoryList(): List<CategoryDataClass> {
|
||||||
return transaction {
|
return transaction {
|
||||||
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).map {
|
CategoryTable.selectAll()
|
||||||
CategoryTable.toDataClass(it)
|
.orderBy(CategoryTable.order to SortOrder.ASC)
|
||||||
}
|
.let {
|
||||||
|
if (needsDefaultCategory()) {
|
||||||
addDefaultIfNecessary(categories)
|
it
|
||||||
|
} else {
|
||||||
|
it.andWhere { CategoryTable.id neq DEFAULT_CATEGORY_ID }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
CategoryTable.toDataClass(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,8 +138,15 @@ object Category {
|
|||||||
|
|
||||||
fun getCategorySize(categoryId: Int): Int {
|
fun getCategorySize(categoryId: Int): Int {
|
||||||
return transaction {
|
return transaction {
|
||||||
CategoryMangaTable.select {
|
if (categoryId == DEFAULT_CATEGORY_ID) {
|
||||||
CategoryMangaTable.category eq categoryId
|
MangaTable
|
||||||
|
.leftJoin(CategoryMangaTable)
|
||||||
|
.select { MangaTable.inLibrary eq true }
|
||||||
|
.andWhere { CategoryMangaTable.manga.isNull() }
|
||||||
|
} else {
|
||||||
|
CategoryMangaTable.select {
|
||||||
|
CategoryMangaTable.category eq categoryId
|
||||||
|
}
|
||||||
}.count().toInt()
|
}.count().toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import suwayomi.tachidesk.manga.model.table.toDataClass
|
|||||||
|
|
||||||
object CategoryManga {
|
object CategoryManga {
|
||||||
fun addMangaToCategory(mangaId: Int, categoryId: Int) {
|
fun addMangaToCategory(mangaId: Int, categoryId: Int) {
|
||||||
|
if (categoryId == DEFAULT_CATEGORY_ID) return
|
||||||
fun notAlreadyInCategory() = CategoryMangaTable.select { (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) }.isEmpty()
|
fun notAlreadyInCategory() = CategoryMangaTable.select { (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) }.isEmpty()
|
||||||
|
|
||||||
transaction {
|
transaction {
|
||||||
@@ -50,6 +51,7 @@ object CategoryManga {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeMangaFromCategory(mangaId: Int, categoryId: Int) {
|
fun removeMangaFromCategory(mangaId: Int, categoryId: Int) {
|
||||||
|
if (categoryId == DEFAULT_CATEGORY_ID) return
|
||||||
transaction {
|
transaction {
|
||||||
CategoryMangaTable.deleteWhere { (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) }
|
CategoryMangaTable.deleteWhere { (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) }
|
||||||
if (CategoryMangaTable.select { CategoryMangaTable.manga eq mangaId }.count() == 0L) {
|
if (CategoryMangaTable.select { CategoryMangaTable.manga eq mangaId }.count() == 0L) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package suwayomi.tachidesk.manga.impl
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
import org.jetbrains.exposed.sql.insert
|
import org.jetbrains.exposed.sql.insert
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
@@ -22,7 +23,9 @@ object Library {
|
|||||||
val manga = getManga(mangaId)
|
val manga = getManga(mangaId)
|
||||||
if (!manga.inLibrary) {
|
if (!manga.inLibrary) {
|
||||||
transaction {
|
transaction {
|
||||||
val defaultCategories = CategoryTable.select { CategoryTable.isDefault eq true }.toList()
|
val defaultCategories = CategoryTable.select {
|
||||||
|
(CategoryTable.isDefault eq true) and (CategoryTable.id neq Category.DEFAULT_CATEGORY_ID)
|
||||||
|
}.toList()
|
||||||
val existingCategories = CategoryMangaTable.select { CategoryMangaTable.manga eq mangaId }.toList()
|
val existingCategories = CategoryMangaTable.select { CategoryMangaTable.manga eq mangaId }.toList()
|
||||||
|
|
||||||
MangaTable.update({ MangaTable.id eq manga.id }) {
|
MangaTable.update({ MangaTable.id eq manga.id }) {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package suwayomi.tachidesk.server.database.migration
|
||||||
|
|
||||||
|
import de.neonew.exposed.migrations.helpers.SQLMigration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
@Suppress("ClassName", "unused")
|
||||||
|
class M0027_AddDefaultCategory : SQLMigration() {
|
||||||
|
override val sql: String = """
|
||||||
|
INSERT INTO CATEGORY (ID, NAME, IS_DEFAULT, "ORDER", INCLUDE_IN_UPDATE) VALUES (0, 'Default', TRUE, 0, -1)
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user