Month -> 31 trailing days
This commit is contained in:
parent
e62832fde6
commit
360af2f0cb
2 changed files with 45 additions and 33 deletions
32
src/app.rs
32
src/app.rs
|
|
@ -28,7 +28,7 @@ pub enum Screen {
|
|||
pub enum LogViewPeriod {
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
Month, // Represents the last 31 days
|
||||
}
|
||||
|
||||
pub enum LogViewDayOrder {
|
||||
|
|
@ -1587,17 +1587,29 @@ impl App {
|
|||
}
|
||||
|
||||
fn load_log_content(&mut self) -> anyhow::Result<()> {
|
||||
let flag = match self.log_view_period {
|
||||
LogViewPeriod::Day => "--day",
|
||||
LogViewPeriod::Week => "--week",
|
||||
LogViewPeriod::Month => "--month",
|
||||
let mut command = Command::new("watson");
|
||||
command.arg("log").arg("--json");
|
||||
|
||||
// Handle different period options
|
||||
match self.log_view_period {
|
||||
LogViewPeriod::Day => {
|
||||
command.arg("--day");
|
||||
},
|
||||
LogViewPeriod::Week => {
|
||||
command.arg("--week");
|
||||
},
|
||||
LogViewPeriod::Month => {
|
||||
// Use --from with date 31 days ago for month view
|
||||
let thirty_one_days_ago = chrono::Local::now()
|
||||
.checked_sub_signed(chrono::Duration::days(31))
|
||||
.expect("Failed to calculate date from 31 days ago");
|
||||
|
||||
command.arg("--from");
|
||||
command.arg(thirty_one_days_ago.format("%Y-%m-%d").to_string());
|
||||
},
|
||||
};
|
||||
|
||||
let output = Command::new("watson")
|
||||
.arg("log")
|
||||
.arg(flag)
|
||||
.arg("--json")
|
||||
.output()?;
|
||||
let output = command.output()?;
|
||||
|
||||
if output.status.success() {
|
||||
let json_str = String::from_utf8_lossy(&output.stdout);
|
||||
|
|
|
|||
46
src/ui.rs
46
src/ui.rs
|
|
@ -33,10 +33,10 @@ fn render_main(frame: &mut Frame, app: &App) {
|
|||
let has_active_timer = app.state.active_timer.is_some();
|
||||
let has_status = app.status_message.is_some();
|
||||
let show_help_hint = app.config.show_help_hint;
|
||||
|
||||
|
||||
// Show bottom bar if we have any of: timer, status, or help hint
|
||||
let show_bottom_bar = has_active_timer || has_status || show_help_hint;
|
||||
|
||||
|
||||
let bottom_height = if show_bottom_bar {
|
||||
if has_status {
|
||||
2 // Need extra line for status
|
||||
|
|
@ -63,41 +63,41 @@ fn render_main(frame: &mut Frame, app: &App) {
|
|||
.borders(Borders::ALL)
|
||||
.title("WAT")
|
||||
.style(Style::default().fg(ACTIVE_COLOR));
|
||||
|
||||
|
||||
let text = Paragraph::new("No sections enabled. Edit config (press 'c') to enable sections.")
|
||||
.block(block)
|
||||
.style(Style::default().fg(Color::Yellow))
|
||||
.alignment(Alignment::Center);
|
||||
|
||||
|
||||
frame.render_widget(text, frame.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Build constraints for enabled sections
|
||||
let mut constraints = Vec::new();
|
||||
|
||||
|
||||
if bottom_height > 0 {
|
||||
// Reserve space for bottom bar first, then split remainder among sections
|
||||
constraints.push(Constraint::Min(0)); // Sections get remaining space
|
||||
constraints.push(Constraint::Length(bottom_height)); // Bottom bar gets fixed height
|
||||
|
||||
|
||||
let layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(constraints)
|
||||
.split(frame.size());
|
||||
|
||||
|
||||
// Split the top area among enabled sections
|
||||
let section_percentage = 100 / enabled_sections as u16;
|
||||
let section_constraints = vec![Constraint::Percentage(section_percentage); enabled_sections];
|
||||
|
||||
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(section_constraints)
|
||||
.split(layout[0]);
|
||||
|
||||
|
||||
// Render enabled sections
|
||||
let mut chunk_idx = 0;
|
||||
|
||||
|
||||
if app.config.show_permanent {
|
||||
render_section(
|
||||
frame,
|
||||
|
|
@ -145,14 +145,14 @@ fn render_main(frame: &mut Frame, app: &App) {
|
|||
// No bottom bar - just render sections
|
||||
let section_percentage = 100 / enabled_sections as u16;
|
||||
let constraints = vec![Constraint::Percentage(section_percentage); enabled_sections];
|
||||
|
||||
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(constraints)
|
||||
.split(frame.size());
|
||||
|
||||
let mut chunk_idx = 0;
|
||||
|
||||
|
||||
if app.config.show_permanent {
|
||||
render_section(
|
||||
frame,
|
||||
|
|
@ -679,7 +679,7 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
let period_str = match app.log_view_period {
|
||||
LogViewPeriod::Day => "Day",
|
||||
LogViewPeriod::Week => "Week",
|
||||
LogViewPeriod::Month => "Month",
|
||||
LogViewPeriod::Month => "31 Days",
|
||||
};
|
||||
|
||||
let grouping_str = match app.log_view_grouping {
|
||||
|
|
@ -812,14 +812,14 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
|
||||
// Third pass: render with highlighting and overlap detection
|
||||
let is_by_date = matches!(app.log_view_grouping, LogViewGrouping::ByDate);
|
||||
|
||||
|
||||
// Pre-calculate overlaps for efficiency - check consecutive entries within same day
|
||||
let mut overlap_entry_indices = std::collections::HashSet::new();
|
||||
if is_by_date && app.log_view_frame_indices.len() > 1 {
|
||||
// Track which day we're in to avoid comparing across days
|
||||
let mut current_day_start_entry = 0;
|
||||
let mut in_day = false;
|
||||
|
||||
|
||||
for (line_idx, line) in app.log_view_content.iter().enumerate() {
|
||||
// New day header
|
||||
if !line.starts_with(" ") && !line.is_empty() && !line.starts_with(" ") {
|
||||
|
|
@ -835,12 +835,12 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
.filter(|l| l.starts_with(" ") && !l.is_empty() && l.trim() != "---")
|
||||
.count()
|
||||
.saturating_sub(1);
|
||||
|
||||
|
||||
// Only check overlap if not the first entry of the day
|
||||
if entry_idx > current_day_start_entry {
|
||||
let current_frame_idx = app.log_view_frame_indices[entry_idx];
|
||||
let prev_frame_idx = app.log_view_frame_indices[entry_idx - 1];
|
||||
|
||||
|
||||
if let (Some(current), Some(prev)) = (
|
||||
app.log_view_frames.get(current_frame_idx),
|
||||
app.log_view_frames.get(prev_frame_idx),
|
||||
|
|
@ -859,16 +859,16 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
app.log_view_content
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, line)| {
|
||||
let is_selected = idx >= selected_line_start && idx <= selected_line_end;
|
||||
|
||||
|
||||
// Skip styling for separator lines
|
||||
let is_separator = line.trim() == "---";
|
||||
|
||||
|
||||
// Check if this line corresponds to an overlapping entry
|
||||
let has_overlap = if !is_separator && is_by_date && line.starts_with(" ") && !line.is_empty() {
|
||||
// Count which entry this is (0-based in display order)
|
||||
|
|
@ -878,7 +878,7 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
.filter(|l| l.starts_with(" ") && !l.is_empty() && l.trim() != "---")
|
||||
.count()
|
||||
.saturating_sub(1);
|
||||
|
||||
|
||||
overlap_entry_indices.contains(&entry_idx)
|
||||
} else {
|
||||
false
|
||||
|
|
@ -904,7 +904,7 @@ fn render_log_view(frame: &mut Frame, app: &App) {
|
|||
let paragraph = Paragraph::new(text_lines)
|
||||
.block(block)
|
||||
.wrap(ratatui::widgets::Wrap { trim: false });
|
||||
|
||||
|
||||
frame.render_widget(paragraph, chunks[0]);
|
||||
|
||||
// Render help hint at bottom if enabled
|
||||
|
|
@ -928,7 +928,7 @@ fn render_log_view_help(frame: &mut Frame, app: &App) {
|
|||
"Time Periods:",
|
||||
"- d: Switch to Day view (current day)",
|
||||
"- w: Switch to Week view (current week)",
|
||||
"- m: Switch to Month view (current month)",
|
||||
"- m: Switch to Month view (last 31 days)",
|
||||
"",
|
||||
"Grouping:",
|
||||
"- g: Toggle between grouping by Date or by Project",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue