Compare commits

...

6 Commits

Author SHA1 Message Date
134b425ce6
Remove unused MediaType
All checks were successful
Push Workflows / docs (push) Successful in 1m52s
Push Workflows / test (push) Successful in 3m2s
Push Workflows / leptos-test (push) Successful in 3m22s
Push Workflows / build (push) Successful in 4m22s
Push Workflows / docker-build (push) Successful in 7m1s
2024-10-06 15:50:58 -04:00
c678d93661
Create ArtistData, impl DashboardTile 2024-10-06 15:50:58 -04:00
c18bf277b9
Create AlbumData, impl DashboardTile 2024-10-06 15:50:57 -04:00
097b1fc491
impl DashboardTile for Songdata 2024-10-06 15:47:22 -04:00
f02a22d805
Format text inside dashboard tiles normally 2024-10-06 15:47:22 -04:00
553e24800b
Refactor DashboardTile into trait 2024-10-06 15:47:18 -04:00
8 changed files with 110 additions and 91 deletions

39
src/albumdata.rs Normal file
View File

@ -0,0 +1,39 @@
use crate::models::Artist;
use crate::components::dashboard_tile::DashboardTile;
use time::Date;
/// Holds information about an album
///
/// Intended to be used in the front-end
pub struct AlbumData {
/// Album id
pub id: i32,
/// Album title
pub title: String,
/// Album artists
pub artists: Vec<Artist>,
/// Album release date
pub release_date: Option<Date>,
/// Path to album image, relative to the root of the web server.
/// For example, `"/assets/images/Album.jpg"`
pub image_path: String,
}
impl DashboardTile for AlbumData {
fn image_path(&self) -> String {
self.image_path.clone()
}
fn title(&self) -> String {
self.title.clone()
}
fn link(&self) -> String {
format!("/album/{}", self.id)
}
fn description(&self) -> Option<String> {
Some(format!("Album • {}", Artist::display_list(&self.artists)))
}
}

32
src/artistdata.rs Normal file
View File

@ -0,0 +1,32 @@
use crate::components::dashboard_tile::DashboardTile;
/// Holds information about an artist
///
/// Intended to be used in the front-end
pub struct ArtistData {
/// Artist id
pub id: i32,
/// Artist name
pub name: String,
/// Path to artist image, relative to the root of the web server.
/// For example, `"/assets/images/Artist.jpg"`
pub image_path: String,
}
impl DashboardTile for ArtistData {
fn image_path(&self) -> String {
self.image_path.clone()
}
fn title(&self) -> String {
self.name.clone()
}
fn link(&self) -> String {
format!("/artist/{}", self.id)
}
fn description(&self) -> Option<String> {
Some("Artist".to_string())
}
}

View File

@ -2,19 +2,17 @@ use leptos::html::Ul;
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use leptos_use::{use_element_size, UseElementSizeReturn, use_scroll, UseScrollReturn}; use leptos_use::{use_element_size, UseElementSizeReturn, use_scroll, UseScrollReturn};
use serde::{Deserialize, Serialize};
use crate::components::dashboard_tile::DashboardTile; use crate::components::dashboard_tile::DashboardTile;
use leptos_icons::*; use leptos_icons::*;
/// A row of dashboard tiles, with a title /// A row of dashboard tiles, with a title
#[derive(Serialize, Deserialize)]
pub struct DashboardRow { pub struct DashboardRow {
pub title: String, pub title: String,
pub tiles: Vec<DashboardTile>, pub tiles: Vec<Box<dyn DashboardTile>>,
} }
impl DashboardRow { impl DashboardRow {
pub fn new(title: String, tiles: Vec<DashboardTile>) -> Self { pub fn new(title: String, tiles: Vec<Box<dyn DashboardTile>>) -> Self {
Self { Self {
title, title,
tiles, tiles,
@ -109,7 +107,7 @@ impl IntoView for DashboardRow {
{self.tiles.into_iter().map(|tile_info| { {self.tiles.into_iter().map(|tile_info| {
view! { view! {
<li> <li>
{ tile_info } { tile_info.into_view() }
</li> </li>
} }
}).collect::<Vec<_>>()} }).collect::<Vec<_>>()}

View File

@ -1,68 +1,26 @@
use leptos::leptos_dom::*; use leptos::leptos_dom::*;
use leptos::*; use leptos::*;
use serde::{Deserialize, Serialize};
use crate::media_type::MediaType;
/// Info representing what will be displayed in a dashboard tile pub trait DashboardTile {
#[derive(Serialize, Deserialize)] fn image_path(&self) -> String;
pub struct DashboardTile { fn title(&self) -> String;
pub image_path: String, fn link(&self) -> String;
pub title: String, fn description(&self) -> Option<String> { None }
pub media_type: Option<MediaType>,
pub artist: Option<String>,
} }
impl DashboardTile { impl IntoView for &dyn DashboardTile {
pub fn new(image_path: String, title: String, media_type: Option<MediaType>, artist: Option<String>) -> Self {
Self {
image_path,
title,
media_type,
artist: artist.map(|artist| artist.to_string()),
}
}
/// Get the description of the dashboard tile
/// Will display the media type, and the artist if it is available and relevant
pub fn description(&self) -> String {
match self.media_type {
Some(MediaType::Song) => {
if let Some(artist) = &self.artist {
format!("{}{}", MediaType::Song.to_string(), artist)
} else {
MediaType::Song.to_string()
}
},
Some(MediaType::Album) => {
if let Some(artist) = &self.artist {
format!("{}{}", MediaType::Album.to_string(), artist)
} else {
MediaType::Album.to_string()
}
},
Some(MediaType::Artist) => {
MediaType::Artist.to_string()
},
None => {
if let Some(artist) = &self.artist {
artist.to_string()
} else {
"".to_string()
}
}
}
}
}
impl IntoView for DashboardTile {
fn into_view(self) -> View { fn into_view(self) -> View {
let description = self.description(); let link = self.link();
view! { view! {
<div class="dashboard-tile"> <div class="dashboard-tile">
<img src={self.image_path} alt="dashboard-tile" /> <a href={link}>
<p class="dashboard-tile-title">{self.title}</p> <img src={self.image_path()} alt="dashboard-tile" />
<p class="dashboard-tile-description">{description}</p> <p class="dashboard-tile-title">{self.title()}</p>
<p class="dashboard-tile-description">
{self.description().unwrap_or_default()}
</p>
</a>
</div> </div>
}.into_view() }.into_view()
} }

View File

@ -1,6 +1,8 @@
pub mod app; pub mod app;
pub mod auth; pub mod auth;
pub mod songdata; pub mod songdata;
pub mod albumdata;
pub mod artistdata;
pub mod playstatus; pub mod playstatus;
pub mod playbar; pub mod playbar;
pub mod database; pub mod database;
@ -13,7 +15,6 @@ pub mod users;
pub mod search; pub mod search;
pub mod fileserv; pub mod fileserv;
pub mod error_template; pub mod error_template;
pub mod media_type;
pub mod api; pub mod api;
pub mod upload; pub mod upload;
pub mod util; pub mod util;

View File

@ -1,20 +0,0 @@
use serde::{Deserialize, Serialize};
/// Differentiates between different types of media
/// Used to display a short text near a corresponging image / title to indicate what type of media it is
#[derive(Serialize, Deserialize)]
pub enum MediaType {
Song,
Album,
Artist,
}
impl ToString for MediaType {
fn to_string(&self) -> String {
match self {
MediaType::Song => "Song".to_string(),
MediaType::Album => "Album".to_string(),
MediaType::Artist => "Artist".to_string(),
}
}
}

View File

@ -1,6 +1,5 @@
use crate::models::{Album, Artist, Song}; use crate::models::{Album, Artist, Song};
use crate::components::dashboard_tile::DashboardTile; use crate::components::dashboard_tile::DashboardTile;
use crate::media_type::MediaType;
use time::Date; use time::Date;
@ -63,13 +62,20 @@ impl TryInto<Song> for SongData {
} }
} }
impl Into<DashboardTile> for SongData { impl DashboardTile for SongData {
fn into(self) -> DashboardTile { fn image_path(&self) -> String {
DashboardTile { self.image_path.clone()
image_path: self.image_path, }
title: self.title,
media_type: Some(MediaType::Song), fn title(&self) -> String {
artist: Some(Artist::display_list(&self.artists)), self.title.clone()
} }
fn link(&self) -> String {
format!("/song/{}", self.id)
}
fn description(&self) -> Option<String> {
Some(format!("Song • {}", Artist::display_list(&self.artists)))
} }
} }

View File

@ -6,6 +6,11 @@
margin-right: 20px; margin-right: 20px;
} }
a {
text-decoration: none;
color: $text-controls-color;
}
p.dashboard-tile-title { p.dashboard-tile-title {
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;