AlbumData Query, API Endpoint, and Integration into AlbumPage
Some checks failed
Push Workflows / build (push) Failing after 1m8s
Push Workflows / docs (push) Successful in 1m4s
Push Workflows / test (push) Successful in 1m47s
Push Workflows / leptos-test (push) Successful in 4m47s
Push Workflows / docker-build (push) Successful in 12m16s

This commit is contained in:
Aidan Westphal 2024-11-20 04:43:53 +00:00
parent 3b6035dd71
commit dd14aa0b4d
6 changed files with 102 additions and 10 deletions

View File

@ -1,11 +1,15 @@
use crate::models::Artist; use crate::models::Artist;
use crate::components::dashboard_tile::DashboardTile; use crate::components::dashboard_tile::DashboardTile;
use crate::components::album_info::AlbumInfo;
use serde::{Serialize, Deserialize};
use chrono::NaiveDate; use chrono::NaiveDate;
/// Holds information about an album /// Holds information about an album
/// ///
/// Intended to be used in the front-end /// Intended to be used in the front-end
#[derive(Serialize, Deserialize, Clone)]
pub struct AlbumData { pub struct AlbumData {
/// Album id /// Album id
pub id: i32, pub id: i32,

View File

@ -1,5 +1,6 @@
use leptos::*; use leptos::*;
use crate::models::Album; use crate::models::Album;
use crate::albumdata::AlbumData;
use crate::songdata::SongData; use crate::songdata::SongData;
use cfg_if::cfg_if; use cfg_if::cfg_if;
@ -13,9 +14,9 @@ cfg_if! {
} }
#[server(endpoint = "album/get")] #[server(endpoint = "album/get")]
pub async fn get_album(id: i32) -> Result<Album, ServerFnError> { pub async fn get_album(id: i32) -> Result<AlbumData, ServerFnError> {
let db_con = &mut get_db_conn(); let db_con = &mut get_db_conn();
let album = Album::get_album(id,db_con) let album = Album::get_album_data(id,db_con)
.map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error getting album: {}", e)))?; .map_err(|e| ServerFnError::<NoCustomError>::ServerError(format!("Error getting album: {}", e)))?;
Ok(album) Ok(album)
} }

View File

@ -8,3 +8,4 @@ pub mod upload;
pub mod song_list; pub mod song_list;
pub mod loading; pub mod loading;
pub mod error; pub mod error;
pub mod album_info;

View File

@ -0,0 +1,27 @@
use leptos::leptos_dom::*;
use leptos::*;
use crate::albumdata::AlbumData;
#[component]
pub fn AlbumInfo(albumdata: AlbumData) -> impl IntoView {
view! {
<div>
<div>
<img src={albumdata.image_path} alt="dashboard-tile" />
</div>
<div>
<p>{albumdata.title}</p>
<div>
{
albumdata.artists.iter().map(|artist| {
view! {
<p>{artist.name.clone()}</p>
}
}).collect::<Vec<_>>()
}
</div>
</div>
</div>
}.into_view()
}

View File

@ -2,6 +2,7 @@ use chrono::{NaiveDate, NaiveDateTime};
use leptos::{server, ServerFnError}; use leptos::{server, ServerFnError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::songdata::SongData; use crate::songdata::SongData;
use crate::albumdata::AlbumData;
use cfg_if::cfg_if; use cfg_if::cfg_if;
@ -539,15 +540,44 @@ impl Album {
/// * `Result<Album, Box<dyn Error>>` - A result indicating success with the desired album, or an error /// * `Result<Album, Box<dyn Error>>` - A result indicating success with the desired album, or an error
/// ///
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
pub fn get_album(album_id: i32, conn: &mut PgPooledConn) -> Result<Album, Box<dyn Error>> { pub fn get_album_data(album_id: i32, conn: &mut PgPooledConn) -> Result<AlbumData, Box<dyn Error>> {
use crate::schema::albums::dsl::*; use crate::schema::*;
use crate::database::get_db_conn; use crate::database::get_db_conn;
let album = albums let album: Vec<(Album, std::option::Option<Artist>)> = albums::table
.find(album_id) .find(album_id)
.first(conn)?; .left_join(songs::table.on(albums::id.nullable().eq(songs::album_id)))
.left_join(song_artists::table.inner_join(artists::table).on(songs::id.eq(song_artists::song_id)))
.select((
albums::all_columns,
artists::all_columns.nullable()
))
.distinct()
.load(conn)?;
Ok(album) let mut artist_list: Vec<Artist> = Vec::new();
for (_, artist) in album {
if let Some(artist) = artist {
artist_list.push(artist);
}
}
// Get info of album
let albuminfo = albums::table
.filter(albums::id.eq(album_id))
.first::<Album>(conn)?;
let img = albuminfo.image_path.unwrap_or("/assets/images/placeholders/MusicPlaceholder.svg".to_string());
let albumdata = AlbumData {
id: albuminfo.id.unwrap(),
title: albuminfo.title,
artists: artist_list,
release_date: albuminfo.release_date,
image_path: img
};
Ok(albumdata)
} }
/// Obtain an album from its albumid /// Obtain an album from its albumid

View File

@ -1,9 +1,10 @@
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use leptos_router::*; use leptos_router::*;
use crate::models::*; use crate::{albumdata, models::*};
use crate::components::song_list::*; use crate::components::song_list::*;
use crate::api::album::*; use crate::api::album::*;
use crate::components::album_info::*;
#[derive(Params, PartialEq)] #[derive(Params, PartialEq)]
@ -32,7 +33,35 @@ pub fn AlbumPage() -> impl IntoView {
}, },
); );
let albumdata = create_resource(
id,
|value| async move {
match value {
Ok(v) => {get_album(v).await},
Err(e) => {Err(ServerFnError::Request(format!("Error getting song data: {}", e).into()))},
}
},
);
view! { view! {
<Suspense
fallback=move || view! { <p>"Loading..."</p> }
>
{move || {
albumdata.with( |albumdata| {
match albumdata {
Some(Ok(s)) => {
view! { <AlbumInfo albumdata=(*s).clone()/> }
},
Some(Err(e)) => {
view! { <div>{format!("Error loading albums: : {}",e)}</div> }.into_view()
},
None => {view! { }.into_view()}
}
})
}}
</Suspense>
<Suspense <Suspense
fallback=move || view! { <p>"Loading..."</p> } fallback=move || view! { <p>"Loading..."</p> }
> >
@ -40,7 +69,7 @@ pub fn AlbumPage() -> impl IntoView {
song_list.with( |song_list| { song_list.with( |song_list| {
match song_list { match song_list {
Some(Ok(s)) => { Some(Ok(s)) => {
view! { <SongList songs=(*s).clone().into()/> }.into_view() view! { <SongList songs=(*s).clone()/> }
}, },
Some(Err(e)) => { Some(Err(e)) => {
view! { <div>{format!("Error loading albums: : {}",e)}</div> }.into_view() view! { <div>{format!("Error loading albums: : {}",e)}</div> }.into_view()