mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Properly sync associated items of recordings and works
This commit is contained in:
parent
bec0dfbf56
commit
37f21c582d
7 changed files with 103 additions and 89 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<Person>>,
|
||||
backend: Rc<Backend>,
|
||||
stack: gtk::Stack,
|
||||
}
|
||||
|
||||
impl PersonList {
|
||||
pub fn new(backend: Rc<Backend>) -> Rc<Self> {
|
||||
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<S>(&self, selected: S)
|
||||
where
|
||||
S: Fn(&Person) -> () + 'static,
|
||||
{
|
||||
self.list.set_selected(selected);
|
||||
}
|
||||
|
||||
pub fn reload(self: Rc<Self>) {
|
||||
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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue