forked from janek/mostr
		
	feat(tasks): display details on task without subtasks
This commit is contained in:
		
					parent
					
						
							
								12b7c909ab
							
						
					
				
			
			
				commit
				
					
						3b9fedd9a3
					
				
			
		
					 2 changed files with 26 additions and 17 deletions
				
			
		| 
						 | 
					@ -456,12 +456,12 @@ async fn main() {
 | 
				
			||||||
                    Some('(') => {
 | 
					                    Some('(') => {
 | 
				
			||||||
                        if let Some(arg) = arg {
 | 
					                        if let Some(arg) = arg {
 | 
				
			||||||
                            if tasks.track_from(arg) {
 | 
					                            if tasks.track_from(arg) {
 | 
				
			||||||
                                let (prefix, tracked) = tasks.times_tracked();
 | 
					                                let (label, times) = tasks.times_tracked();
 | 
				
			||||||
                                println!("{}\n{}", prefix.bold(), tracked.rev().take(15).join("\n"));
 | 
					                                println!("{}\n{}", label.italic(), times.rev().take(15).join("\n"));
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            let (prefix, mut tracked) = tasks.times_tracked();
 | 
					                            let (label, mut times) = tasks.times_tracked();
 | 
				
			||||||
                            println!("{}\n{}", prefix.bold(), tracked.join("\n"));
 | 
					                            println!("{}\n{}", label.italic(), times.join("\n"));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										35
									
								
								src/tasks.rs
									
										
									
									
									
								
							
							
						
						
									
										35
									
								
								src/tasks.rs
									
										
									
									
									
								
							| 
						 | 
					@ -37,7 +37,6 @@ pub(crate) struct Tasks {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// A filtered view of the current tasks
 | 
					    /// A filtered view of the current tasks
 | 
				
			||||||
    view: Vec<EventId>,
 | 
					    view: Vec<EventId>,
 | 
				
			||||||
    /// Negative: Only Leaf nodes
 | 
					 | 
				
			||||||
    /// Zero: Only Active node
 | 
					    /// Zero: Only Active node
 | 
				
			||||||
    /// Positive: Go down the respective level
 | 
					    /// Positive: Go down the respective level
 | 
				
			||||||
    depth: i8,
 | 
					    depth: i8,
 | 
				
			||||||
| 
						 | 
					@ -187,10 +186,11 @@ impl Tasks {
 | 
				
			||||||
                            .map(|str| EventId::from_str(str).ok().map_or(str.to_string(), |id| self.get_task_title(&id)))
 | 
					                            .map(|str| EventId::from_str(str).ok().map_or(str.to_string(), |id| self.get_task_title(&id)))
 | 
				
			||||||
                            .join(" "));
 | 
					                            .join(" "));
 | 
				
			||||||
                        if new.as_ref() != full.last() {
 | 
					                        if new.as_ref() != full.last() {
 | 
				
			||||||
 | 
					                            // TODO alternating color for days
 | 
				
			||||||
                            full.push(format!("{:>15} {}", relative_datetimestamp(&event.created_at), new.as_ref().unwrap_or(&"---".to_string())));
 | 
					                            full.push(format!("{:>15} {}", relative_datetimestamp(&event.created_at), new.as_ref().unwrap_or(&"---".to_string())));
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    ("Your Time Tracking History:".to_string(), Box::from(full.into_iter()))
 | 
					                    ("Your Time-Tracking History:".to_string(), Box::from(full.into_iter()))
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    ("You have nothing tracked yet".to_string(), Box::from(empty()))
 | 
					                    ("You have nothing tracked yet".to_string(), Box::from(empty()))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -217,14 +217,14 @@ impl Tasks {
 | 
				
			||||||
                            vec.push(format!("{} started by {}", local_datetimestamp(stamp), key)));
 | 
					                            vec.push(format!("{} started by {}", local_datetimestamp(stamp), key)));
 | 
				
			||||||
                        vec
 | 
					                        vec
 | 
				
			||||||
                    }).sorted_unstable(); // TODO sorting depends on timestamp format - needed to interleave different people
 | 
					                    }).sorted_unstable(); // TODO sorting depends on timestamp format - needed to interleave different people
 | 
				
			||||||
                (format!("Times tracked on {}", self.get_task_title(&id)), Box::from(history))
 | 
					                (format!("Times Tracked on {:?}", self.get_task_title(&id)), Box::from(history))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Total time in seconds tracked on this task by the current user.
 | 
					    /// Total time in seconds tracked on this task by the current user.
 | 
				
			||||||
    pub(crate) fn time_tracked(&self, id: EventId) -> u64 {
 | 
					    pub(crate) fn time_tracked(&self, id: EventId) -> u64 {
 | 
				
			||||||
        TimesTracked::from(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &vec![&id]).sum::<Duration>().as_secs()
 | 
					        Durations::from(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &vec![&id]).sum::<Duration>().as_secs()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -234,7 +234,7 @@ impl Tasks {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let children = self.get_task_tree(&id).get_all();
 | 
					        let children = self.get_task_tree(&id).get_all();
 | 
				
			||||||
        for user in self.history.values() {
 | 
					        for user in self.history.values() {
 | 
				
			||||||
            total += TimesTracked::from(user, &children).into_iter().sum::<Duration>().as_secs();
 | 
					            total += Durations::from(user, &children).sum::<Duration>().as_secs();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        total
 | 
					        total
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -381,7 +381,7 @@ impl Tasks {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(crate) fn visible_tasks(&self) -> Vec<&Task> {
 | 
					    pub(crate) fn visible_tasks(&self) -> Vec<&Task> {
 | 
				
			||||||
        if self.depth == 0 {
 | 
					        if self.depth == 0 {
 | 
				
			||||||
            return self.get_current_task().into_iter().collect();
 | 
					            return vec![];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if self.view.len() > 0 {
 | 
					        if self.view.len() > 0 {
 | 
				
			||||||
            return self.resolve_tasks(self.view.iter()).collect();
 | 
					            return self.resolve_tasks(self.view.iter()).collect();
 | 
				
			||||||
| 
						 | 
					@ -413,11 +413,21 @@ impl Tasks {
 | 
				
			||||||
            )?;
 | 
					            )?;
 | 
				
			||||||
            writeln!(lock, "{}", t.descriptions().join("\n"))?;
 | 
					            writeln!(lock, "{}", t.descriptions().join("\n"))?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut tasks = self.visible_tasks();
 | 
				
			||||||
 | 
					        if tasks.is_empty() {
 | 
				
			||||||
 | 
					            let (label, times) = self.times_tracked();
 | 
				
			||||||
 | 
					            let mut times_recent = times.rev().take(6).collect_vec();
 | 
				
			||||||
 | 
					            times_recent.reverse();
 | 
				
			||||||
 | 
					            // TODO Add recent prefix
 | 
				
			||||||
 | 
					            writeln!(lock, "{}\n{}", label.italic(), times_recent.join("\n"))?;
 | 
				
			||||||
 | 
					            return Ok(());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        // TODO proper column alignment
 | 
					        // TODO proper column alignment
 | 
				
			||||||
        // TODO hide empty columns
 | 
					        // TODO hide empty columns
 | 
				
			||||||
        writeln!(lock, "{}", self.properties.join("\t").bold())?;
 | 
					        writeln!(lock, "{}", self.properties.join("\t").bold())?;
 | 
				
			||||||
        let mut total_time = 0;
 | 
					        let mut total_time = 0;
 | 
				
			||||||
        let mut tasks = self.visible_tasks();
 | 
					 | 
				
			||||||
        let count = tasks.len();
 | 
					        let count = tasks.len();
 | 
				
			||||||
        tasks.sort_by_cached_key(|task| {
 | 
					        tasks.sort_by_cached_key(|task| {
 | 
				
			||||||
            self.sorting
 | 
					            self.sorting
 | 
				
			||||||
| 
						 | 
					@ -951,22 +961,21 @@ fn timestamps<'a>(events: impl Iterator<Item=&'a Event>, ids: &'a Vec<&'a EventI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Iterates Events to accumulate times tracked
 | 
					/// Iterates Events to accumulate times tracked
 | 
				
			||||||
/// Expects a sorted iterator
 | 
					/// Expects a sorted iterator
 | 
				
			||||||
struct TimesTracked<'a> {
 | 
					struct Durations<'a> {
 | 
				
			||||||
    events: Box<dyn Iterator<Item=&'a Event> + 'a>,
 | 
					    events: Box<dyn Iterator<Item=&'a Event> + 'a>,
 | 
				
			||||||
    ids: &'a Vec<&'a EventId>,
 | 
					    ids: &'a Vec<&'a EventId>,
 | 
				
			||||||
    threshold: Option<Timestamp>,
 | 
					    threshold: Option<Timestamp>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl TimesTracked<'_> {
 | 
					impl Durations<'_> {
 | 
				
			||||||
    fn from<'b>(events: impl IntoIterator<Item=&'b Event> + 'b, ids: &'b Vec<&EventId>) -> TimesTracked<'b> {
 | 
					    fn from<'b>(events: impl IntoIterator<Item=&'b Event> + 'b, ids: &'b Vec<&EventId>) -> Durations<'b> {
 | 
				
			||||||
        TimesTracked {
 | 
					        Durations {
 | 
				
			||||||
            events: Box::new(events.into_iter()),
 | 
					            events: Box::new(events.into_iter()),
 | 
				
			||||||
            ids,
 | 
					            ids,
 | 
				
			||||||
            threshold: Some(Timestamp::now()),
 | 
					            threshold: Some(Timestamp::now()),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					impl Iterator for Durations<'_> {
 | 
				
			||||||
impl Iterator for TimesTracked<'_> {
 | 
					 | 
				
			||||||
    type Item = Duration;
 | 
					    type Item = Duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue