summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorWolfgang Müller2025-02-20 14:27:14 +0100
committerWolfgang Müller2025-02-20 19:51:04 +0100
commitc6bf35aea63969b90463d6e70cb02ed61e4e3270 (patch)
tree1e650689385e23b204754dd1bba156654f95612d
parent39ecba8f6c5a2bc3b4f0629aecac99560c270539 (diff)
downloadhircine-c6bf35aea63969b90463d6e70cb02ed61e4e3270.tar.gz
Add remaining association count sort options
Now that we have all association counts mapped to their respective models we can easily allow sorting on them as well.
-rw-r--r--frontend/src/gql/graphql.ts13
-rw-r--r--frontend/src/lib/Enums.ts11
-rw-r--r--src/hircine/api/sort.py11
-rw-r--r--tests/api/test_sort.py75
4 files changed, 108 insertions, 2 deletions
diff --git a/frontend/src/gql/graphql.ts b/frontend/src/gql/graphql.ts
index 63f2c55..ac8512a 100644
--- a/frontend/src/gql/graphql.ts
+++ b/frontend/src/gql/graphql.ts
@@ -140,6 +140,7 @@ export type ArtistFilterResult = {
export type ArtistResponse = Artist | IdNotFoundError;
export enum ArtistSort {
+ ComicCount = 'COMIC_COUNT',
CreatedAt = 'CREATED_AT',
Name = 'NAME',
Random = 'RANDOM',
@@ -226,6 +227,7 @@ export type CharacterFilterResult = {
export type CharacterResponse = Character | IdNotFoundError;
export enum CharacterSort {
+ ComicCount = 'COMIC_COUNT',
CreatedAt = 'CREATED_AT',
Name = 'NAME',
Random = 'RANDOM',
@@ -273,6 +275,7 @@ export type CircleFilterResult = {
export type CircleResponse = Circle | IdNotFoundError;
export enum CircleSort {
+ ComicCount = 'COMIC_COUNT',
CreatedAt = 'CREATED_AT',
Name = 'NAME',
Random = 'RANDOM',
@@ -355,6 +358,9 @@ export type ComicScraper = {
};
export enum ComicSort {
+ ArtistCount = 'ARTIST_COUNT',
+ CharacterCount = 'CHARACTER_COUNT',
+ CircleCount = 'CIRCLE_COUNT',
CreatedAt = 'CREATED_AT',
Date = 'DATE',
OriginalTitle = 'ORIGINAL_TITLE',
@@ -362,7 +368,8 @@ export enum ComicSort {
Random = 'RANDOM',
TagCount = 'TAG_COUNT',
Title = 'TITLE',
- UpdatedAt = 'UPDATED_AT'
+ UpdatedAt = 'UPDATED_AT',
+ WorldCount = 'WORLD_COUNT'
}
export type ComicSortInput = {
@@ -895,6 +902,7 @@ export enum NamespaceSort {
Name = 'NAME',
Random = 'RANDOM',
SortName = 'SORT_NAME',
+ TagCount = 'TAG_COUNT',
UpdatedAt = 'UPDATED_AT'
}
@@ -1196,8 +1204,10 @@ export type TagFilterResult = {
export type TagResponse = FullTag | IdNotFoundError;
export enum TagSort {
+ ComicCount = 'COMIC_COUNT',
CreatedAt = 'CREATED_AT',
Name = 'NAME',
+ NamespaceCount = 'NAMESPACE_COUNT',
Random = 'RANDOM',
UpdatedAt = 'UPDATED_AT'
}
@@ -1362,6 +1372,7 @@ export type WorldFilterResult = {
export type WorldResponse = IdNotFoundError | World;
export enum WorldSort {
+ ComicCount = 'COMIC_COUNT',
CreatedAt = 'CREATED_AT',
Name = 'NAME',
Random = 'RANDOM',
diff --git a/frontend/src/lib/Enums.ts b/frontend/src/lib/Enums.ts
index 5133d49..292ed7d 100644
--- a/frontend/src/lib/Enums.ts
+++ b/frontend/src/lib/Enums.ts
@@ -73,6 +73,10 @@ export const ComicSortLabel: Record<ComicSort, string> = {
[ComicSort.CreatedAt]: 'Created At',
[ComicSort.UpdatedAt]: 'Updated At',
[ComicSort.TagCount]: 'Tag Count',
+ [ComicSort.ArtistCount]: 'Artist Count',
+ [ComicSort.CharacterCount]: 'Character Count',
+ [ComicSort.CircleCount]: 'Circle Count',
+ [ComicSort.WorldCount]: 'World Count',
[ComicSort.PageCount]: 'Page Count',
[ComicSort.Random]: 'Random'
};
@@ -81,6 +85,7 @@ export const ArtistSortLabel: Record<ArtistSort, string> = {
[ArtistSort.Name]: 'Name',
[ArtistSort.CreatedAt]: 'Created At',
[ArtistSort.UpdatedAt]: 'Updated At',
+ [ArtistSort.ComicCount]: 'Comic Count',
[ArtistSort.Random]: 'Random'
};
@@ -88,6 +93,7 @@ export const CharacterSortLabel: Record<CharacterSort, string> = {
[CharacterSort.Name]: 'Name',
[CharacterSort.CreatedAt]: 'Created At',
[CharacterSort.UpdatedAt]: 'Updated At',
+ [CharacterSort.ComicCount]: 'Comic Count',
[CharacterSort.Random]: 'Random'
};
@@ -95,6 +101,7 @@ export const CircleSortLabel: Record<CircleSort, string> = {
[CircleSort.Name]: 'Name',
[CircleSort.CreatedAt]: 'Created At',
[CircleSort.UpdatedAt]: 'Updated At',
+ [CircleSort.ComicCount]: 'Comic Count',
[CircleSort.Random]: 'Random'
};
@@ -103,12 +110,15 @@ export const NamespaceSortLabel: Record<NamespaceSort, string> = {
[NamespaceSort.SortName]: 'Sort Name',
[NamespaceSort.CreatedAt]: 'Created At',
[NamespaceSort.UpdatedAt]: 'Updated At',
+ [NamespaceSort.TagCount]: 'Tag Count',
[NamespaceSort.Random]: 'Random'
};
export const TagSortLabel: Record<TagSort, string> = {
[TagSort.Name]: 'Name',
[TagSort.CreatedAt]: 'Created At',
+ [TagSort.ComicCount]: 'Comic Count',
+ [TagSort.NamespaceCount]: 'Namespace Count',
[TagSort.UpdatedAt]: 'Updated At',
[TagSort.Random]: 'Random'
};
@@ -117,6 +127,7 @@ export const WorldSortLabel: Record<WorldSort, string> = {
[WorldSort.Name]: 'Name',
[WorldSort.CreatedAt]: 'Created At',
[WorldSort.UpdatedAt]: 'Updated At',
+ [WorldSort.ComicCount]: 'Comic Count',
[WorldSort.Random]: 'Random'
};
diff --git a/src/hircine/api/sort.py b/src/hircine/api/sort.py
index 17043a6..a4ccaf1 100644
--- a/src/hircine/api/sort.py
+++ b/src/hircine/api/sort.py
@@ -22,6 +22,10 @@ class ComicSort(enum.Enum):
DATE = strawberry.enum_value(models.Comic.date)
CREATED_AT = strawberry.enum_value(models.Comic.created_at)
UPDATED_AT = strawberry.enum_value(models.Comic.updated_at)
+ ARTIST_COUNT = strawberry.enum_value(models.Comic.artist_count)
+ CHARACTER_COUNT = strawberry.enum_value(models.Comic.character_count)
+ CIRCLE_COUNT = strawberry.enum_value(models.Comic.circle_count)
+ WORLD_COUNT = strawberry.enum_value(models.Comic.world_count)
TAG_COUNT = strawberry.enum_value(models.Comic.tag_count)
PAGE_COUNT = strawberry.enum_value(models.Comic.page_count)
RANDOM = "Random"
@@ -41,6 +45,7 @@ class ArtistSort(enum.Enum):
NAME = strawberry.enum_value(models.Artist.name)
CREATED_AT = strawberry.enum_value(models.Artist.created_at)
UPDATED_AT = strawberry.enum_value(models.Artist.updated_at)
+ COMIC_COUNT = strawberry.enum_value(models.Artist.comic_count)
RANDOM = "Random"
@@ -49,6 +54,7 @@ class CharacterSort(enum.Enum):
NAME = strawberry.enum_value(models.Character.name)
CREATED_AT = strawberry.enum_value(models.Character.created_at)
UPDATED_AT = strawberry.enum_value(models.Character.updated_at)
+ COMIC_COUNT = strawberry.enum_value(models.Character.comic_count)
RANDOM = "Random"
@@ -57,6 +63,7 @@ class CircleSort(enum.Enum):
NAME = strawberry.enum_value(models.Circle.name)
CREATED_AT = strawberry.enum_value(models.Circle.created_at)
UPDATED_AT = strawberry.enum_value(models.Circle.updated_at)
+ COMIC_COUNT = strawberry.enum_value(models.Circle.comic_count)
RANDOM = "Random"
@@ -66,6 +73,7 @@ class NamespaceSort(enum.Enum):
NAME = strawberry.enum_value(models.Namespace.name)
CREATED_AT = strawberry.enum_value(models.Namespace.created_at)
UPDATED_AT = strawberry.enum_value(models.Namespace.updated_at)
+ TAG_COUNT = strawberry.enum_value(models.Namespace.tag_count)
RANDOM = "Random"
@@ -74,6 +82,8 @@ class TagSort(enum.Enum):
NAME = strawberry.enum_value(models.Tag.name)
CREATED_AT = strawberry.enum_value(models.Tag.created_at)
UPDATED_AT = strawberry.enum_value(models.Tag.updated_at)
+ COMIC_COUNT = strawberry.enum_value(models.Tag.comic_count)
+ NAMESPACE_COUNT = strawberry.enum_value(models.Tag.namespace_count)
RANDOM = "Random"
@@ -82,6 +92,7 @@ class WorldSort(enum.Enum):
NAME = strawberry.enum_value(models.World.name)
CREATED_AT = strawberry.enum_value(models.World.created_at)
UPDATED_AT = strawberry.enum_value(models.World.updated_at)
+ COMIC_COUNT = strawberry.enum_value(models.World.comic_count)
RANDOM = "Random"
diff --git a/tests/api/test_sort.py b/tests/api/test_sort.py
index 404e3d6..65a4990 100644
--- a/tests/api/test_sort.py
+++ b/tests/api/test_sort.py
@@ -1,7 +1,7 @@
import pytest
from conftest import DB, Response
-from hircine.db.models import Namespace
+from hircine.db.models import Namespace, Tag
@pytest.fixture
@@ -23,6 +23,24 @@ def query_comic_sort(execute_sort):
@pytest.fixture
+def query_artist_sort(execute_sort):
+ query = """
+ query artists($sort: ArtistSortInput) {
+ artists(sort: $sort) {
+ __typename
+ count
+ edges {
+ id
+ name
+ }
+ }
+ }
+ """
+
+ return execute_sort(query)
+
+
+@pytest.fixture
def query_namespace_sort(execute_sort):
query = """
query namespaces($sort: NamespaceSortInput) {
@@ -88,6 +106,31 @@ async def test_query_comics_sort_tag_count(gen_comic, query_comic_sort, sort, re
assert ids == [edge["id"] for edge in response.edges]
+@pytest.mark.parametrize(
+ "sort,reverse,expect",
+ [
+ ({"on": "COMIC_COUNT"}, False, [2, 3, 1, 4]),
+ ({"on": "COMIC_COUNT", "direction": "DESCENDING"}, True, [1, 4, 2, 3]),
+ ({"on": "COMIC_COUNT", "direction": "ASCENDING"}, False, [2, 3, 1, 4]),
+ ],
+ ids=[
+ "ascending (default)",
+ "descending",
+ "ascending",
+ ],
+)
+@pytest.mark.anyio
+async def test_query_artists_sort_comic_count(
+ gen_comic, query_artist_sort, sort, reverse, expect
+):
+ await DB.add_all(*gen_comic)
+
+ response = Response(await query_artist_sort(sort))
+ response.assert_is("ArtistFilterResult")
+
+ assert expect == [edge["id"] for edge in response.edges]
+
+
@pytest.mark.anyio
async def test_query_comics_sort_random(gen_comic, query_comic_sort):
comics = await DB.add_all(*gen_comic)
@@ -136,3 +179,33 @@ async def test_query_namespace_sort_sort_name(query_namespace_sort):
response.assert_is("NamespaceFilterResult")
assert [edge["name"] for edge in response.edges] == ["two", "one"]
+
+@pytest.mark.parametrize(
+ "sort,reverse,expect",
+ [
+ ({"on": "TAG_COUNT"}, False, [2, 1]),
+ ({"on": "TAG_COUNT", "direction": "DESCENDING"}, True, [1, 2]),
+ ({"on": "TAG_COUNT", "direction": "ASCENDING"}, False, [2, 1]),
+ ],
+ ids=[
+ "ascending (default)",
+ "descending",
+ "ascending",
+ ],
+)
+@pytest.mark.anyio
+async def test_query_namespace_sort_tag_count(
+ gen_comic, query_namespace_sort, sort, reverse, expect
+):
+ namespace_foo = Namespace(id=1, name="foo")
+ namespace_bar = Namespace(id=2, name="bar")
+
+ tag_foo = Tag(id=1, name="foo", namespaces=[namespace_foo])
+ tag_bar = Tag(id=2, name="bar", namespaces=[namespace_foo, namespace_bar])
+
+ await DB.add_all(tag_foo, tag_bar)
+
+ response = Response(await query_namespace_sort(sort))
+ response.assert_is("NamespaceFilterResult")
+
+ assert expect == [edge["id"] for edge in response.edges]