Switch to chrono instead of time
This commit is contained in:
parent
820a1d816a
commit
6dcbba2588
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -378,13 +378,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.37"
|
version = "0.4.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e"
|
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-targets 0.52.4",
|
"windows-targets 0.52.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -690,11 +693,11 @@ checksum = "03fc05c17098f21b89bc7d98fe1dd3cce2c11c2ad8e145f2a44fe08ed28eb559"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
"diesel_derives",
|
"diesel_derives",
|
||||||
"itoa",
|
"itoa",
|
||||||
"pq-sys",
|
"pq-sys",
|
||||||
"r2d2",
|
"r2d2",
|
||||||
"time",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1834,6 +1837,7 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"axum-login",
|
"axum-login",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"chrono",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
@ -1857,7 +1861,6 @@ dependencies = [
|
|||||||
"server_fn",
|
"server_fn",
|
||||||
"symphonia",
|
"symphonia",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower 0.5.1",
|
"tower 0.5.1",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
@ -19,11 +19,10 @@ wasm-bindgen = { version = "=0.2.93", default-features = false, optional = true
|
|||||||
leptos_icons = { version = "0.3.0" }
|
leptos_icons = { version = "0.3.0" }
|
||||||
icondata = { version = "0.3.0" }
|
icondata = { version = "0.3.0" }
|
||||||
dotenv = { version = "0.15.0", optional = true }
|
dotenv = { version = "0.15.0", optional = true }
|
||||||
diesel = { version = "2.1.4", features = ["postgres", "r2d2", "time"], default-features = false, optional = true }
|
diesel = { version = "2.1.4", features = ["postgres", "r2d2", "chrono"], default-features = false, optional = true }
|
||||||
lazy_static = { version = "1.4.0", optional = true }
|
lazy_static = { version = "1.4.0", optional = true }
|
||||||
serde = { version = "1.0.195", features = ["derive"], default-features = false }
|
serde = { version = "1.0.195", features = ["derive"], default-features = false }
|
||||||
openssl = { version = "0.10.63", optional = true }
|
openssl = { version = "0.10.63", optional = true }
|
||||||
time = { version = "0.3.34", features = ["serde"], default-features = false }
|
|
||||||
diesel_migrations = { version = "2.1.0", optional = true }
|
diesel_migrations = { version = "2.1.0", optional = true }
|
||||||
pbkdf2 = { version = "0.12.2", features = ["simple"], optional = true }
|
pbkdf2 = { version = "0.12.2", features = ["simple"], optional = true }
|
||||||
tokio = { version = "1", optional = true, features = ["rt-multi-thread"] }
|
tokio = { version = "1", optional = true, features = ["rt-multi-thread"] }
|
||||||
@ -42,6 +41,7 @@ flexi_logger = { version = "0.28.0", optional = true, default-features = false }
|
|||||||
web-sys = "0.3.69"
|
web-sys = "0.3.69"
|
||||||
leptos-use = "0.13.5"
|
leptos-use = "0.13.5"
|
||||||
image-convert = { version = "0.18.0", optional = true, default-features = false }
|
image-convert = { version = "0.18.0", optional = true, default-features = false }
|
||||||
|
chrono = { version = "0.4.38", default-features = false, features = ["serde", "clock"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
hydrate = [
|
hydrate = [
|
||||||
@ -50,6 +50,7 @@ hydrate = [
|
|||||||
"leptos_router/hydrate",
|
"leptos_router/hydrate",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
"chrono/wasmbind",
|
||||||
]
|
]
|
||||||
ssr = [
|
ssr = [
|
||||||
"dep:leptos_axum",
|
"dep:leptos_axum",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::models::Artist;
|
use crate::models::Artist;
|
||||||
use crate::components::dashboard_tile::DashboardTile;
|
use crate::components::dashboard_tile::DashboardTile;
|
||||||
|
|
||||||
use time::Date;
|
use chrono::NaiveDate;
|
||||||
|
|
||||||
/// Holds information about an album
|
/// Holds information about an album
|
||||||
///
|
///
|
||||||
@ -14,7 +14,7 @@ pub struct AlbumData {
|
|||||||
/// Album artists
|
/// Album artists
|
||||||
pub artists: Vec<Artist>,
|
pub artists: Vec<Artist>,
|
||||||
/// Album release date
|
/// Album release date
|
||||||
pub release_date: Option<Date>,
|
pub release_date: Option<NaiveDate>,
|
||||||
/// Path to album image, relative to the root of the web server.
|
/// Path to album image, relative to the root of the web server.
|
||||||
/// For example, `"/assets/images/Album.jpg"`
|
/// For example, `"/assets/images/Album.jpg"`
|
||||||
pub image_path: String,
|
pub image_path: String,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::time::SystemTime;
|
use chrono::NaiveDateTime;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use crate::models::HistoryEntry;
|
use crate::models::HistoryEntry;
|
||||||
use crate::models::Song;
|
use crate::models::Song;
|
||||||
@ -25,7 +25,7 @@ pub async fn get_history(limit: Option<i64>) -> Result<Vec<HistoryEntry>, Server
|
|||||||
|
|
||||||
/// Get the listen dates and songs of the current user.
|
/// Get the listen dates and songs of the current user.
|
||||||
#[server(endpoint = "history/get_songs")]
|
#[server(endpoint = "history/get_songs")]
|
||||||
pub async fn get_history_songs(limit: Option<i64>) -> Result<Vec<(SystemTime, Song)>, ServerFnError> {
|
pub async fn get_history_songs(limit: Option<i64>) -> Result<Vec<(NaiveDateTime, Song)>, ServerFnError> {
|
||||||
let user = get_user().await?;
|
let user = get_user().await?;
|
||||||
let db_con = &mut get_db_conn();
|
let db_con = &mut get_db_conn();
|
||||||
let songs = user.get_history_songs(limit, db_con)
|
let songs = user.get_history_songs(limit, db_con)
|
||||||
|
@ -6,7 +6,7 @@ use cfg_if::cfg_if;
|
|||||||
use crate::songdata::SongData;
|
use crate::songdata::SongData;
|
||||||
use crate::artistdata::ArtistData;
|
use crate::artistdata::ArtistData;
|
||||||
|
|
||||||
use std::time::SystemTime;
|
use chrono::NaiveDateTime;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "ssr")] {
|
if #[cfg(feature = "ssr")] {
|
||||||
@ -67,7 +67,7 @@ pub async fn upload_picture(data: MultipartData) -> Result<(), ServerFnError> {
|
|||||||
/// Returns a list of tuples with the date the song was listened to
|
/// Returns a list of tuples with the date the song was listened to
|
||||||
/// and the song data, sorted by date (most recent first).
|
/// and the song data, sorted by date (most recent first).
|
||||||
#[server(endpoint = "/profile/recent_songs")]
|
#[server(endpoint = "/profile/recent_songs")]
|
||||||
pub async fn recent_songs(for_user_id: i32, limit: Option<i64>) -> Result<Vec<(SystemTime, SongData)>, ServerFnError> {
|
pub async fn recent_songs(for_user_id: i32, limit: Option<i64>) -> Result<Vec<(NaiveDateTime, SongData)>, ServerFnError> {
|
||||||
let mut db_con = get_db_conn();
|
let mut db_con = get_db_conn();
|
||||||
|
|
||||||
// Get the ids of the most recent songs listened to
|
// Get the ids of the most recent songs listened to
|
||||||
@ -108,7 +108,7 @@ pub async fn recent_songs(for_user_id: i32, limit: Option<i64>) -> Result<Vec<(S
|
|||||||
.load(&mut db_con)?;
|
.load(&mut db_con)?;
|
||||||
|
|
||||||
// Process the history data into a map of song ids to song data
|
// Process the history data into a map of song ids to song data
|
||||||
let mut history_songs: HashMap<i32, (SystemTime, SongData)> = HashMap::with_capacity(history.len());
|
let mut history_songs: HashMap<i32, (NaiveDateTime, SongData)> = HashMap::with_capacity(history.len());
|
||||||
|
|
||||||
for (history, song, album, artist, like, dislike) in history {
|
for (history, song, album, artist, like, dislike) in history {
|
||||||
let song_id = history.song_id;
|
let song_id = history.song_id;
|
||||||
@ -148,7 +148,7 @@ pub async fn recent_songs(for_user_id: i32, limit: Option<i64>) -> Result<Vec<(S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort the songs by date
|
// Sort the songs by date
|
||||||
let mut history_songs: Vec<(SystemTime, SongData)> = history_songs.into_values().collect();
|
let mut history_songs: Vec<(NaiveDateTime, SongData)> = history_songs.into_values().collect();
|
||||||
history_songs.sort_by(|a, b| b.0.cmp(&a.0));
|
history_songs.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
Ok(history_songs)
|
Ok(history_songs)
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ pub async fn recent_songs(for_user_id: i32, limit: Option<i64>) -> Result<Vec<(S
|
|||||||
/// If not provided, all songs listened to in the date range are returned.
|
/// If not provided, all songs listened to in the date range are returned.
|
||||||
/// Returns a list of tuples with the play count and the song data, sorted by play count (most played first).
|
/// Returns a list of tuples with the play count and the song data, sorted by play count (most played first).
|
||||||
#[server(endpoint = "/profile/top_songs")]
|
#[server(endpoint = "/profile/top_songs")]
|
||||||
pub async fn top_songs(for_user_id: i32, start_date: SystemTime, end_date: SystemTime, limit: Option<i64>)
|
pub async fn top_songs(for_user_id: i32, start_date: NaiveDateTime, end_date: NaiveDateTime, limit: Option<i64>)
|
||||||
-> Result<Vec<(i64, SongData)>, ServerFnError>
|
-> Result<Vec<(i64, SongData)>, ServerFnError>
|
||||||
{
|
{
|
||||||
let mut db_con = get_db_conn();
|
let mut db_con = get_db_conn();
|
||||||
@ -259,7 +259,7 @@ pub async fn top_songs(for_user_id: i32, start_date: SystemTime, end_date: Syste
|
|||||||
/// If not provided, all artists listened to in the date range are returned.
|
/// If not provided, all artists listened to in the date range are returned.
|
||||||
/// Returns a list of tuples with the play count and the artist data, sorted by play count (most played first).
|
/// Returns a list of tuples with the play count and the artist data, sorted by play count (most played first).
|
||||||
#[server(endpoint = "/profile/top_artists")]
|
#[server(endpoint = "/profile/top_artists")]
|
||||||
pub async fn top_artists(for_user_id: i32, start_date: SystemTime, end_date: SystemTime, limit: Option<i64>)
|
pub async fn top_artists(for_user_id: i32, start_date: NaiveDateTime, end_date: NaiveDateTime, limit: Option<i64>)
|
||||||
-> Result<Vec<(i64, ArtistData)>, ServerFnError>
|
-> Result<Vec<(i64, ArtistData)>, ServerFnError>
|
||||||
{
|
{
|
||||||
let mut db_con = get_db_conn();
|
let mut db_con = get_db_conn();
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use std::time::SystemTime;
|
use chrono::{NaiveDate, NaiveDateTime};
|
||||||
use time::Date;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
@ -39,8 +38,8 @@ pub struct User {
|
|||||||
#[cfg_attr(feature = "ssr", diesel(deserialize_as = String))]
|
#[cfg_attr(feature = "ssr", diesel(deserialize_as = String))]
|
||||||
pub password: Option<String>,
|
pub password: Option<String>,
|
||||||
/// The time the user was created
|
/// The time the user was created
|
||||||
#[cfg_attr(feature = "ssr", diesel(deserialize_as = SystemTime))]
|
#[cfg_attr(feature = "ssr", diesel(deserialize_as = NaiveDateTime))]
|
||||||
pub created_at: Option<SystemTime>,
|
pub created_at: Option<NaiveDateTime>,
|
||||||
/// Whether the user is an admin
|
/// Whether the user is an admin
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
}
|
}
|
||||||
@ -103,7 +102,7 @@ impl User {
|
|||||||
///
|
///
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub fn get_history_songs(self: &Self, limit: Option<i64>, conn: &mut PgPooledConn) ->
|
pub fn get_history_songs(self: &Self, limit: Option<i64>, conn: &mut PgPooledConn) ->
|
||||||
Result<Vec<(SystemTime, Song)>, Box<dyn Error>> {
|
Result<Vec<(NaiveDateTime, Song)>, Box<dyn Error>> {
|
||||||
use crate::schema::songs::dsl::*;
|
use crate::schema::songs::dsl::*;
|
||||||
use crate::schema::song_history::dsl::*;
|
use crate::schema::song_history::dsl::*;
|
||||||
|
|
||||||
@ -467,7 +466,7 @@ pub struct Album {
|
|||||||
/// The album's title
|
/// The album's title
|
||||||
pub title: String,
|
pub title: String,
|
||||||
/// The album's release date
|
/// The album's release date
|
||||||
pub release_date: Option<Date>,
|
pub release_date: Option<NaiveDate>,
|
||||||
/// The path to the album's image file
|
/// The path to the album's image file
|
||||||
pub image_path: Option<String>,
|
pub image_path: Option<String>,
|
||||||
}
|
}
|
||||||
@ -546,7 +545,7 @@ pub struct Song {
|
|||||||
/// The duration of the song in seconds
|
/// The duration of the song in seconds
|
||||||
pub duration: i32,
|
pub duration: i32,
|
||||||
/// The song's release date
|
/// The song's release date
|
||||||
pub release_date: Option<Date>,
|
pub release_date: Option<NaiveDate>,
|
||||||
/// The path to the song's audio file
|
/// The path to the song's audio file
|
||||||
pub storage_path: String,
|
pub storage_path: String,
|
||||||
/// The path to the song's image file
|
/// The path to the song's image file
|
||||||
@ -622,7 +621,7 @@ pub struct HistoryEntry {
|
|||||||
/// The id of the user who listened to the song
|
/// The id of the user who listened to the song
|
||||||
pub user_id: i32,
|
pub user_id: i32,
|
||||||
/// The date the song was listened to
|
/// The date the song was listened to
|
||||||
pub date: SystemTime,
|
pub date: NaiveDateTime,
|
||||||
/// The id of the song that was listened to
|
/// The id of the song that was listened to
|
||||||
pub song_id: i32,
|
pub song_id: i32,
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos::logging::*;
|
|
||||||
use leptos_router::use_params_map;
|
use leptos_router::use_params_map;
|
||||||
use leptos_icons::*;
|
use leptos_icons::*;
|
||||||
use server_fn::error::NoCustomError;
|
use server_fn::error::NoCustomError;
|
||||||
@ -17,7 +16,7 @@ use crate::models::User;
|
|||||||
use crate::users::get_user_by_id;
|
use crate::users::get_user_by_id;
|
||||||
|
|
||||||
/// Duration in seconds backwards from now to aggregate history data for
|
/// Duration in seconds backwards from now to aggregate history data for
|
||||||
const HISTORY_SECS: u64 = 60 * 60 * 24 * 30;
|
const HISTORY_SECS: i64 = 60 * 60 * 24 * 30;
|
||||||
const HISTORY_MESSAGE: &str = "Last Month";
|
const HISTORY_MESSAGE: &str = "Last Month";
|
||||||
|
|
||||||
/// How many top songs to show
|
/// How many top songs to show
|
||||||
@ -160,19 +159,7 @@ fn UserProfile(user: User) -> impl IntoView {
|
|||||||
{user.email}
|
{user.email}
|
||||||
{
|
{
|
||||||
user.created_at.map(|created_at| {
|
user.created_at.map(|created_at| {
|
||||||
use time::{OffsetDateTime, macros::format_description};
|
format!(" • Joined {}", created_at.format("%B %Y"))
|
||||||
let format = format_description!("[month repr:long] [year]");
|
|
||||||
let date_time = Into::<OffsetDateTime>::into(created_at).format(format);
|
|
||||||
|
|
||||||
match date_time {
|
|
||||||
Ok(date_time) => {
|
|
||||||
format!(" • Joined {}", date_time)
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
error!("Error formatting date: {}", e);
|
|
||||||
String::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -191,11 +178,10 @@ fn UserProfile(user: User) -> impl IntoView {
|
|||||||
#[component]
|
#[component]
|
||||||
fn TopSongs(#[prop(into)] user_id: MaybeSignal<i32>) -> impl IntoView {
|
fn TopSongs(#[prop(into)] user_id: MaybeSignal<i32>) -> impl IntoView {
|
||||||
let top_songs = create_resource(move || user_id.get(), |user_id| async move {
|
let top_songs = create_resource(move || user_id.get(), |user_id| async move {
|
||||||
use std::time::{SystemTime, Duration};
|
use chrono::{Local, Duration};
|
||||||
|
let now = Local::now();
|
||||||
let now = SystemTime::now();
|
let start = now - Duration::seconds(HISTORY_SECS);
|
||||||
let start = now - Duration::from_secs(HISTORY_SECS);
|
let top_songs = top_songs(user_id, start.naive_utc(), now.naive_utc(), Some(TOP_SONGS_COUNT)).await;
|
||||||
let top_songs = top_songs(user_id, start, now, Some(TOP_SONGS_COUNT)).await;
|
|
||||||
|
|
||||||
top_songs.map(|top_songs| {
|
top_songs.map(|top_songs| {
|
||||||
top_songs.into_iter().map(|(plays, song)| {
|
top_songs.into_iter().map(|(plays, song)| {
|
||||||
@ -283,11 +269,11 @@ fn RecentSongs(#[prop(into)] user_id: MaybeSignal<i32>) -> impl IntoView {
|
|||||||
#[component]
|
#[component]
|
||||||
fn TopArtists(#[prop(into)] user_id: MaybeSignal<i32>) -> impl IntoView {
|
fn TopArtists(#[prop(into)] user_id: MaybeSignal<i32>) -> impl IntoView {
|
||||||
let top_artists = create_resource(move || user_id.get(), |user_id| async move {
|
let top_artists = create_resource(move || user_id.get(), |user_id| async move {
|
||||||
use std::time::{SystemTime, Duration};
|
use chrono::{Local, Duration};
|
||||||
|
|
||||||
let now = SystemTime::now();
|
let now = Local::now();
|
||||||
let start = now - Duration::from_secs(HISTORY_SECS);
|
let start = now - Duration::seconds(HISTORY_SECS);
|
||||||
let top_artists = top_artists(user_id, start, now, Some(TOP_ARTISTS_COUNT)).await;
|
let top_artists = top_artists(user_id, start.naive_utc(), now.naive_utc(), Some(TOP_ARTISTS_COUNT)).await;
|
||||||
|
|
||||||
top_artists.map(|top_artists| {
|
top_artists.map(|top_artists| {
|
||||||
top_artists.into_iter().map(|(_plays, artist)| {
|
top_artists.into_iter().map(|(_plays, artist)| {
|
||||||
|
@ -2,7 +2,7 @@ use crate::models::{Album, Artist, Song};
|
|||||||
use crate::components::dashboard_tile::DashboardTile;
|
use crate::components::dashboard_tile::DashboardTile;
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use time::Date;
|
use chrono::NaiveDate;
|
||||||
|
|
||||||
/// Holds information about a song
|
/// Holds information about a song
|
||||||
///
|
///
|
||||||
@ -22,7 +22,7 @@ pub struct SongData {
|
|||||||
/// The duration of the song in seconds
|
/// The duration of the song in seconds
|
||||||
pub duration: i32,
|
pub duration: i32,
|
||||||
/// The song's release date
|
/// The song's release date
|
||||||
pub release_date: Option<Date>,
|
pub release_date: Option<NaiveDate>,
|
||||||
/// Path to song file, relative to the root of the web server.
|
/// Path to song file, relative to the root of the web server.
|
||||||
/// For example, `"/assets/audio/Song.mp3"`
|
/// For example, `"/assets/audio/Song.mp3"`
|
||||||
pub song_path: String,
|
pub song_path: String,
|
||||||
|
@ -10,7 +10,7 @@ cfg_if! {
|
|||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use log::*;
|
use log::*;
|
||||||
use server_fn::error::NoCustomError;
|
use server_fn::error::NoCustomError;
|
||||||
use time::Date;
|
use chrono::NaiveDate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,15 +124,14 @@ async fn validate_track_number(track_number: Field<'static>) -> Result<Option<i3
|
|||||||
/// Validate the release date in a multipart field
|
/// Validate the release date in a multipart field
|
||||||
/// Expects a field with a release date, and ensures it is a valid date in the format [year]-[month]-[day]
|
/// Expects a field with a release date, and ensures it is a valid date in the format [year]-[month]-[day]
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
async fn validate_release_date(release_date: Field<'static>) -> Result<Option<Date>, ServerFnError> {
|
async fn validate_release_date(release_date: Field<'static>) -> Result<Option<NaiveDate>, ServerFnError> {
|
||||||
match release_date.text().await {
|
match release_date.text().await {
|
||||||
Ok(release_date) => {
|
Ok(release_date) => {
|
||||||
if release_date.trim().is_empty() {
|
if release_date.trim().is_empty() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let date_format = time::macros::format_description!("[year]-[month]-[day]");
|
let release_date = NaiveDate::parse_from_str(&release_date.trim(), "%Y-%m-%d");
|
||||||
let release_date = Date::parse(&release_date.trim(), date_format);
|
|
||||||
|
|
||||||
match release_date {
|
match release_date {
|
||||||
Ok(release_date) => Ok(Some(release_date)),
|
Ok(release_date) => Ok(Some(release_date)),
|
||||||
@ -181,8 +180,7 @@ pub async fn upload(data: MultipartData) -> Result<(), ServerFnError> {
|
|||||||
ServerError("Title field required and must precede file field".to_string()))?;
|
ServerError("Title field required and must precede file field".to_string()))?;
|
||||||
|
|
||||||
let clean_title = title.replace(" ", "_").replace("/", "_");
|
let clean_title = title.replace(" ", "_").replace("/", "_");
|
||||||
let date_format = time::macros::format_description!("[year]-[month]-[day]_[hour]:[minute]:[second]");
|
let date_str = chrono::Utc::now().format("%Y-%m-%d_%H:%M:%S").to_string();
|
||||||
let date_str = time::OffsetDateTime::now_utc().format(date_format).unwrap_or_default();
|
|
||||||
let upload_path = format!("assets/audio/upload-{}_{}.mp3", date_str, clean_title);
|
let upload_path = format!("assets/audio/upload-{}_{}.mp3", date_str, clean_title);
|
||||||
file_name = Some(format!("upload-{}_{}.mp3", date_str, clean_title));
|
file_name = Some(format!("upload-{}_{}.mp3", date_str, clean_title));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user