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.append(
|
||||
>k::Label::builder()
|
||||
.halign(gtk::Align::Start)
|
||||
.label("15km of biking in 60 minutes")
|
||||
.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 emseries::{Record, Recordable, Timestamp};
|
||||
use chrono::{Duration, Local, NaiveDate};
|
||||
use emseries::Record;
|
||||
use ft_core::TraxRecord;
|
||||
use glib::Object;
|
||||
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
|
||||
/// daily summaries, daily details, and will provide all functions the user may need for editing
|
||||
/// records.
|
||||
pub struct HistoricalViewPrivate {}
|
||||
pub struct HistoricalViewPrivate {
|
||||
time_window: RefCell<DayInterval>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for HistoricalViewPrivate {
|
||||
|
@ -33,7 +36,9 @@ impl ObjectSubclass for HistoricalViewPrivate {
|
|||
type ParentType = gtk::Box;
|
||||
|
||||
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_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>();
|
||||
model.extend_from_slice(&day_records.0);
|
||||
let mut model = gio::ListStore::new::<DayRecords>();
|
||||
model.extend(grouped_records.items());
|
||||
|
||||
let factory = gtk::SignalListItemFactory::new();
|
||||
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 {
|
||||
fn from(records: Vec<Record<TraxRecord>>) -> GroupedRecords {
|
||||
GroupedRecords(
|
||||
records
|
||||
.into_iter()
|
||||
.fold(HashMap::new(), |mut acc, rec| {
|
||||
acc.entry(rec.date())
|
||||
.and_modify(|entry: &mut DayRecords| (*entry).add_record(rec.clone()))
|
||||
.or_insert(DayRecords::new(rec.date(), vec![rec]));
|
||||
acc
|
||||
impl GroupedRecords {
|
||||
fn new(interval: DayInterval) -> Self {
|
||||
let mut s = Self {
|
||||
interval: interval.clone(),
|
||||
data: HashMap::new(),
|
||||
};
|
||||
interval.days().for_each(|date| {
|
||||
let _ = s.data.insert(date, DayRecords::new(date, vec![]));
|
||||
});
|
||||
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