Create or open file. Save on add/remove/edit task
This commit is contained in:
		
							parent
							
								
									e7564f8f82
								
							
						
					
					
						commit
						6a323d06c1
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,3 +1,4 @@
 | 
				
			|||||||
/target
 | 
					/target
 | 
				
			||||||
/.idea/
 | 
					/.idea/
 | 
				
			||||||
/kanban-tui.json
 | 
					/kanban-tui.json
 | 
				
			||||||
 | 
					/kanban.json
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										44
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								src/app.rs
									
									
									
									
									
								
							@ -2,6 +2,8 @@
 | 
				
			|||||||
// use int_enum::IntEnum;
 | 
					// use int_enum::IntEnum;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use std::cmp::min;
 | 
					use std::cmp::min;
 | 
				
			||||||
 | 
					use std::fs::OpenOptions;
 | 
				
			||||||
 | 
					use std::io::Read;
 | 
				
			||||||
use tui_textarea::TextArea;
 | 
					use tui_textarea::TextArea;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
@ -34,6 +36,7 @@ impl Default for Task {
 | 
				
			|||||||
#[derive(Deserialize, Serialize, Debug)]
 | 
					#[derive(Deserialize, Serialize, Debug)]
 | 
				
			||||||
pub struct Project {
 | 
					pub struct Project {
 | 
				
			||||||
    pub name: String,
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub filepath: String,
 | 
				
			||||||
    pub selected_column_idx: usize,
 | 
					    pub selected_column_idx: usize,
 | 
				
			||||||
    pub columns: Vec<Column>
 | 
					    pub columns: Vec<Column>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -46,16 +49,6 @@ pub enum KanbanError {
 | 
				
			|||||||
    Io(#[from] std::io::Error),
 | 
					    Io(#[from] std::io::Error),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Default for Project {
 | 
					 | 
				
			||||||
    fn default() -> Self {
 | 
					 | 
				
			||||||
        Project {
 | 
					 | 
				
			||||||
            name: String::new(),
 | 
					 | 
				
			||||||
            columns: vec![],
 | 
					 | 
				
			||||||
            selected_column_idx: 0,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum TaskEditFocus {
 | 
					pub enum TaskEditFocus {
 | 
				
			||||||
    Title,
 | 
					    Title,
 | 
				
			||||||
@ -135,14 +128,14 @@ impl<'a> Column {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn select_next_task(&mut self) {
 | 
					    pub fn select_next_task(&mut self) {
 | 
				
			||||||
        let task_idx = &mut self.selected_task_idx;
 | 
					        let task_idx = &mut self.selected_task_idx;
 | 
				
			||||||
        *task_idx = min(*task_idx + 1, self.tasks.len() - 1)
 | 
					        *task_idx = min(*task_idx + 1, self.tasks.len().saturating_sub(1))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn select_last_task(&mut self) {
 | 
					    pub fn select_last_task(&mut self) {
 | 
				
			||||||
        self.selected_task_idx = self.tasks.len() - 1;
 | 
					        self.selected_task_idx = self.tasks.len() - 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub  fn get_task_state_from_curr_selected_task(&self) -> Option<TaskState<'a>> {
 | 
					    pub fn get_task_state_from_curr_selected_task(&self) -> Option<TaskState<'a>> {
 | 
				
			||||||
        self.get_selected_task().map(|t| {
 | 
					        self.get_selected_task().map(|t| {
 | 
				
			||||||
            TaskState {
 | 
					            TaskState {
 | 
				
			||||||
                title: TextArea::from(t.title.lines()),
 | 
					                title: TextArea::from(t.title.lines()),
 | 
				
			||||||
@ -155,10 +148,16 @@ impl<'a> Column {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Project {
 | 
					impl Project {
 | 
				
			||||||
    pub fn new(name: &str) -> Self {
 | 
					    pub fn new(name: &str, filepath: String) -> Self {
 | 
				
			||||||
        Project {
 | 
					        Project {
 | 
				
			||||||
            name: name.to_owned(),
 | 
					            name: name.to_owned(),
 | 
				
			||||||
            columns: vec![],
 | 
					            filepath,
 | 
				
			||||||
 | 
					            columns: vec![
 | 
				
			||||||
 | 
					                Column::new("Todo"),
 | 
				
			||||||
 | 
					                Column::new("InProgress"),
 | 
				
			||||||
 | 
					                Column::new("Done"),
 | 
				
			||||||
 | 
					                Column::new("Ideas"),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
            selected_column_idx: 0,
 | 
					            selected_column_idx: 0,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -168,13 +167,24 @@ impl Project {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn load(filepath: String) -> Result<Self, KanbanError> {
 | 
					    pub fn load(filepath: String) -> Result<Self, KanbanError> {
 | 
				
			||||||
        let json = std::fs::read_to_string(filepath)?;
 | 
					        let mut file = OpenOptions::new()
 | 
				
			||||||
        Self::load_from_json(&json)
 | 
					            .write(true)
 | 
				
			||||||
 | 
					            .read(true)
 | 
				
			||||||
 | 
					            .create(true)
 | 
				
			||||||
 | 
					            .open(&filepath)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut json = String::new();
 | 
				
			||||||
 | 
					        file.read_to_string(&mut json)?;
 | 
				
			||||||
 | 
					        if json.is_empty() {
 | 
				
			||||||
 | 
					            Ok(Project::new("", filepath))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Self::load_from_json(&json)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn save(&self) {
 | 
					    pub fn save(&self) {
 | 
				
			||||||
        let json = serde_json::to_string_pretty(&self).unwrap();
 | 
					        let json = serde_json::to_string_pretty(&self).unwrap();
 | 
				
			||||||
        std::fs::write("kanban-tui.json", json).unwrap();
 | 
					        std::fs::write(&self.filepath, json).unwrap();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn get_selected_column(&self) -> &Column {
 | 
					    pub fn get_selected_column(&self) -> &Column {
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,8 @@ pub fn handle_input(state: &mut AppState) -> Result<(), std::io::Error> {
 | 
				
			|||||||
                                } else {
 | 
					                                } else {
 | 
				
			||||||
                                    column.add_task(title, description);
 | 
					                                    column.add_task(title, description);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                state.task_edit_state = None
 | 
					                                state.task_edit_state = None;
 | 
				
			||||||
 | 
					                                project.save();
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            _ => (),
 | 
					                            _ => (),
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@ -83,7 +84,10 @@ pub fn handle_input(state: &mut AppState) -> Result<(), std::io::Error> {
 | 
				
			|||||||
                    KeyCode::Char('n') => state.task_edit_state = Some(TaskState::default()),
 | 
					                    KeyCode::Char('n') => state.task_edit_state = Some(TaskState::default()),
 | 
				
			||||||
                    KeyCode::Char('e') =>
 | 
					                    KeyCode::Char('e') =>
 | 
				
			||||||
                        state.task_edit_state = column.get_task_state_from_curr_selected_task(),
 | 
					                        state.task_edit_state = column.get_task_state_from_curr_selected_task(),
 | 
				
			||||||
                    KeyCode::Char('D') => column.remove_task(),
 | 
					                    KeyCode::Char('D') => {
 | 
				
			||||||
 | 
					                        column.remove_task();
 | 
				
			||||||
 | 
					                        project.save();
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
                    _ => {}
 | 
					                    _ => {}
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ use tui::backend::CrosstermBackend;
 | 
				
			|||||||
use tui::Terminal;
 | 
					use tui::Terminal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() -> anyhow::Result<()> {
 | 
					fn main() -> anyhow::Result<()> {
 | 
				
			||||||
    let pattern = env::args().nth(1).expect("Path to task database not provided");
 | 
					    let pattern = env::args().nth(1).unwrap_or("kanban.json".to_string());
 | 
				
			||||||
    let mut state = AppState::new(Project::load(pattern)?);
 | 
					    let mut state = AppState::new(Project::load(pattern)?);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enable_raw_mode()?;
 | 
					    enable_raw_mode()?;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user