Create or open file. Save on add/remove/edit task

This commit is contained in:
Joseph Ferano 2023-06-07 23:34:40 +07:00
parent e7564f8f82
commit 6a323d06c1
4 changed files with 35 additions and 20 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/target /target
/.idea/ /.idea/
/kanban-tui.json /kanban-tui.json
/kanban.json

View File

@ -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 {

View File

@ -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();
},
_ => {} _ => {}
} }
} }

View File

@ -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()?;