adding all of our core sql systems
This commit is contained in:
parent
2408404ff4
commit
c9225680c3
20 changed files with 1055 additions and 227 deletions
|
@ -1,5 +1,5 @@
|
|||
use crate::model::Model;
|
||||
use color_eyre::eyre::Result;
|
||||
use super::model::Model;
|
||||
use miette::{Result, miette, IntoDiagnostic};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
use std::path::PathBuf;
|
||||
|
@ -13,25 +13,26 @@ pub struct Image {
|
|||
}
|
||||
|
||||
impl Model<Image> {
|
||||
pub fn load_from_db(&mut self) {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let result = query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for image in v.into_iter() {
|
||||
let _ = self.add_item(image);
|
||||
}
|
||||
pub async fn load_from_db(&mut self) {
|
||||
let result = query_as!(
|
||||
Image,
|
||||
r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#
|
||||
)
|
||||
.fetch_all(&mut self.db)
|
||||
.await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for image in v.into_iter() {
|
||||
let _ = self.add_item(image);
|
||||
}
|
||||
Err(e) => error!("There was an error in converting images: {e}"),
|
||||
}
|
||||
});
|
||||
Err(e) => error!("There was an error in converting images: {e}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_image_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Image> {
|
||||
Ok(query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await?)
|
||||
Ok(query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -47,37 +48,38 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_db_and_model() {
|
||||
let mut image_model: Model<Image> = Model::default();
|
||||
image_model.load_from_db();
|
||||
#[tokio::test]
|
||||
pub async fn test_db_and_model() {
|
||||
let mut image_model: Model<Image> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
image_model.load_from_db().await;
|
||||
dbg!(&image_model.items);
|
||||
if let Some(image) = image_model.find(|i| i.id == 3) {
|
||||
let test_image = test_image("nccq5".into());
|
||||
dbg!(&test_image);
|
||||
assert_eq!(test_image.title, image.title);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_add_image() {
|
||||
#[tokio::test]
|
||||
pub async fn test_add_image() {
|
||||
let image = test_image("A new image".into());
|
||||
let mut image_model: Model<Image> = Model::default();
|
||||
let mut image_model: Model<Image> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
let result = image_model.add_item(image.clone());
|
||||
let new_image = test_image("A newer image".into());
|
||||
match result {
|
||||
Ok(_) => {
|
||||
assert_eq!(&image, image_model.find(|i| i.id == 0).unwrap());
|
||||
assert_ne!(
|
||||
&new_image,
|
||||
image_model.find(|i| i.id == 0).unwrap()
|
||||
);
|
||||
assert_ne!(&new_image, image_model.find(|i| i.id == 0).unwrap());
|
||||
}
|
||||
Err(e) => assert!(
|
||||
false,
|
||||
"There was an error adding the image: {:?}",
|
||||
e
|
||||
),
|
||||
Err(e) => assert!(false, "There was an error adding the image: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::{error::Error, fmt::Display};
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::presentations::PresKind;
|
||||
use super::presentations::PresKind;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ServiceItemKind {
|
||||
|
@ -22,9 +22,7 @@ impl std::fmt::Display for ServiceItemKind {
|
|||
Self::Video => "video".to_owned(),
|
||||
Self::Presentation(PresKind::Html) => "html".to_owned(),
|
||||
Self::Presentation(PresKind::Pdf) => "pdf".to_owned(),
|
||||
Self::Presentation(PresKind::Generic) => {
|
||||
"presentation".to_owned()
|
||||
}
|
||||
Self::Presentation(PresKind::Generic) => "presentation".to_owned(),
|
||||
Self::Content => "content".to_owned(),
|
||||
};
|
||||
write!(f, "{s}")
|
||||
|
@ -38,9 +36,7 @@ impl TryFrom<String> for ServiceItemKind {
|
|||
"song" => Ok(Self::Song),
|
||||
"image" => Ok(Self::Image),
|
||||
"video" => Ok(Self::Video),
|
||||
"presentation" => {
|
||||
Ok(Self::Presentation(PresKind::Generic))
|
||||
}
|
||||
"presentation" => Ok(Self::Presentation(PresKind::Generic)),
|
||||
"html" => Ok(Self::Presentation(PresKind::Html)),
|
||||
"pdf" => Ok(Self::Presentation(PresKind::Pdf)),
|
||||
"content" => Ok(Self::Content),
|
||||
|
@ -55,9 +51,7 @@ impl From<ServiceItemKind> for String {
|
|||
ServiceItemKind::Song => "song".to_owned(),
|
||||
ServiceItemKind::Video => "video".to_owned(),
|
||||
ServiceItemKind::Image => "image".to_owned(),
|
||||
ServiceItemKind::Presentation(_) => {
|
||||
"presentation".to_owned()
|
||||
}
|
||||
ServiceItemKind::Presentation(_) => "presentation".to_owned(),
|
||||
ServiceItemKind::Content => "content".to_owned(),
|
||||
}
|
||||
}
|
||||
|
@ -71,10 +65,7 @@ pub enum ParseError {
|
|||
impl Error for ParseError {}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let message = match self {
|
||||
Self::UnknownType => "The type does not exist. It needs to be one of 'song', 'video', 'image', 'presentation', or 'content'",
|
||||
};
|
||||
|
|
|
@ -1,2 +1,9 @@
|
|||
pub mod images;
|
||||
pub mod kinds;
|
||||
pub mod lisp;
|
||||
pub mod presentations;
|
||||
pub mod service_items;
|
||||
pub mod slide;
|
||||
pub mod songs;
|
||||
pub mod videos;
|
||||
pub mod model;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::mem::replace;
|
||||
|
||||
use color_eyre::eyre::{eyre, Result};
|
||||
use cosmic::{executor, iced::Executor, Task};
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use sqlx::{Connection, SqliteConnection};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -24,7 +25,7 @@ impl<T> Model<T> {
|
|||
let _old_item = replace(current_item, item);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(eyre!(
|
||||
Err(miette!(
|
||||
"Item doesn't exist in model. Id was {}",
|
||||
index
|
||||
))
|
||||
|
@ -36,8 +37,7 @@ impl<T> Model<T> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_item(&self, index: i32) -> Option<&T>
|
||||
{
|
||||
pub fn get_item(&self, index: i32) -> Option<&T> {
|
||||
self.items.get(index as usize)
|
||||
}
|
||||
|
||||
|
@ -54,19 +54,16 @@ impl<T> Model<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Model<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
items: vec![],
|
||||
db: {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
get_db().await
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl<T> Default for Model<T> {
|
||||
// fn default() -> Self {
|
||||
// Self {
|
||||
// items: vec![],
|
||||
// db: {
|
||||
// get_db().await
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
pub async fn get_db() -> SqliteConnection {
|
||||
let mut data = dirs::data_local_dir().unwrap();
|
||||
|
@ -82,19 +79,25 @@ pub async fn get_db() -> SqliteConnection {
|
|||
pub trait Modeling {
|
||||
type Item;
|
||||
|
||||
fn setup_db() -> SqliteConnection {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let mut data = dirs::data_local_dir().unwrap();
|
||||
data.push("lumina");
|
||||
data.push("library-db.sqlite3");
|
||||
let mut db_url = String::from("sqlite://");
|
||||
db_url.push_str(data.to_str().unwrap());
|
||||
rt.block_on(async {
|
||||
SqliteConnection::connect(&db_url)
|
||||
.await
|
||||
.expect("problems")
|
||||
})
|
||||
}
|
||||
// fn setup_db() -> SqliteConnection {
|
||||
// let rt = executor::Default::new().unwrap();
|
||||
// let rt = executor::multi::Executor::new().unwrap();
|
||||
// let mut data = dirs::data_local_dir().unwrap();
|
||||
// data.push("lumina");
|
||||
// data.push("library-db.sqlite3");
|
||||
// let mut db_url = String::from("sqlite://");
|
||||
// db_url.push_str(data.to_str().unwrap());
|
||||
// rt.spawn(async {
|
||||
// SqliteConnection::connect(&db_url)
|
||||
// .await
|
||||
// .expect("problems")
|
||||
// });
|
||||
// rt.enter(async {
|
||||
// SqliteConnection::connect(&db_url)
|
||||
// .await
|
||||
// .expect("problems")
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
use color_eyre::eyre::Result;
|
||||
use miette::{miette, Result, IntoDiagnostic};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection};
|
||||
use std::path::PathBuf;
|
||||
use tracing::error;
|
||||
|
||||
use crate::model::Model;
|
||||
use super::model::Model;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum PresKind {
|
||||
|
@ -54,34 +54,38 @@ impl FromRow<'_, SqliteRow> for Presentation {
|
|||
}
|
||||
|
||||
impl Model<Presentation> {
|
||||
pub fn load_from_db(&mut self) {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let result = query!(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for presentation in v.into_iter() {
|
||||
let _ = self.add_item(Presentation {
|
||||
id: presentation.id,
|
||||
title: presentation.title,
|
||||
path: presentation.path.into(),
|
||||
kind: if presentation.html {
|
||||
PresKind::Html
|
||||
} else {
|
||||
PresKind::Pdf
|
||||
}
|
||||
});
|
||||
}
|
||||
pub async fn load_from_db(&mut self) {
|
||||
let result = query!(
|
||||
r#"SELECT id as "id: i32", title, file_path as "path", html from presentations"#
|
||||
)
|
||||
.fetch_all(&mut self.db)
|
||||
.await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for presentation in v.into_iter() {
|
||||
let _ = self.add_item(Presentation {
|
||||
id: presentation.id,
|
||||
title: presentation.title,
|
||||
path: presentation.path.into(),
|
||||
kind: if presentation.html {
|
||||
PresKind::Html
|
||||
} else {
|
||||
PresKind::Pdf
|
||||
},
|
||||
});
|
||||
}
|
||||
Err(e) => error!("There was an error in converting presentations: {e}"),
|
||||
}
|
||||
});
|
||||
Err(e) => error!("There was an error in converting presentations: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_presentation_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Presentation> {
|
||||
let row = query(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await?;
|
||||
Ok(Presentation::from_row(&row)?)
|
||||
pub async fn get_presentation_from_db(
|
||||
database_id: i32,
|
||||
db: &mut SqliteConnection,
|
||||
) -> Result<Presentation> {
|
||||
let row = query(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await.into_diagnostic()?;
|
||||
Ok(Presentation::from_row(&row).into_diagnostic()?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -106,11 +110,13 @@ mod test {
|
|||
assert_eq!(pres.get_kind(), &PresKind::Pdf)
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_db_and_model() {
|
||||
let mut presentation_model: Model<Presentation> =
|
||||
Model::default();
|
||||
presentation_model.load_from_db();
|
||||
#[tokio::test]
|
||||
async fn test_db_and_model() {
|
||||
let mut presentation_model: Model<Presentation> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
presentation_model.load_from_db().await;
|
||||
if let Some(presentation) = presentation_model.find(|p| p.id == 54) {
|
||||
let test_presentation = test_presentation();
|
||||
assert_eq!(&test_presentation, presentation);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use color_eyre::eyre::Result;
|
||||
use miette::Result;
|
||||
|
||||
use crate::images::Image;
|
||||
use crate::presentations::Presentation;
|
||||
use crate::songs::Song;
|
||||
use crate::videos::Video;
|
||||
use super::images::Image;
|
||||
use super::presentations::Presentation;
|
||||
use super::songs::Song;
|
||||
use super::videos::Video;
|
||||
|
||||
use super::kinds::ServiceItemKind;
|
||||
|
||||
|
@ -71,7 +71,7 @@ impl ServiceItemModel {
|
|||
mod test {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::presentations::PresKind;
|
||||
use crate::core::presentations::PresKind;
|
||||
|
||||
use super::*;
|
||||
use pretty_assertions::{assert_eq, assert_ne};
|
||||
|
@ -94,7 +94,6 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
pub fn test_service_item() {
|
||||
let song = test_song();
|
||||
|
@ -105,9 +104,12 @@ mod test {
|
|||
match service_model.add_item(&song) {
|
||||
Ok(_) => {
|
||||
assert_eq!(ServiceItemKind::Song, service_model.items[0].kind);
|
||||
assert_eq!(ServiceItemKind::Presentation(PresKind::Html), pres_item.kind);
|
||||
assert_eq!(
|
||||
ServiceItemKind::Presentation(PresKind::Html),
|
||||
pres_item.kind
|
||||
);
|
||||
assert_eq!(service_item, service_model.items[0]);
|
||||
},
|
||||
}
|
||||
Err(e) => panic!("Problem adding item: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use color_eyre::eyre::{eyre, Context, Result};
|
||||
use cosmic::{executor, iced::Executor};
|
||||
use miette::{miette, IntoDiagnostic, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query, query_as, sqlite::SqliteRow, FromRow, Row, SqliteConnection};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::{
|
||||
model::{get_db, Model},
|
||||
slides::{Background, TextAlignment},
|
||||
use super::{
|
||||
model::{Model},
|
||||
slide::{Background, TextAlignment},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
@ -26,11 +27,9 @@ pub struct Song {
|
|||
}
|
||||
|
||||
const VERSE_KEYWORDS: [&str; 24] = [
|
||||
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6",
|
||||
"Verse 7", "Verse 8", "Chorus 1", "Chorus 2", "Chorus 3",
|
||||
"Chorus 4", "Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
|
||||
"Intro 1", "Intro 2", "Ending 1", "Ending 2", "Other 1",
|
||||
"Other 2", "Other 3", "Other 4",
|
||||
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5", "Verse 6", "Verse 7", "Verse 8",
|
||||
"Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4", "Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
|
||||
"Intro 1", "Intro 2", "Ending 1", "Ending 2", "Other 1", "Other 2", "Other 3", "Other 4",
|
||||
];
|
||||
|
||||
impl FromRow<'_, SqliteRow> for Song {
|
||||
|
@ -49,14 +48,21 @@ impl FromRow<'_, SqliteRow> for Song {
|
|||
let str: &str = row.try_get(0)?;
|
||||
str.split(' ').map(|s| s.to_string()).collect()
|
||||
}),
|
||||
background: Some({
|
||||
background: {
|
||||
let string: String = row.try_get(7)?;
|
||||
Background::try_from(string)?
|
||||
}),
|
||||
match Background::try_from(string) {
|
||||
Ok(background) => Some(background),
|
||||
Err(_) => None,
|
||||
}
|
||||
|
||||
},
|
||||
text_alignment: Some({
|
||||
let horizontal_alignment: String = row.try_get(3)?;
|
||||
let vertical_alignment: String = row.try_get(4)?;
|
||||
match (horizontal_alignment.to_lowercase().as_str(), vertical_alignment.to_lowercase().as_str()) {
|
||||
match (
|
||||
horizontal_alignment.to_lowercase().as_str(),
|
||||
vertical_alignment.to_lowercase().as_str(),
|
||||
) {
|
||||
("left", "top") => TextAlignment::TopLeft,
|
||||
("left", "center") => TextAlignment::MiddleLeft,
|
||||
("left", "bottom") => TextAlignment::BottomLeft,
|
||||
|
@ -66,7 +72,7 @@ impl FromRow<'_, SqliteRow> for Song {
|
|||
("right", "top") => TextAlignment::TopRight,
|
||||
("right", "center") => TextAlignment::MiddleRight,
|
||||
("right", "bottom") => TextAlignment::BottomRight,
|
||||
_ => TextAlignment::MiddleCenter
|
||||
_ => TextAlignment::MiddleCenter,
|
||||
}
|
||||
}),
|
||||
font: row.try_get(6)?,
|
||||
|
@ -75,35 +81,30 @@ impl FromRow<'_, SqliteRow> for Song {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result<Song> {
|
||||
let row = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await?;
|
||||
Ok(Song::from_row(&row)?)
|
||||
pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result<Song> {
|
||||
let row = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await.into_diagnostic()?;
|
||||
Ok(Song::from_row(&row).into_diagnostic()?)
|
||||
}
|
||||
|
||||
|
||||
impl Model<Song> {
|
||||
pub fn load_from_db(&mut self) {
|
||||
pub async fn load_from_db(&mut self) {
|
||||
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let result = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(s) => {
|
||||
for song in s.into_iter() {
|
||||
match Song::from_row(&song) {
|
||||
Ok(song) => {
|
||||
let _ = self.add_item(song);
|
||||
},
|
||||
Err(e) => error!("Could not convert song: {e}"),
|
||||
};
|
||||
let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(s) => {
|
||||
for song in s.into_iter() {
|
||||
match Song::from_row(&song) {
|
||||
Ok(song) => {
|
||||
let _ = self.add_item(song);
|
||||
},
|
||||
Err(e) => error!("Could not convert song: {e}"),
|
||||
};
|
||||
},
|
||||
Err(e) => {
|
||||
error!("There was an error in converting songs: {e}");
|
||||
},
|
||||
}
|
||||
})
|
||||
};
|
||||
},
|
||||
Err(e) => {
|
||||
error!("There was an error in converting songs: {e}");
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,15 +112,11 @@ impl Song {
|
|||
pub fn get_lyrics(&self) -> Result<Vec<String>> {
|
||||
let mut lyric_list = Vec::new();
|
||||
if self.lyrics.is_none() {
|
||||
return Err(eyre!("There is no lyrics here"));
|
||||
return Err(miette!("There is no lyrics here"));
|
||||
} else if self.verse_order.is_none() {
|
||||
return Err(eyre!("There is no verse_order here"));
|
||||
} else if self
|
||||
.verse_order
|
||||
.clone()
|
||||
.is_some_and(|v| v.is_empty())
|
||||
{
|
||||
return Err(eyre!("There is no verse_order here"));
|
||||
return Err(miette!("There is no verse_order here"));
|
||||
} else if self.verse_order.clone().is_some_and(|v| v.is_empty()) {
|
||||
return Err(miette!("There is no verse_order here"));
|
||||
}
|
||||
if let Some(raw_lyrics) = self.lyrics.clone() {
|
||||
let raw_lyrics = raw_lyrics.as_str();
|
||||
|
@ -148,21 +145,16 @@ impl Song {
|
|||
let mut verse_name = "";
|
||||
debug!(verse = verse);
|
||||
for word in VERSE_KEYWORDS {
|
||||
let end_verse =
|
||||
verse.get(1..2).unwrap_or_default();
|
||||
let beg_verse =
|
||||
verse.get(0..1).unwrap_or_default();
|
||||
if word.starts_with(beg_verse)
|
||||
&& word.ends_with(end_verse)
|
||||
{
|
||||
let end_verse = verse.get(1..2).unwrap_or_default();
|
||||
let beg_verse = verse.get(0..1).unwrap_or_default();
|
||||
if word.starts_with(beg_verse) && word.ends_with(end_verse) {
|
||||
verse_name = word;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(lyric) = lyric_map.get(verse_name) {
|
||||
if lyric.contains("\n\n") {
|
||||
let split_lyrics: Vec<&str> =
|
||||
lyric.split("\n\n").collect();
|
||||
let split_lyrics: Vec<&str> = lyric.split("\n\n").collect();
|
||||
for lyric in split_lyrics {
|
||||
if lyric.is_empty() {
|
||||
continue;
|
||||
|
@ -181,7 +173,7 @@ impl Song {
|
|||
}
|
||||
Ok(lyric_list)
|
||||
} else {
|
||||
Err(eyre!("There are no lyrics"))
|
||||
Err(miette!("There are no lyrics"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -254,12 +246,11 @@ From the day
|
|||
You saved my soul"
|
||||
.to_string(),
|
||||
);
|
||||
song.verse_order =
|
||||
"O1 V1 C1 C2 O2 V2 C3 C2 O2 B1 C2 C2 E1 O2"
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.map(|s| Some(s.to_string()))
|
||||
.collect();
|
||||
song.verse_order = "O1 V1 C1 C2 O2 V2 C3 C2 O2 B1 C2 C2 E1 O2"
|
||||
.to_string()
|
||||
.split(' ')
|
||||
.map(|s| Some(s.to_string()))
|
||||
.collect();
|
||||
let lyrics = song.get_lyrics();
|
||||
match lyrics {
|
||||
Ok(lyrics) => {
|
||||
|
@ -271,40 +262,47 @@ You saved my soul"
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_db_and_model() {
|
||||
let mut song_model: Model<Song> = Model::default();
|
||||
song_model.load_from_db();
|
||||
async fn model() -> Model<Song> {
|
||||
let song_model: Model<Song> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
song_model
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_db_and_model() {
|
||||
let mut song_model = model().await;
|
||||
song_model.load_from_db().await;
|
||||
if let Some(song) = song_model.find(|s| s.id == 7) {
|
||||
let test_song = test_song();
|
||||
assert_eq!(&test_song, song);
|
||||
} else {
|
||||
dbg!(song_model);
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_song_from_db() {
|
||||
async fn test_song_from_db() {
|
||||
let song = test_song();
|
||||
let result = get_song_from_db(7, &mut get_db().await).await;
|
||||
let mut db = model().await.db;
|
||||
let result = get_song_from_db(7, &mut db).await;
|
||||
match result {
|
||||
Ok(db_song) => assert_eq!(song, db_song),
|
||||
Err(e) => assert!(false, "{e}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_update() {
|
||||
#[tokio::test]
|
||||
async fn test_update() {
|
||||
let song = test_song();
|
||||
let cloned_song = song.clone();
|
||||
let mut song_model: Model<Song> = Model::default();
|
||||
song_model.load_from_db();
|
||||
let mut song_model: Model<Song> = model().await;
|
||||
song_model.load_from_db().await;
|
||||
|
||||
match song_model.update_item(song, 2) {
|
||||
Ok(()) => assert_eq!(
|
||||
&cloned_song,
|
||||
song_model.find(|s| s.id == 7).unwrap()
|
||||
),
|
||||
Ok(()) => assert_eq!(&cloned_song, song_model.find(|s| s.id == 7).unwrap()),
|
||||
Err(e) => assert!(false, "{e}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::model::Model;
|
||||
use color_eyre::eyre::Result;
|
||||
use super::model::Model;
|
||||
use cosmic::{executor, iced::Executor};
|
||||
use miette::{Result, miette, IntoDiagnostic};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{query_as, SqliteConnection};
|
||||
use std::path::PathBuf;
|
||||
|
@ -16,28 +17,23 @@ pub struct Video {
|
|||
}
|
||||
|
||||
impl Model<Video> {
|
||||
pub fn load_from_db(&mut self) {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let result = query_as!(Video, r#"SELECT title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for video in v.into_iter() {
|
||||
let _ = self.add_item(video);
|
||||
}
|
||||
pub async fn load_from_db(&mut self) {
|
||||
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
||||
match result {
|
||||
Ok(v) => {
|
||||
for video in v.into_iter() {
|
||||
let _ = self.add_item(video);
|
||||
}
|
||||
Err(e) => error!("There was an error in converting videos: {e}"),
|
||||
}
|
||||
});
|
||||
Err(e) => error!("There was an error in converting videos: {e}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_video_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Video> {
|
||||
Ok(query_as!(Video, r#"SELECT title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!", id as "id: i32" from videos where id = ?"#, database_id).fetch_one(db).await?)
|
||||
Ok(query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos where id = ?"#, database_id).fetch_one(db).await.into_diagnostic()?)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -51,37 +47,39 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_db_and_model() {
|
||||
let mut video_model: Model<Video> = Model::default();
|
||||
video_model.load_from_db();
|
||||
#[tokio::test]
|
||||
async fn test_db_and_model() {
|
||||
let mut video_model: Model<Video> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
video_model.load_from_db().await;
|
||||
if let Some(video) = video_model.find(|v| v.id == 73) {
|
||||
let test_video = test_video("Getting started with Tokio. The ultimate starter guide to writing async Rust.".into());
|
||||
let test_video = test_video(
|
||||
"Getting started with Tokio. The ultimate starter guide to writing async Rust."
|
||||
.into(),
|
||||
);
|
||||
assert_eq!(test_video.title, video.title);
|
||||
} else {
|
||||
assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_add_video() {
|
||||
#[tokio::test]
|
||||
async fn test_add_video() {
|
||||
let video = test_video("A new video".into());
|
||||
let mut video_model: Model<Video> = Model::default();
|
||||
let mut video_model: Model<Video> = Model {
|
||||
items: vec![],
|
||||
db: crate::core::model::get_db().await
|
||||
};
|
||||
let result = video_model.add_item(video.clone());
|
||||
let new_video = test_video("A newer video".into());
|
||||
match result {
|
||||
Ok(_) => {
|
||||
assert_eq!(&video, video_model.find(|v| v.id == 0).unwrap());
|
||||
assert_ne!(
|
||||
&new_video,
|
||||
video_model.find(|v| v.id == 0).unwrap()
|
||||
);
|
||||
assert_ne!(&new_video, video_model.find(|v| v.id == 0).unwrap());
|
||||
}
|
||||
Err(e) => assert!(
|
||||
false,
|
||||
"There was an error adding the video: {:?}",
|
||||
e
|
||||
),
|
||||
Err(e) => assert!(false, "There was an error adding the video: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue