Render and be able to edit bike rides (and sorta other time distance workouts) #169
|
@ -238,52 +238,8 @@ impl DayEdit {
|
||||||
*s.imp().on_finished.borrow_mut() = Box::new(on_finished);
|
*s.imp().on_finished.borrow_mut() = Box::new(on_finished);
|
||||||
*s.imp().view_model.borrow_mut() = Some(view_model.clone());
|
*s.imp().view_model.borrow_mut() = Some(view_model.clone());
|
||||||
|
|
||||||
s.append(
|
s.append(&control_buttons(&s, &view_model));
|
||||||
&ActionGroup::builder()
|
s.append(&weight_and_steps_row(&view_model));
|
||||||
.primary_action("Save", {
|
|
||||||
let s = s.clone();
|
|
||||||
let view_model = view_model.clone();
|
|
||||||
move || {
|
|
||||||
view_model.save();
|
|
||||||
s.finish();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.secondary_action("Cancel", {
|
|
||||||
let s = s.clone();
|
|
||||||
let view_model = view_model.clone();
|
|
||||||
move || {
|
|
||||||
view_model.revert();
|
|
||||||
s.finish();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let top_row = gtk::Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
|
||||||
.build();
|
|
||||||
top_row.append(
|
|
||||||
&weight_field(view_model.weight().map(WeightFormatter::from), {
|
|
||||||
let view_model = view_model.clone();
|
|
||||||
move |w| match w {
|
|
||||||
Some(w) => view_model.set_weight(*w),
|
|
||||||
None => eprintln!("have not implemented record delete"),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.widget(),
|
|
||||||
);
|
|
||||||
|
|
||||||
top_row.append(
|
|
||||||
&steps_editor(view_model.steps(), {
|
|
||||||
let view_model = view_model.clone();
|
|
||||||
move |s| match s {
|
|
||||||
Some(s) => view_model.set_steps(s),
|
|
||||||
None => eprintln!("have not implemented record delete"),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.widget(),
|
|
||||||
);
|
|
||||||
s.append(&top_row);
|
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
@ -292,3 +248,57 @@ impl DayEdit {
|
||||||
(self.imp().on_finished.borrow())()
|
(self.imp().on_finished.borrow())()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn control_buttons(s: &DayEdit, view_model: &DayDetailViewModel) -> ActionGroup {
|
||||||
|
ActionGroup::builder()
|
||||||
|
.primary_action("Save", {
|
||||||
|
let s = s.clone();
|
||||||
|
let view_model = view_model.clone();
|
||||||
|
move || {
|
||||||
|
view_model.save();
|
||||||
|
s.finish();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.secondary_action("Cancel", {
|
||||||
|
let s = s.clone();
|
||||||
|
let view_model = view_model.clone();
|
||||||
|
move || {
|
||||||
|
let s = s.clone();
|
||||||
|
let view_model = view_model.clone();
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
view_model.revert().await;
|
||||||
|
s.finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn weight_and_steps_row(view_model: &DayDetailViewModel) -> gtk::Box {
|
||||||
|
let row = gtk::Box::builder()
|
||||||
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
|
.build();
|
||||||
|
row.append(
|
||||||
|
&weight_field(view_model.weight().map(WeightFormatter::from), {
|
||||||
|
let view_model = view_model.clone();
|
||||||
|
move |w| match w {
|
||||||
|
Some(w) => view_model.set_weight(*w),
|
||||||
|
None => eprintln!("have not implemented record delete"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.widget(),
|
||||||
|
);
|
||||||
|
|
||||||
|
row.append(
|
||||||
|
&steps_editor(view_model.steps(), {
|
||||||
|
let view_model = view_model.clone();
|
||||||
|
move |s| match s {
|
||||||
|
Some(s) => view_model.set_steps(s),
|
||||||
|
None => eprintln!("have not implemented record delete"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.widget(),
|
||||||
|
);
|
||||||
|
|
||||||
|
row
|
||||||
|
}
|
||||||
|
|
|
@ -374,8 +374,38 @@ impl DayDetailViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn revert(&self) {
|
pub async fn revert(&self) {
|
||||||
unimplemented!();
|
self.populate_records().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn populate_records(&self) {
|
||||||
|
let records = self.provider.records(self.date, self.date).await.unwrap();
|
||||||
|
|
||||||
|
let (weight_records, records): (Vec<Record<TraxRecord>>, Vec<Record<TraxRecord>>) =
|
||||||
|
records.into_iter().partition(|r| r.data.is_weight());
|
||||||
|
let (step_records, records): (Vec<Record<TraxRecord>>, Vec<Record<TraxRecord>>) =
|
||||||
|
records.into_iter().partition(|r| r.data.is_steps());
|
||||||
|
|
||||||
|
*self.weight.write().unwrap() = weight_records
|
||||||
|
.first()
|
||||||
|
.and_then(|r| match r.data {
|
||||||
|
TraxRecord::Weight(ref w) => Some((r.id.clone(), w.clone())),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.map(|(id, w)| RecordState::Original(Record { id, data: w }));
|
||||||
|
|
||||||
|
*self.steps.write().unwrap() = step_records
|
||||||
|
.first()
|
||||||
|
.and_then(|r| match r.data {
|
||||||
|
TraxRecord::Steps(ref w) => Some((r.id.clone(), w.clone())),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.map(|(id, w)| RecordState::Original(Record { id, data: w }));
|
||||||
|
|
||||||
|
*self.records.write().unwrap() = records
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| (r.id.clone(), RecordState::Original(r)))
|
||||||
|
.collect::<HashMap<RecordId, RecordState<TraxRecord>>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,7 +413,7 @@ impl DayDetailViewModel {
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use chrono::{DateTime, FixedOffset, TimeZone};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use dimensioned::si;
|
use dimensioned::si;
|
||||||
use emseries::Record;
|
use emseries::Record;
|
||||||
|
|
||||||
|
@ -640,7 +670,7 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_can_delete_an_existing_record() {
|
async fn it_can_delete_an_existing_record() {
|
||||||
let (view_model, provider) = create_view_model().await;
|
let (view_model, provider) = create_view_model().await;
|
||||||
let mut workout = view_model.time_distance_records().first().cloned().unwrap();
|
let workout = view_model.time_distance_records().first().cloned().unwrap();
|
||||||
|
|
||||||
view_model.remove_record(workout.id);
|
view_model.remove_record(workout.id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue