Compare commits
6 Commits
2793391f00
...
134b425ce6
Author | SHA1 | Date | |
---|---|---|---|
134b425ce6 | |||
c678d93661 | |||
c18bf277b9 | |||
097b1fc491 | |||
f02a22d805 | |||
553e24800b |
39
src/albumdata.rs
Normal file
39
src/albumdata.rs
Normal 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
32
src/artistdata.rs
Normal 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())
|
||||||
|
}
|
||||||
|
}
|
@ -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<_>>()}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user