mirror of
https://github.com/Arcadia-Solutions/arcadia.git
synced 2025-12-16 23:14:15 -06:00
feat: better typing on a series page
This commit is contained in:
@@ -5,7 +5,12 @@ use actix_web::{
|
||||
};
|
||||
use arcadia_common::error::Result;
|
||||
use arcadia_storage::{
|
||||
models::series::SeriesAndTitleGroupHierarchyLite, redis::RedisPoolInterface,
|
||||
models::{
|
||||
common::OrderByDirection,
|
||||
series::SeriesAndTitleGroupHierarchyLite,
|
||||
torrent::{TorrentSearch, TorrentSearchOrderByColumn},
|
||||
},
|
||||
redis::RedisPoolInterface,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use utoipa::IntoParams;
|
||||
@@ -31,5 +36,25 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
|
||||
) -> Result<HttpResponse> {
|
||||
let series = arc.pool.find_series(&query.id).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(series))
|
||||
let search_form = TorrentSearch {
|
||||
series_id: Some(query.id),
|
||||
page: 1,
|
||||
page_size: i64::MAX,
|
||||
order_by_column: TorrentSearchOrderByColumn::TitleGroupOriginalReleaseDate,
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
title_group_include_empty_groups: true,
|
||||
title_group_name: None,
|
||||
torrent_reported: None,
|
||||
torrent_staff_checked: None,
|
||||
torrent_created_by_id: None,
|
||||
torrent_snatched_by_id: None,
|
||||
artist_id: None,
|
||||
collage_id: None,
|
||||
};
|
||||
let title_groups_in_series = arc.pool.search_torrents(&search_form, None).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(SeriesAndTitleGroupHierarchyLite {
|
||||
series,
|
||||
title_groups: title_groups_in_series.results,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
artist_id: None,
|
||||
collage_id: None,
|
||||
series_id: None,
|
||||
};
|
||||
let uploaded_torrents = arc
|
||||
.pool
|
||||
|
||||
@@ -53,6 +53,7 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
artist_id: None,
|
||||
collage_id: None,
|
||||
series_id: None,
|
||||
};
|
||||
let uploaded_torrents = arc
|
||||
.pool
|
||||
|
||||
@@ -188,6 +188,7 @@ async fn test_find_torrents_by_external_link(pool: PgPool) {
|
||||
page_size: 50,
|
||||
order_by_column: TorrentSearchOrderByColumn::TorrentCreatedAt,
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
series_id: None,
|
||||
};
|
||||
|
||||
let query = serde_urlencoded::to_string(query).unwrap();
|
||||
@@ -244,6 +245,7 @@ async fn test_find_torrents_by_name(pool: PgPool) {
|
||||
page_size: 50,
|
||||
order_by_column: TorrentSearchOrderByColumn::TorrentCreatedAt,
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
series_id: None,
|
||||
};
|
||||
|
||||
let query = serde_urlencoded::to_string(query).unwrap();
|
||||
@@ -300,6 +302,7 @@ async fn test_find_torrents_no_link_or_name_provided(pool: PgPool) {
|
||||
page_size: 50,
|
||||
order_by_column: TorrentSearchOrderByColumn::TorrentCreatedAt,
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
series_id: None,
|
||||
};
|
||||
|
||||
let query = serde_urlencoded::to_string(query).unwrap();
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT\n jsonb_build_object(\n 'series', to_jsonb(s),\n 'title_groups', COALESCE(\n jsonb_agg(tgd.title_group_data),\n '[]'::jsonb\n )\n ) AS series_and_title_groups\n FROM\n series s\n LEFT JOIN\n title_groups tg ON s.id = tg.series_id\n LEFT JOIN\n get_title_groups_and_edition_group_and_torrents_lite AS tgd ON tg.id = tgd.title_group_id\n WHERE\n s.id = $1\n GROUP BY\n s.id, s.*;\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "series_and_title_groups",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "09337987d244feeb7b38251eac5791f9d499388dd01ab4d369e963ed3ecf3f95"
|
||||
}
|
||||
70
backend/storage/.sqlx/query-9bd01434dd614efca467327891d8038b8f431cf6188a9ed81ee9a925f7c32208.json
generated
Normal file
70
backend/storage/.sqlx/query-9bd01434dd614efca467327891d8038b8f431cf6188a9ed81ee9a925f7c32208.json
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT * FROM series\n WHERE series.id = $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name",
|
||||
"type_info": "Varchar"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "description",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "tags",
|
||||
"type_info": "TextArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "covers",
|
||||
"type_info": "TextArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "banners",
|
||||
"type_info": "TextArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "created_by_id",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "created_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "updated_at",
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9bd01434dd614efca467327891d8038b8f431cf6188a9ed81ee9a925f7c32208"
|
||||
}
|
||||
145
backend/storage/.sqlx/query-baa37b12c8a0b2ff7ac0419faac8bbe6c2763b894727e823d6b343941efcd160.json
generated
Normal file
145
backend/storage/.sqlx/query-baa37b12c8a0b2ff7ac0419faac8bbe6c2763b894727e823d6b343941efcd160.json
generated
Normal file
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT title_group_id AS \"id!\", title_group_name AS \"name!\", title_group_covers AS \"covers!\",\n title_group_category AS \"category!: _\", title_group_content_type AS \"content_type!: _\", title_group_tag_names AS \"tags!\",\n title_group_original_release_date AS \"original_release_date!\", title_group_platform AS \"platform!: _\",\n '[]'::jsonb AS \"edition_groups!: _\",\n '[]'::jsonb AS \"affiliated_artists!: _\"\n\n FROM title_group_hierarchy_lite tgh\n\n WHERE ($4::BOOLEAN IS NULL OR tgh.torrent_staff_checked = $4)\n AND ($5::BOOLEAN IS NULL OR tgh.torrent_reported = $5)\n AND (\n $7::INT IS NULL OR\n -- don't return torrents created as anonymous\n -- unless the requesting user is the uploader\n (tgh.torrent_created_by_id = $7 AND (\n tgh.torrent_created_by_id = $8 OR\n NOT tgh.torrent_uploaded_as_anonymous)\n )\n )\n AND (\n $9::BIGINT IS NULL OR\n EXISTS (SELECT 1 FROM affiliated_artists aa WHERE aa.title_group_id = tgh.title_group_id AND aa.artist_id = $9)\n )\n -- name filter (partial match) or external link match or series name match\n AND (\n $10::TEXT IS NULL OR\n tgh.title_group_name ILIKE '%' || $10 || '%' ESCAPE '\\' OR\n tgh.title_group_series_name ILIKE '%' || $10 || '%' ESCAPE '\\'\n )\n AND ($11::TEXT IS NULL OR $11 = ANY(tgh.title_group_external_links))\n AND ($12::BOOLEAN IS TRUE OR tgh.torrent_id IS NOT NULL)\n AND ($13::BIGINT IS NULL OR tgh.title_group_series_id = $13)\n\n GROUP BY title_group_id, title_group_name, title_group_covers, title_group_category,\n title_group_content_type, title_group_tag_names, title_group_original_release_date, title_group_platform\n\n ORDER BY\n CASE WHEN $1 = 'title_group_original_release_date' AND $6 = 'asc' THEN title_group_original_release_date END ASC,\n CASE WHEN $1 = 'title_group_original_release_date' AND $6 = 'desc' THEN title_group_original_release_date END DESC,\n CASE WHEN $1 = 'torrent_size' AND $6 = 'asc' THEN MAX(torrent_size) END ASC,\n CASE WHEN $1 = 'torrent_size' AND $6 = 'desc' THEN MAX(torrent_size) END DESC,\n CASE WHEN $1 = 'torrent_created_at' AND $6 = 'asc' THEN MAX(torrent_created_at) END ASC,\n CASE WHEN $1 = 'torrent_created_at' AND $6 = 'desc' THEN MAX(torrent_created_at) END DESC,\n title_group_original_release_date ASC\n\n LIMIT $2 OFFSET $3\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id!",
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "name!",
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "covers!",
|
||||
"type_info": "TextArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "category!: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "title_group_category_enum",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"Ep",
|
||||
"Album",
|
||||
"Single",
|
||||
"Soundtrack",
|
||||
"Anthology",
|
||||
"Compilation",
|
||||
"Remix",
|
||||
"Bootleg",
|
||||
"Mixtape",
|
||||
"ConcertRecording",
|
||||
"DjMix",
|
||||
"FeatureFilm",
|
||||
"ShortFilm",
|
||||
"Game",
|
||||
"Program",
|
||||
"Illustrated",
|
||||
"Periodical",
|
||||
"Book",
|
||||
"Article",
|
||||
"Manual",
|
||||
"Other"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "content_type!: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "content_type_enum",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"movie",
|
||||
"video",
|
||||
"tv_show",
|
||||
"music",
|
||||
"podcast",
|
||||
"software",
|
||||
"book",
|
||||
"collection"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "tags!",
|
||||
"type_info": "VarcharArray"
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "original_release_date!",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "platform!: _",
|
||||
"type_info": {
|
||||
"Custom": {
|
||||
"name": "platform_enum",
|
||||
"kind": {
|
||||
"Enum": [
|
||||
"Linux",
|
||||
"MacOS",
|
||||
"Windows",
|
||||
"Xbox"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "edition_groups!: _",
|
||||
"type_info": "Jsonb"
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "affiliated_artists!: _",
|
||||
"type_info": "Jsonb"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Bool",
|
||||
"Bool",
|
||||
"Text",
|
||||
"Int4",
|
||||
"Int4",
|
||||
"Int8",
|
||||
"Text",
|
||||
"Text",
|
||||
"Bool",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "baa37b12c8a0b2ff7ac0419faac8bbe6c2763b894727e823d6b343941efcd160"
|
||||
}
|
||||
@@ -457,6 +457,7 @@ pub struct TorrentSearch {
|
||||
// link to other tables
|
||||
pub artist_id: Option<i64>,
|
||||
pub collage_id: Option<i32>,
|
||||
pub series_id: Option<i64>,
|
||||
// pagination and ordering
|
||||
pub page: i64,
|
||||
pub page_size: i64,
|
||||
|
||||
@@ -160,6 +160,7 @@ impl ConnectionPool {
|
||||
torrent_reported: None,
|
||||
torrent_snatched_by_id: None,
|
||||
torrent_staff_checked: None,
|
||||
series_id: None,
|
||||
order_by_direction: OrderByDirection::Desc,
|
||||
order_by_column: TorrentSearchOrderByColumn::TitleGroupOriginalReleaseDate,
|
||||
collage_id: None,
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use arcadia_common::error::{Error, Result};
|
||||
use serde_json::Value;
|
||||
use sqlx::{query_as_unchecked, query_scalar};
|
||||
use std::borrow::Borrow;
|
||||
|
||||
@@ -32,27 +31,12 @@ impl ConnectionPool {
|
||||
Ok(created_series)
|
||||
}
|
||||
|
||||
pub async fn find_series(&self, series_id: &i64) -> Result<Value> {
|
||||
let found_series = sqlx::query!(
|
||||
pub async fn find_series(&self, series_id: &i64) -> Result<Series> {
|
||||
let series = sqlx::query_as!(
|
||||
Series,
|
||||
r#"
|
||||
SELECT
|
||||
jsonb_build_object(
|
||||
'series', to_jsonb(s),
|
||||
'title_groups', COALESCE(
|
||||
jsonb_agg(tgd.title_group_data),
|
||||
'[]'::jsonb
|
||||
)
|
||||
) AS series_and_title_groups
|
||||
FROM
|
||||
series s
|
||||
LEFT JOIN
|
||||
title_groups tg ON s.id = tg.series_id
|
||||
LEFT JOIN
|
||||
get_title_groups_and_edition_group_and_torrents_lite AS tgd ON tg.id = tgd.title_group_id
|
||||
WHERE
|
||||
s.id = $1
|
||||
GROUP BY
|
||||
s.id, s.*;
|
||||
SELECT * FROM series
|
||||
WHERE series.id = $1
|
||||
"#,
|
||||
series_id
|
||||
)
|
||||
@@ -60,8 +44,7 @@ impl ConnectionPool {
|
||||
.await
|
||||
.map_err(|_| Error::SeriesWithIdNotFound(*series_id))?;
|
||||
|
||||
// Ok(serde_json::from_value(found_series.series_and_groups.unwrap()).unwrap())
|
||||
Ok(found_series.series_and_title_groups.unwrap())
|
||||
Ok(series)
|
||||
}
|
||||
|
||||
pub async fn search_series(&self, form: &SearchSeriesQuery) -> Result<SeriesSearchResponse> {
|
||||
|
||||
@@ -454,6 +454,7 @@ impl ConnectionPool {
|
||||
)
|
||||
AND ($11::TEXT IS NULL OR $11 = ANY(tgh.title_group_external_links))
|
||||
AND ($12::BOOLEAN IS TRUE OR tgh.torrent_id IS NOT NULL)
|
||||
AND ($13::BIGINT IS NULL OR tgh.title_group_series_id = $13)
|
||||
|
||||
GROUP BY title_group_id, title_group_name, title_group_covers, title_group_category,
|
||||
title_group_content_type, title_group_tag_names, title_group_original_release_date, title_group_platform
|
||||
@@ -480,7 +481,8 @@ impl ConnectionPool {
|
||||
form.artist_id,
|
||||
name_filter,
|
||||
external_link_filter,
|
||||
form.title_group_include_empty_groups
|
||||
form.title_group_include_empty_groups,
|
||||
form.series_id
|
||||
)
|
||||
.fetch_all(self.borrow())
|
||||
.await
|
||||
|
||||
@@ -84,6 +84,11 @@ const router = createRouter({
|
||||
},
|
||||
component: () => import('../views/torrent_request/TorrentRequestView.vue'),
|
||||
},
|
||||
{
|
||||
path: '/new-series',
|
||||
name: 'CreateSeries',
|
||||
component: () => import('../views/series/CreateOrEditSeriesView.vue'),
|
||||
},
|
||||
{
|
||||
path: '/series/:id',
|
||||
name: 'Series',
|
||||
|
||||
Reference in New Issue
Block a user