mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-03 19:04:39 -05:00
Implement more query parameters
This commit is contained in:
@@ -9,6 +9,8 @@ package suwayomi.tachidesk.graphql.queries
|
|||||||
|
|
||||||
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||||
import graphql.schema.DataFetchingEnvironment
|
import graphql.schema.DataFetchingEnvironment
|
||||||
|
import org.jetbrains.exposed.sql.SortOrder
|
||||||
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
import org.jetbrains.exposed.sql.selectAll
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import suwayomi.tachidesk.graphql.types.CategoryType
|
import suwayomi.tachidesk.graphql.types.CategoryType
|
||||||
@@ -17,9 +19,6 @@ import java.util.concurrent.CompletableFuture
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO Queries
|
* TODO Queries
|
||||||
* - Sort?
|
|
||||||
* - Query by name
|
|
||||||
* - In ID list
|
|
||||||
* - Paged queries
|
* - Paged queries
|
||||||
*
|
*
|
||||||
* TODO Mutations
|
* TODO Mutations
|
||||||
@@ -36,9 +35,41 @@ class CategoryQuery {
|
|||||||
return dataFetchingEnvironment.getValueFromDataLoader<Int, CategoryType>("CategoryDataLoader", id)
|
return dataFetchingEnvironment.getValueFromDataLoader<Int, CategoryType>("CategoryDataLoader", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun categories(): List<CategoryType> {
|
enum class CategorySort {
|
||||||
|
ID,
|
||||||
|
NAME,
|
||||||
|
ORDER
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CategoriesQueryInput(
|
||||||
|
val sort: CategorySort? = null,
|
||||||
|
val sortOrder: SortOrder? = null,
|
||||||
|
val ids: List<Int>? = null,
|
||||||
|
val query: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
fun categories(input: CategoriesQueryInput? = null): List<CategoryType> {
|
||||||
val results = transaction {
|
val results = transaction {
|
||||||
CategoryTable.selectAll().toList()
|
val res = CategoryTable.selectAll()
|
||||||
|
|
||||||
|
if (input != null) {
|
||||||
|
if (input.ids != null) {
|
||||||
|
res.andWhere { CategoryTable.id inList input.ids }
|
||||||
|
}
|
||||||
|
if (!input.query.isNullOrEmpty()) {
|
||||||
|
res.andWhere { CategoryTable.name like input.query }
|
||||||
|
}
|
||||||
|
val orderBy = when (input.sort) {
|
||||||
|
CategorySort.ID -> CategoryTable.id
|
||||||
|
CategorySort.NAME -> CategoryTable.name
|
||||||
|
CategorySort.ORDER, null -> CategoryTable.order
|
||||||
|
}
|
||||||
|
res.orderBy(orderBy, order = input.sortOrder ?: SortOrder.ASC)
|
||||||
|
} else {
|
||||||
|
res.orderBy(CategoryTable.order)
|
||||||
|
}
|
||||||
|
|
||||||
|
res.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return results.map { CategoryType(it) }
|
return results.map { CategoryType(it) }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ package suwayomi.tachidesk.graphql.queries
|
|||||||
|
|
||||||
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||||
import graphql.schema.DataFetchingEnvironment
|
import graphql.schema.DataFetchingEnvironment
|
||||||
|
import org.jetbrains.exposed.sql.SortOrder
|
||||||
import org.jetbrains.exposed.sql.andWhere
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
import org.jetbrains.exposed.sql.selectAll
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
@@ -18,11 +19,7 @@ import java.util.concurrent.CompletableFuture
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO Queries
|
* TODO Queries
|
||||||
* - Filter by read
|
|
||||||
* - Filter by bookmarked
|
|
||||||
* - Filter by downloaded
|
|
||||||
* - Filter by scanlators
|
* - Filter by scanlators
|
||||||
* - Sort? Upload date, source order, last read, chapter number
|
|
||||||
* - Get page list?
|
* - Get page list?
|
||||||
*
|
*
|
||||||
* TODO Mutations
|
* TODO Mutations
|
||||||
@@ -38,9 +35,23 @@ class ChapterQuery {
|
|||||||
return dataFetchingEnvironment.getValueFromDataLoader<Int, ChapterType>("ChapterDataLoader", id)
|
return dataFetchingEnvironment.getValueFromDataLoader<Int, ChapterType>("ChapterDataLoader", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class ChapterSort {
|
||||||
|
SOURCE_ORDER,
|
||||||
|
NAME,
|
||||||
|
UPLOAD_DATE,
|
||||||
|
CHAPTER_NUMBER,
|
||||||
|
LAST_READ_AT,
|
||||||
|
FETCHED_AT
|
||||||
|
}
|
||||||
|
|
||||||
data class ChapterQueryInput(
|
data class ChapterQueryInput(
|
||||||
val ids: List<Int>? = null,
|
val ids: List<Int>? = null,
|
||||||
val mangaIds: List<Int>? = null,
|
val mangaIds: List<Int>? = null,
|
||||||
|
val read: Boolean? = null,
|
||||||
|
val bookmarked: Boolean? = null,
|
||||||
|
val downloaded: Boolean? = null,
|
||||||
|
val sort: ChapterSort? = null,
|
||||||
|
val sortOrder: SortOrder? = null,
|
||||||
val page: Int? = null,
|
val page: Int? = null,
|
||||||
val count: Int? = null
|
val count: Int? = null
|
||||||
)
|
)
|
||||||
@@ -51,15 +62,36 @@ class ChapterQuery {
|
|||||||
|
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
if (input.mangaIds != null) {
|
if (input.mangaIds != null) {
|
||||||
res = res.andWhere { ChapterTable.manga inList input.mangaIds }
|
res.andWhere { ChapterTable.manga inList input.mangaIds }
|
||||||
}
|
}
|
||||||
if (input.ids != null) {
|
if (input.ids != null) {
|
||||||
res = res.andWhere { ChapterTable.id inList input.ids }
|
res.andWhere { ChapterTable.id inList input.ids }
|
||||||
}
|
}
|
||||||
|
if (input.read != null) {
|
||||||
|
res.andWhere { ChapterTable.isRead eq input.read }
|
||||||
|
}
|
||||||
|
if (input.bookmarked != null) {
|
||||||
|
res.andWhere { ChapterTable.isBookmarked eq input.bookmarked }
|
||||||
|
}
|
||||||
|
if (input.downloaded != null) {
|
||||||
|
res.andWhere { ChapterTable.isDownloaded eq input.downloaded }
|
||||||
|
}
|
||||||
|
val orderBy = when (input.sort) {
|
||||||
|
ChapterSort.SOURCE_ORDER, null -> ChapterTable.sourceOrder
|
||||||
|
ChapterSort.NAME -> ChapterTable.name
|
||||||
|
ChapterSort.UPLOAD_DATE -> ChapterTable.date_upload
|
||||||
|
ChapterSort.CHAPTER_NUMBER -> ChapterTable.chapter_number
|
||||||
|
ChapterSort.LAST_READ_AT -> ChapterTable.lastReadAt
|
||||||
|
ChapterSort.FETCHED_AT -> ChapterTable.fetchedAt
|
||||||
|
}
|
||||||
|
res.orderBy(orderBy, order = input.sortOrder ?: SortOrder.ASC)
|
||||||
|
|
||||||
if (input.count != null) {
|
if (input.count != null) {
|
||||||
val offset = if (input.page == null) 0 else (input.page * input.count).toLong()
|
val offset = if (input.page == null) 0 else (input.page * input.count).toLong()
|
||||||
res = res.limit(input.count, offset)
|
res.limit(input.count, offset)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res.orderBy(ChapterTable.sourceOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
res.toList()
|
res.toList()
|
||||||
|
|||||||
@@ -9,10 +9,13 @@ package suwayomi.tachidesk.graphql.queries
|
|||||||
|
|
||||||
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||||
import graphql.schema.DataFetchingEnvironment
|
import graphql.schema.DataFetchingEnvironment
|
||||||
|
import org.jetbrains.exposed.sql.SortOrder
|
||||||
import org.jetbrains.exposed.sql.andWhere
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.jetbrains.exposed.sql.selectAll
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import suwayomi.tachidesk.graphql.queries.util.GreaterOrLessThanLong
|
||||||
|
import suwayomi.tachidesk.graphql.queries.util.andWhereGreaterOrLessThen
|
||||||
import suwayomi.tachidesk.graphql.types.MangaType
|
import suwayomi.tachidesk.graphql.types.MangaType
|
||||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||||
@@ -21,7 +24,6 @@ import java.util.concurrent.CompletableFuture
|
|||||||
/**
|
/**
|
||||||
* TODO Queries
|
* TODO Queries
|
||||||
* - Query options(optionally query the title, description, or/and)
|
* - Query options(optionally query the title, description, or/and)
|
||||||
* - Sort?
|
|
||||||
*
|
*
|
||||||
* TODO Mutations
|
* TODO Mutations
|
||||||
* - Favorite
|
* - Favorite
|
||||||
@@ -39,9 +41,21 @@ class MangaQuery {
|
|||||||
return dataFetchingEnvironment.getValueFromDataLoader<Int, MangaType>("MangaDataLoader", id)
|
return dataFetchingEnvironment.getValueFromDataLoader<Int, MangaType>("MangaDataLoader", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class MangaSort {
|
||||||
|
ID,
|
||||||
|
TITLE,
|
||||||
|
IN_LIBRARY_AT,
|
||||||
|
LAST_FETCHED_AT
|
||||||
|
}
|
||||||
|
|
||||||
data class MangaQueryInput(
|
data class MangaQueryInput(
|
||||||
val ids: List<Int>? = null,
|
val ids: List<Int>? = null,
|
||||||
val categoryIds: List<Int>? = null,
|
val categoryIds: List<Int>? = null,
|
||||||
|
val sourceIds: List<Long>? = null,
|
||||||
|
val inLibrary: Boolean? = null,
|
||||||
|
val inLibraryAt: GreaterOrLessThanLong? = null,
|
||||||
|
val sort: MangaSort? = null,
|
||||||
|
val sortOrder: SortOrder? = null,
|
||||||
val page: Int? = null,
|
val page: Int? = null,
|
||||||
val count: Int? = null
|
val count: Int? = null
|
||||||
)
|
)
|
||||||
@@ -58,6 +72,27 @@ class MangaQuery {
|
|||||||
if (input.ids != null) {
|
if (input.ids != null) {
|
||||||
res.andWhere { MangaTable.id inList input.ids }
|
res.andWhere { MangaTable.id inList input.ids }
|
||||||
}
|
}
|
||||||
|
if (input.sourceIds != null) {
|
||||||
|
res.andWhere { MangaTable.sourceReference inList input.sourceIds }
|
||||||
|
}
|
||||||
|
if (input.inLibrary != null) {
|
||||||
|
res.andWhere { MangaTable.inLibrary eq input.inLibrary }
|
||||||
|
}
|
||||||
|
if (input.inLibraryAt != null) {
|
||||||
|
res.andWhereGreaterOrLessThen(
|
||||||
|
column = MangaTable.inLibraryAt,
|
||||||
|
greaterOrLessThan = input.inLibraryAt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (input.sort != null) {
|
||||||
|
val orderBy = when (input.sort) {
|
||||||
|
MangaSort.ID -> MangaTable.id
|
||||||
|
MangaSort.TITLE -> MangaTable.title
|
||||||
|
MangaSort.IN_LIBRARY_AT -> MangaTable.inLibraryAt
|
||||||
|
MangaSort.LAST_FETCHED_AT -> MangaTable.lastFetchedAt
|
||||||
|
}
|
||||||
|
res.orderBy(orderBy, order = input.sortOrder ?: SortOrder.ASC)
|
||||||
|
}
|
||||||
if (input.count != null) {
|
if (input.count != null) {
|
||||||
val offset = if (input.page == null) 0 else (input.page * input.count).toLong()
|
val offset = if (input.page == null) 0 else (input.page * input.count).toLong()
|
||||||
res.limit(input.count, offset)
|
res.limit(input.count, offset)
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
package suwayomi.tachidesk.graphql.queries
|
package suwayomi.tachidesk.graphql.queries
|
||||||
|
|
||||||
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.greater
|
|
||||||
import org.jetbrains.exposed.sql.and
|
import org.jetbrains.exposed.sql.and
|
||||||
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
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package suwayomi.tachidesk.graphql.queries.util
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.Column
|
||||||
|
import org.jetbrains.exposed.sql.Query
|
||||||
|
import org.jetbrains.exposed.sql.andWhere
|
||||||
|
|
||||||
|
interface GreaterOrLessThan<T : Comparable<T>> {
|
||||||
|
val value: T
|
||||||
|
val type: GreaterOrLessThanType
|
||||||
|
}
|
||||||
|
|
||||||
|
data class GreaterOrLessThanLong(
|
||||||
|
override val value: Long,
|
||||||
|
override val type: GreaterOrLessThanType
|
||||||
|
) : GreaterOrLessThan<Long>
|
||||||
|
|
||||||
|
enum class GreaterOrLessThanType {
|
||||||
|
GREATER_THAN,
|
||||||
|
GREATER_THAN_OR_EQ,
|
||||||
|
LESS_THAN,
|
||||||
|
LESS_THAN_OR_EQ
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Comparable<T>> Query.andWhereGreaterOrLessThen(
|
||||||
|
column: Column<T>,
|
||||||
|
greaterOrLessThan: GreaterOrLessThan<T>
|
||||||
|
) {
|
||||||
|
when (greaterOrLessThan.type) {
|
||||||
|
GreaterOrLessThanType.GREATER_THAN -> andWhere {
|
||||||
|
column greater greaterOrLessThan.value // toValue()
|
||||||
|
}
|
||||||
|
GreaterOrLessThanType.GREATER_THAN_OR_EQ -> andWhere {
|
||||||
|
column greaterEq greaterOrLessThan.value // toValue()
|
||||||
|
}
|
||||||
|
GreaterOrLessThanType.LESS_THAN -> andWhere {
|
||||||
|
column less greaterOrLessThan.value // toValue()
|
||||||
|
}
|
||||||
|
GreaterOrLessThanType.LESS_THAN_OR_EQ -> andWhere {
|
||||||
|
column lessEq greaterOrLessThan.value // toValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user