From c38fa823c919df854b15baba2e2571d17b1fb6c2 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Mon, 5 Dec 2022 00:32:48 +0400 Subject: [PATCH] Change columns up. Refactor input and state change code. --- src/input.rs | 19 ++++-------- src/types.rs | 83 ++++++++++++++++++++++++++++++++++------------------ src/ui.rs | 8 ++--- 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/src/input.rs b/src/input.rs index 05f19c5..953d720 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,28 +1,19 @@ -use std::cmp::min; use crossterm::event; use crossterm::event::{Event, KeyCode}; -use int_enum::IntEnum; -use crate::types::{AppState, TaskStatus}; +use crate::types::{AppState}; pub fn handle_input(state: &mut AppState) -> Result<(), std::io::Error> { if let Event::Key(key) = event::read()? { match key.code { KeyCode::Char('q') => state.quit = true, KeyCode::Char('h') | - KeyCode::Left => state.selected_column = state.selected_column.saturating_sub(1), + KeyCode::Left => state.select_previous_column(), KeyCode::Char('j') | - KeyCode::Down => { - let column: TaskStatus = TaskStatus::from_int(state.selected_column).unwrap(); - let tasks = state.current_project.tasks_per_column.get(&column).unwrap(); - if tasks.len() > 0 { - let mins = min(state.selected_task[state.selected_column] + 1, tasks.len() - 1); - state.selected_task[state.selected_column] = mins; - } - } + KeyCode::Down => state.select_next_task(), KeyCode::Char('k') | - KeyCode::Up => state.selected_task[state.selected_column] = state.selected_task[state.selected_column].saturating_sub(1), + KeyCode::Up => state.select_previous_task(), KeyCode::Char('l') | - KeyCode::Right => state.selected_column = min(state.selected_column + 1, 4), + KeyCode::Right => state.select_next_column(), _ => {} } } diff --git a/src/types.rs b/src/types.rs index 1afae98..53df369 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,3 +1,4 @@ +use std::cmp::min; use indexmap::IndexMap; use int_enum::IntEnum; use serde::{Deserialize, Serialize}; @@ -5,13 +6,13 @@ use serde::{Deserialize, Serialize}; #[repr(usize)] #[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, IntEnum)] pub enum TaskStatus { - Done = 0, - Todo = 1, - InProgress = 2, - Testing = 3, - Backlog = 4, + Todo = 0, + InProgress = 1, + Done = 2, + Ideas = 3, } +// #[derive(Deserialize, Serialize, Debug, Clone, Copy)] #[derive(Deserialize, Serialize, Debug)] pub struct Task { pub title: String, @@ -27,6 +28,7 @@ impl Default for Task { } } +/// Type used mainly for serialization at this time #[derive(Deserialize, Serialize, Debug)] pub struct Project { pub name: String, @@ -41,15 +43,30 @@ impl Project { [(TaskStatus::Done, vec![]), (TaskStatus::Todo, vec![]), (TaskStatus::InProgress, vec![]), - (TaskStatus::Testing, vec![]), - (TaskStatus::Backlog, vec![])], + (TaskStatus::Ideas, vec![])], ), } } - fn add_task(&mut self, status: TaskStatus, task: Task) { + pub fn load() -> Self { + let json = std::fs::read_to_string("kanban-tui.json") + .expect("Could not read json file"); + serde_json::from_str(&json) + .expect("There is something wrong with the json schema, it doesn't match Project struct") + } + + pub fn add_task(&mut self, status: TaskStatus, task: Task) { self.tasks_per_column.entry(status).or_default().push(task); } + + /// Comment out cause this is dangerous + pub fn save() { + // let mut project = Project::new("Kanban Tui"); + // project.add_task(Task::default()); + // project.add_task(Task::default()); + // let json = serde_json::to_string_pretty(&project).unwrap(); + // std::fs::write("./project.json", json).unwrap(); + } } impl Default for Project { @@ -61,27 +78,10 @@ impl Default for Project { } } -impl Project { - pub fn load() -> Self { - let json = std::fs::read_to_string("kanban-tui.json") - .expect("Could not read json file"); - serde_json::from_str(&json) - .expect("There is something wrong with the json schema, it doesn't match Project struct") - } - /// Comment out cause this is dangerous - pub fn save() { - // let mut project = Project::new("Kanban Tui"); - // project.add_task(Task::default()); - // project.add_task(Task::default()); - // let json = serde_json::to_string_pretty(&project).unwrap(); - // std::fs::write("./project.json", json).unwrap(); - } -} - pub struct AppState { pub selected_column: usize, - pub selected_task: [usize; 5], - pub current_project: Project, + pub selected_task: [usize; 4], + pub project: Project, pub quit: bool, } @@ -89,10 +89,35 @@ impl AppState { pub fn new(project: Project) -> Self { AppState { selected_column: 0, - selected_task: [0, 0, 0, 0, 0], + selected_task: [0, 0, 0, 0], quit: false, - current_project: project, + project: project, } } + + pub fn get_tasks_in_active_column(&self) -> &Vec { + let column: TaskStatus = TaskStatus::from_int(self.selected_column).unwrap().clone(); + self.project.tasks_per_column.get(&column).unwrap() + } + + pub fn select_previous_task(&mut self) { + self.selected_task[self.selected_column] = self.selected_task[self.selected_column].saturating_sub(1) + } + + pub fn select_next_task(&mut self) { + let tasks = self.get_tasks_in_active_column(); + if tasks.len() > 0 { + let mins = min(self.selected_task[self.selected_column] + 1, tasks.len() - 1); + self.selected_task[self.selected_column] = mins; + } + } + + pub fn select_previous_column(&mut self) { + self.selected_column = self.selected_column.saturating_sub(1); + } + + pub fn select_next_column(&mut self) { + self.selected_column = min(self.selected_column + 1, self.project.tasks_per_column.len() - 1) + } } diff --git a/src/ui.rs b/src/ui.rs index 5314c1e..51b0a0d 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -11,12 +11,12 @@ fn draw_tasks(f: &mut Frame, area: &Rect, state: &AppState) { let columns = Layout::default() .direction(Direction::Horizontal) .constraints( - vec![Constraint::Percentage(20); - state.current_project.tasks_per_column.len()].as_ref() + vec![Constraint::Percentage(100 / state.project.tasks_per_column.len() as u16); + state.project.tasks_per_column.len()].as_ref() ) .split(*area); - for (i, (status, tasks)) in state.current_project.tasks_per_column.iter().enumerate() { + for (i, (status, tasks)) in state.project.tasks_per_column.iter().enumerate() { let items: Vec = tasks.iter().enumerate().map(|(j, task)| { let mut style = Style::default(); if i == state.selected_column && j == state.selected_task[state.selected_column] { @@ -48,7 +48,7 @@ fn draw_task_info(f: &mut Frame, area: &Rect, state: &AppState) { .title("TASK INFO") .borders(Borders::ALL); let column: TaskStatus = TaskStatus::from_int(state.selected_column).unwrap(); - let tasks = state.current_project.tasks_per_column.get(&column).unwrap(); + let tasks = state.project.tasks_per_column.get(&column).unwrap(); if tasks.len() > 0 { let task: &Task = &tasks[state.selected_task[state.selected_column]]; let p = Paragraph::new(task.description.as_str()).block(block).wrap(Wrap { trim: true });