AlbumData Query, API Endpoint, and Integration into AlbumPage
This commit is contained in:
parent
3b6035dd71
commit
dd14aa0b4d
@ -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,
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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;
|
27
src/components/album_info.rs
Normal file
27
src/components/album_info.rs
Normal 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()
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user