From 37f21c582d6a2f1b7cac7379d5a44a646586b686 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sun, 29 Nov 2020 01:29:03 +0100 Subject: [PATCH] Properly sync associated items of recordings and works --- musicus/src/database/recordings.rs | 28 ++++++++ musicus/src/database/works.rs | 22 ++++++ musicus/src/meson.build | 1 - musicus/src/widgets/mod.rs | 3 - musicus/src/widgets/person_list.rs | 82 ----------------------- musicus_server/src/database/recordings.rs | 30 ++++++++- musicus_server/src/database/works.rs | 26 ++++++- 7 files changed, 103 insertions(+), 89 deletions(-) delete mode 100644 musicus/src/widgets/person_list.rs diff --git a/musicus/src/database/recordings.rs b/musicus/src/database/recordings.rs index 29ed3c4..6fe071a 100644 --- a/musicus/src/database/recordings.rs +++ b/musicus/src/database/recordings.rs @@ -115,6 +115,34 @@ impl Database { let recording_id = &recording.id; self.delete_recording(recording_id)?; + // Add associated items from the server, if they don't already exist. + + if self.get_work(&recording.work.id)?.is_none() { + self.update_work(recording.work.clone())?; + } + + for performance in &recording.performances { + if let Some(person) = &performance.person { + if self.get_person(&person.id)?.is_none() { + self.update_person(person.clone())?; + } + } + + if let Some(ensemble) = &performance.ensemble { + if self.get_ensemble(&ensemble.id)?.is_none() { + self.update_ensemble(ensemble.clone())?; + } + } + + if let Some(role) = &performance.role { + if self.get_instrument(&role.id)?.is_none() { + self.update_instrument(role.clone())?; + } + } + } + + // Add the actual recording. + let row: RecordingRow = recording.clone().into(); diesel::insert_into(recordings::table) .values(row) diff --git a/musicus/src/database/works.rs b/musicus/src/database/works.rs index b7b0919..f9b3a33 100644 --- a/musicus/src/database/works.rs +++ b/musicus/src/database/works.rs @@ -100,6 +100,28 @@ impl Database { let work_id = &work.id; self.delete_work(work_id)?; + // Add associated items from the server, if they don't already exist. + + if self.get_person(&work.composer.id)?.is_none() { + self.update_person(work.composer.clone())?; + } + + for instrument in &work.instruments { + if self.get_instrument(&instrument.id)?.is_none() { + self.update_instrument(instrument.clone())?; + } + } + + for part in &work.parts { + if let Some(person) = &part.composer { + if self.get_person(&person.id)?.is_none() { + self.update_person(person.clone())?; + } + } + } + + // Add the actual work. + let row: WorkRow = work.clone().into(); diesel::insert_into(works::table) .values(row) diff --git a/musicus/src/meson.build b/musicus/src/meson.build index 53abb39..4f0b78e 100644 --- a/musicus/src/meson.build +++ b/musicus/src/meson.build @@ -89,7 +89,6 @@ sources = files( 'widgets/list.rs', 'widgets/mod.rs', 'widgets/navigator.rs', - 'widgets/person_list.rs', 'widgets/player_bar.rs', 'widgets/poe_list.rs', 'widgets/selector_row.rs', diff --git a/musicus/src/widgets/mod.rs b/musicus/src/widgets/mod.rs index 0578fa3..511c4b0 100644 --- a/musicus/src/widgets/mod.rs +++ b/musicus/src/widgets/mod.rs @@ -4,9 +4,6 @@ pub use list::*; pub mod navigator; pub use navigator::*; -pub mod person_list; -pub use person_list::*; - pub mod player_bar; pub use player_bar::*; diff --git a/musicus/src/widgets/person_list.rs b/musicus/src/widgets/person_list.rs deleted file mode 100644 index df352e2..0000000 --- a/musicus/src/widgets/person_list.rs +++ /dev/null @@ -1,82 +0,0 @@ -use super::*; -use crate::backend::Backend; -use crate::database::*; -use gettextrs::gettext; -use glib::clone; -use gtk::prelude::*; -use gtk_macros::get_widget; -use std::rc::Rc; - -pub struct PersonList { - pub widget: gtk::Box, - list: Rc>, - backend: Rc, - stack: gtk::Stack, -} - -impl PersonList { - pub fn new(backend: Rc) -> Rc { - let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/person_list.ui"); - - get_widget!(builder, gtk::Box, widget); - get_widget!(builder, gtk::SearchEntry, search_entry); - get_widget!(builder, gtk::Stack, stack); - get_widget!(builder, gtk::ScrolledWindow, scrolled_window); - - let list = List::new(&gettext("No persons found.")); - - list.set_make_widget(|person: &Person| { - let label = gtk::Label::new(Some(&person.name_lf())); - label.set_halign(gtk::Align::Start); - label.set_margin_start(6); - label.set_margin_end(6); - label.set_margin_top(6); - label.set_margin_bottom(6); - label.upcast() - }); - - list.set_filter(clone!(@strong search_entry => move |person: &Person| { - let search = search_entry.get_text().to_string().to_lowercase(); - let name = person.name_fl().to_lowercase(); - search.is_empty() || name.contains(&search) - })); - - scrolled_window.add(&list.widget); - - let result = Rc::new(Self { - widget, - list, - backend, - stack, - }); - - search_entry.connect_search_changed(clone!(@strong result => move |_| { - result.list.invalidate_filter(); - })); - - result.clone().reload(); - - result - } - - pub fn set_selected(&self, selected: S) - where - S: Fn(&Person) -> () + 'static, - { - self.list.set_selected(selected); - } - - pub fn reload(self: Rc) { - self.stack.set_visible_child_name("loading"); - - let context = glib::MainContext::default(); - let backend = self.backend.clone(); - let list = self.list.clone(); - - context.spawn_local(async move { - let persons = backend.db().get_persons().await.unwrap(); - list.show_items(persons); - self.stack.set_visible_child_name("content"); - }); - } -} diff --git a/musicus_server/src/database/recordings.rs b/musicus_server/src/database/recordings.rs index a756cee..1452746 100644 --- a/musicus_server/src/database/recordings.rs +++ b/musicus_server/src/database/recordings.rs @@ -1,5 +1,6 @@ use super::schema::{ensembles, performances, persons, recordings}; use super::{get_ensemble, get_instrument, get_person, get_work}; +use super::{update_ensemble, update_instrument, update_person, update_work}; use super::{DbConn, Ensemble, Instrument, Person, User, Work}; use crate::error::ServerError; use anyhow::{anyhow, Error, Result}; @@ -48,7 +49,6 @@ struct PerformanceRow { /// Update an existing recording or insert a new one. This will only work, if the provided user is /// allowed to do that. -// TODO: Also add newly created associated items. pub fn update_recording(conn: &DbConn, recording: &Recording, user: &User) -> Result<()> { conn.transaction::<(), Error, _>(|| { let old_row = get_recording_row(conn, &recording.id)?; @@ -66,6 +66,34 @@ pub fn update_recording(conn: &DbConn, recording: &Recording, user: &User) -> Re .filter(recordings::id.eq(id)) .execute(conn)?; + // Add associated items, if they don't already exist. + + if get_work(conn, &recording.work.id)?.is_none() { + update_work(conn, &recording.work, &user)?; + } + + for performance in &recording.performances { + if let Some(person) = &performance.person { + if get_person(conn, &person.id)?.is_none() { + update_person(conn, person, &user)?; + } + } + + if let Some(ensemble) = &performance.ensemble { + if get_ensemble(conn, &ensemble.id)?.is_none() { + update_ensemble(conn, ensemble, &user)?; + } + } + + if let Some(role) = &performance.role { + if get_instrument(conn, &role.id)?.is_none() { + update_instrument(conn, role, &user)?; + } + } + } + + // Add the actual recording. + let row = RecordingRow { id: id.clone(), work: recording.work.id.clone(), diff --git a/musicus_server/src/database/works.rs b/musicus_server/src/database/works.rs index 372330b..20975b8 100644 --- a/musicus_server/src/database/works.rs +++ b/musicus_server/src/database/works.rs @@ -1,5 +1,6 @@ use super::schema::{instrumentations, work_parts, work_sections, works}; -use super::{get_instrument, get_person, DbConn, Instrument, Person, User}; +use super::{get_instrument, get_person, update_instrument, update_person}; +use super::{DbConn, Instrument, Person, User}; use crate::error::ServerError; use anyhow::{anyhow, Error, Result}; use diesel::prelude::*; @@ -76,7 +77,6 @@ struct WorkSectionRow { /// Update an existing work or insert a new one. This will only succeed, if the user is allowed to /// do that. -// TODO: Also add newly created associated items. pub fn update_work(conn: &DbConn, work: &Work, user: &User) -> Result<()> { conn.transaction::<(), Error, _>(|| { let old_row = get_work_row(conn, &work.id)?; @@ -94,6 +94,28 @@ pub fn update_work(conn: &DbConn, work: &Work, user: &User) -> Result<()> { .filter(works::id.eq(id)) .execute(conn)?; + // Add associated items, if they don't already exist. + + if get_person(conn, &work.composer.id)?.is_none() { + update_person(conn, &work.composer, &user)?; + } + + for instrument in &work.instruments { + if get_instrument(conn, &instrument.id)?.is_none() { + update_instrument(conn, instrument, &user)?; + } + } + + for part in &work.parts { + if let Some(person) = &part.composer { + if get_person(conn, &person.id)?.is_none() { + update_person(conn, person, &user)?; + } + } + } + + // Add the actual work. + let row = WorkRow { id: id.clone(), composer: work.composer.id.clone(),