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().view_model.borrow_mut() = Some(view_model.clone());
|
||||
|
||||
s.append(
|
||||
&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 || {
|
||||
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.append(&control_buttons(&s, &view_model));
|
||||
s.append(&weight_and_steps_row(&view_model));
|
||||
|
||||
s
|
||||
}
|
||||
|
@ -292,3 +248,57 @@ impl DayEdit {
|
|||
(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) {
|
||||
unimplemented!();
|
||||
pub async fn revert(&self) {
|
||||
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 {
|
||||
use super::*;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, FixedOffset, TimeZone};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use dimensioned::si;
|
||||
use emseries::Record;
|
||||
|
||||
|
@ -640,7 +670,7 @@ mod test {
|
|||
#[tokio::test]
|
||||
async fn it_can_delete_an_existing_record() {
|
||||
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);
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in New Issue