Create placeholders in the historical view for days that are unpopulated.
This commit is contained in:
parent
6d9e2ea382
commit
7a6e902fdd
|
@ -90,12 +90,14 @@ impl DaySummary {
|
||||||
*self.imp().weight.borrow_mut() = Some(label);
|
*self.imp().weight.borrow_mut() = Some(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
self.append(
|
self.append(
|
||||||
>k::Label::builder()
|
>k::Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(gtk::Align::Start)
|
||||||
.label("15km of biking in 60 minutes")
|
.label("15km of biking in 60 minutes")
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ You should have received a copy of the GNU General Public License along with Fit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::components::DaySummary;
|
use crate::components::DaySummary;
|
||||||
use emseries::{Record, Recordable, Timestamp};
|
use chrono::{Duration, Local, NaiveDate};
|
||||||
|
use emseries::Record;
|
||||||
use ft_core::TraxRecord;
|
use ft_core::TraxRecord;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*};
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
|
@ -24,7 +25,9 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
/// The historical view will show a window into the main database. It will show some version of
|
/// The historical view will show a window into the main database. It will show some version of
|
||||||
/// daily summaries, daily details, and will provide all functions the user may need for editing
|
/// daily summaries, daily details, and will provide all functions the user may need for editing
|
||||||
/// records.
|
/// records.
|
||||||
pub struct HistoricalViewPrivate {}
|
pub struct HistoricalViewPrivate {
|
||||||
|
time_window: RefCell<DayInterval>,
|
||||||
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for HistoricalViewPrivate {
|
impl ObjectSubclass for HistoricalViewPrivate {
|
||||||
|
@ -33,7 +36,9 @@ impl ObjectSubclass for HistoricalViewPrivate {
|
||||||
type ParentType = gtk::Box;
|
type ParentType = gtk::Box;
|
||||||
|
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {}
|
Self {
|
||||||
|
time_window: RefCell::new(DayInterval::default()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +59,11 @@ impl HistoricalView {
|
||||||
s.set_orientation(gtk::Orientation::Vertical);
|
s.set_orientation(gtk::Orientation::Vertical);
|
||||||
s.set_css_classes(&["historical"]);
|
s.set_css_classes(&["historical"]);
|
||||||
|
|
||||||
let day_records: GroupedRecords = GroupedRecords::from(records);
|
let grouped_records =
|
||||||
|
GroupedRecords::new((*s.imp().time_window.borrow()).clone()).with_data(records);
|
||||||
|
|
||||||
let model = gio::ListStore::new::<DayRecords>();
|
let mut model = gio::ListStore::new::<DayRecords>();
|
||||||
model.extend_from_slice(&day_records.0);
|
model.extend(grouped_records.items());
|
||||||
|
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = gtk::SignalListItemFactory::new();
|
||||||
factory.connect_setup(move |_, list_item| {
|
factory.connect_setup(move |_, list_item| {
|
||||||
|
@ -149,23 +155,105 @@ impl DayRecords {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GroupedRecords(Vec<DayRecords>);
|
struct GroupedRecords {
|
||||||
|
interval: DayInterval,
|
||||||
|
data: HashMap<NaiveDate, DayRecords>,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Vec<Record<TraxRecord>>> for GroupedRecords {
|
impl GroupedRecords {
|
||||||
fn from(records: Vec<Record<TraxRecord>>) -> GroupedRecords {
|
fn new(interval: DayInterval) -> Self {
|
||||||
GroupedRecords(
|
let mut s = Self {
|
||||||
records
|
interval: interval.clone(),
|
||||||
.into_iter()
|
data: HashMap::new(),
|
||||||
.fold(HashMap::new(), |mut acc, rec| {
|
};
|
||||||
acc.entry(rec.date())
|
interval.days().for_each(|date| {
|
||||||
.and_modify(|entry: &mut DayRecords| (*entry).add_record(rec.clone()))
|
let _ = s.data.insert(date, DayRecords::new(date, vec![]));
|
||||||
.or_insert(DayRecords::new(rec.date(), vec![rec]));
|
});
|
||||||
acc
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_data(mut self, records: Vec<Record<TraxRecord>>) -> Self {
|
||||||
|
records.into_iter().for_each(|record| {
|
||||||
|
self.data
|
||||||
|
.entry(record.date())
|
||||||
|
.and_modify(|entry: &mut DayRecords| (*entry).add_record(record.clone()))
|
||||||
|
.or_insert(DayRecords::new(record.date(), vec![record]));
|
||||||
|
});
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn items<'a>(&'a self) -> impl Iterator<Item = DayRecords> + 'a {
|
||||||
|
/*
|
||||||
|
GroupedRecordIterator {
|
||||||
|
interval: self.interval.clone(),
|
||||||
|
data: &self.data,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
self.interval.days().map(|date| {
|
||||||
|
self.data
|
||||||
|
.get(&date)
|
||||||
|
.map(|rec| rec.clone())
|
||||||
|
.unwrap_or(DayRecords::new(date, vec![]))
|
||||||
})
|
})
|
||||||
.values()
|
}
|
||||||
.cloned()
|
}
|
||||||
.collect::<Vec<DayRecords>>(),
|
|
||||||
)
|
/*
|
||||||
|
struct GroupedRecordIterator<'a> {
|
||||||
|
interval: DayInterval,
|
||||||
|
data: &'a HashMap<NaiveDate, DayRecords>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a> Iterator for GroupedRecordIterator<'a> {
|
||||||
|
type Item = &'a DayRecords;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<&'a DayRecords> {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
struct DayInterval {
|
||||||
|
start: NaiveDate,
|
||||||
|
end: NaiveDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DayInterval {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
start: (Local::now() - Duration::days(7)).date_naive(),
|
||||||
|
end: Local::now().date_naive(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DayInterval {
|
||||||
|
fn days(&self) -> impl Iterator<Item = NaiveDate> {
|
||||||
|
DayIterator {
|
||||||
|
current: self.start.clone(),
|
||||||
|
end: self.end.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DayIterator {
|
||||||
|
current: NaiveDate,
|
||||||
|
end: NaiveDate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for DayIterator {
|
||||||
|
type Item = NaiveDate;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.current <= self.end {
|
||||||
|
let val = self.current.clone();
|
||||||
|
self.current += Duration::days(1);
|
||||||
|
Some(val)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue