Add 'view' page for log
This commit is contained in:
parent
cae499f3ee
commit
3220ff50cb
4 changed files with 194 additions and 15 deletions
120
src/app.rs
120
src/app.rs
|
|
@ -10,19 +10,29 @@ pub enum Screen {
|
|||
ConfigHelp,
|
||||
NewEntry,
|
||||
ReassignProject,
|
||||
LogView,
|
||||
}
|
||||
|
||||
pub enum LogViewPeriod {
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
pub state: AppState,
|
||||
pub config: Config,
|
||||
pub current_screen: Screen,
|
||||
pub needs_redraw: bool,
|
||||
pub needs_clear: bool,
|
||||
pub new_entry_buffer: String,
|
||||
pub new_entry_project: String,
|
||||
pub new_entry_cursor: usize,
|
||||
pub new_entry_mode: NewEntryMode, // Task or Project
|
||||
pub reassign_project_buffer: String,
|
||||
pub reassign_project_cursor: usize,
|
||||
pub log_view_period: LogViewPeriod,
|
||||
pub log_view_content: Vec<String>,
|
||||
pub log_view_scroll: usize,
|
||||
pub status_message: Option<(String, std::time::Instant)>,
|
||||
}
|
||||
|
||||
|
|
@ -37,13 +47,16 @@ impl App {
|
|||
state: AppState::load()?,
|
||||
config: Config::load()?,
|
||||
current_screen: Screen::Main,
|
||||
needs_redraw: true,
|
||||
needs_clear: false,
|
||||
new_entry_buffer: String::new(),
|
||||
new_entry_project: String::new(),
|
||||
new_entry_cursor: 0,
|
||||
new_entry_mode: NewEntryMode::Task,
|
||||
reassign_project_buffer: String::new(),
|
||||
reassign_project_cursor: 0,
|
||||
log_view_period: LogViewPeriod::Day,
|
||||
log_view_content: Vec::new(),
|
||||
log_view_scroll: 0,
|
||||
status_message: None,
|
||||
})
|
||||
}
|
||||
|
|
@ -52,13 +65,24 @@ impl App {
|
|||
// Update status message
|
||||
self.update_status_message();
|
||||
|
||||
match self.current_screen {
|
||||
let previous_screen = std::mem::discriminant(&self.current_screen);
|
||||
|
||||
let result = match self.current_screen {
|
||||
Screen::Main => self.handle_main_event(event),
|
||||
Screen::Help => self.handle_help_event(event),
|
||||
Screen::ConfigHelp => self.handle_config_help_event(event),
|
||||
Screen::NewEntry => self.handle_new_entry_event(event),
|
||||
Screen::ReassignProject => self.handle_reassign_project_event(event),
|
||||
Screen::LogView => self.handle_log_view_event(event),
|
||||
};
|
||||
|
||||
// If we switched screens, signal that we need to clear
|
||||
let current_screen = std::mem::discriminant(&self.current_screen);
|
||||
if previous_screen != current_screen {
|
||||
self.needs_clear = true;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn handle_main_event(&mut self, event: Event) -> anyhow::Result<bool> {
|
||||
|
|
@ -79,6 +103,7 @@ impl App {
|
|||
(KeyCode::Char('c'), _) => self.edit_app_config()?,
|
||||
(KeyCode::Char('n'), _) => self.start_new_entry(),
|
||||
(KeyCode::Char('p'), _) => self.start_reassign_project(),
|
||||
(KeyCode::Char('v'), _) => self.start_log_view()?,
|
||||
(KeyCode::Char('d'), _) => self.delete_current_item()?,
|
||||
_ => {}
|
||||
},
|
||||
|
|
@ -244,6 +269,56 @@ impl App {
|
|||
Ok(false)
|
||||
}
|
||||
|
||||
fn handle_log_view_event(&mut self, event: Event) -> anyhow::Result<bool> {
|
||||
match event {
|
||||
Event::Key(KeyEvent { code, .. }) => match code {
|
||||
KeyCode::Esc | KeyCode::Char('q') => {
|
||||
self.current_screen = Screen::Main;
|
||||
self.log_view_scroll = 0;
|
||||
self.needs_clear = true;
|
||||
}
|
||||
KeyCode::Char('d') => {
|
||||
self.log_view_period = LogViewPeriod::Day;
|
||||
self.log_view_scroll = 0;
|
||||
self.load_log_content()?;
|
||||
self.needs_clear = true;
|
||||
}
|
||||
KeyCode::Char('w') => {
|
||||
self.log_view_period = LogViewPeriod::Week;
|
||||
self.log_view_scroll = 0;
|
||||
self.load_log_content()?;
|
||||
self.needs_clear = true;
|
||||
}
|
||||
KeyCode::Char('m') => {
|
||||
self.log_view_period = LogViewPeriod::Month;
|
||||
self.log_view_scroll = 0;
|
||||
self.load_log_content()?;
|
||||
self.needs_clear = true;
|
||||
}
|
||||
KeyCode::Char('j') | KeyCode::Down => {
|
||||
if self.log_view_scroll < self.log_view_content.len().saturating_sub(1) {
|
||||
self.log_view_scroll += 1;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('k') | KeyCode::Up => {
|
||||
if self.log_view_scroll > 0 {
|
||||
self.log_view_scroll -= 1;
|
||||
}
|
||||
}
|
||||
KeyCode::PageDown => {
|
||||
self.log_view_scroll = (self.log_view_scroll + 10)
|
||||
.min(self.log_view_content.len().saturating_sub(1));
|
||||
}
|
||||
KeyCode::PageUp => {
|
||||
self.log_view_scroll = self.log_view_scroll.saturating_sub(10);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn move_selection(&mut self, delta: i32) {
|
||||
let items_len = match self.state.current_pane {
|
||||
0 => self.state.permanent_items.len(),
|
||||
|
|
@ -379,6 +454,37 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
fn start_log_view(&mut self) -> anyhow::Result<()> {
|
||||
self.current_screen = Screen::LogView;
|
||||
self.log_view_period = LogViewPeriod::Day;
|
||||
self.log_view_scroll = 0;
|
||||
self.load_log_content()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 output = Command::new("watson").arg("log").arg(flag).output()?;
|
||||
|
||||
if output.status.success() {
|
||||
let content = String::from_utf8_lossy(&output.stdout);
|
||||
self.log_view_content = content.lines().map(|s| s.to_string()).collect();
|
||||
} else {
|
||||
let error = String::from_utf8_lossy(&output.stderr);
|
||||
self.log_view_content = vec![
|
||||
"Failed to load Watson log:".to_string(),
|
||||
error.to_string(),
|
||||
];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reassign_project_for_current_item(&mut self) -> anyhow::Result<()> {
|
||||
let items = match self.state.current_pane {
|
||||
0 => &mut self.state.permanent_items,
|
||||
|
|
@ -439,14 +545,14 @@ impl App {
|
|||
if status.success() {
|
||||
// Reload entire application state
|
||||
self.config = Config::load()?;
|
||||
// Signal for complete reload
|
||||
self.current_screen = Screen::Main;
|
||||
self.needs_redraw = true;
|
||||
}
|
||||
|
||||
// Return to TUI mode
|
||||
execute!(stdout(), EnterAlternateScreen)?;
|
||||
enable_raw_mode()?;
|
||||
|
||||
self.needs_clear = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -476,14 +582,14 @@ impl App {
|
|||
if status.success() {
|
||||
// Reload entire application state
|
||||
self.state = AppState::load()?;
|
||||
// Signal for complete reload
|
||||
self.current_screen = Screen::Main;
|
||||
self.needs_redraw = true;
|
||||
}
|
||||
|
||||
// Return to TUI mode
|
||||
execute!(stdout(), EnterAlternateScreen)?;
|
||||
enable_raw_mode()?;
|
||||
|
||||
self.needs_clear = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue