Formatting
This commit is contained in:
		
							parent
							
								
									2e2145b2ab
								
							
						
					
					
						commit
						9b4341ccf1
					
				
							
								
								
									
										29
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/app.rs
									
									
									
									
									
								
							@ -1,13 +1,15 @@
 | 
			
		||||
use std::cmp::min;
 | 
			
		||||
use indexmap::IndexMap;
 | 
			
		||||
use int_enum::IntEnum;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::cmp::min;
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests;
 | 
			
		||||
 | 
			
		||||
#[repr(usize)]
 | 
			
		||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, IntEnum)]
 | 
			
		||||
#[derive(
 | 
			
		||||
    Deserialize, Serialize, Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, IntEnum,
 | 
			
		||||
)]
 | 
			
		||||
pub enum TaskStatus {
 | 
			
		||||
    Todo = 0,
 | 
			
		||||
    InProgress = 1,
 | 
			
		||||
@ -50,12 +52,12 @@ impl Project {
 | 
			
		||||
    pub fn new(name: &str) -> Self {
 | 
			
		||||
        Project {
 | 
			
		||||
            name: name.to_owned(),
 | 
			
		||||
            tasks_per_column: IndexMap::from(
 | 
			
		||||
                [(TaskStatus::Done, vec![]),
 | 
			
		||||
                    (TaskStatus::Todo, vec![]),
 | 
			
		||||
                    (TaskStatus::InProgress, vec![]),
 | 
			
		||||
                    (TaskStatus::Ideas, vec![])],
 | 
			
		||||
            ),
 | 
			
		||||
            tasks_per_column: IndexMap::from([
 | 
			
		||||
                (TaskStatus::Done, vec![]),
 | 
			
		||||
                (TaskStatus::Todo, vec![]),
 | 
			
		||||
                (TaskStatus::InProgress, vec![]),
 | 
			
		||||
                (TaskStatus::Ideas, vec![]),
 | 
			
		||||
            ]),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -146,7 +148,10 @@ impl AppState {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn select_next_column(&mut self) {
 | 
			
		||||
        self.selected_column = min(self.selected_column + 1, self.project.tasks_per_column.len() - 1)
 | 
			
		||||
        self.selected_column = min(
 | 
			
		||||
            self.selected_column + 1,
 | 
			
		||||
            self.project.tasks_per_column.len() - 1,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn move_task_previous_column(&mut self) {
 | 
			
		||||
@ -166,7 +171,10 @@ impl AppState {
 | 
			
		||||
    pub fn move_task_next_column(&mut self) {
 | 
			
		||||
        let tasks = self.get_tasks_in_active_column();
 | 
			
		||||
        let task_idx = self.selected_task_idx();
 | 
			
		||||
        if self.selected_column < self.project.tasks_per_column.len() && tasks.len() > 0 && task_idx < tasks.len() {
 | 
			
		||||
        if self.selected_column < self.project.tasks_per_column.len()
 | 
			
		||||
            && tasks.len() > 0
 | 
			
		||||
            && task_idx < tasks.len()
 | 
			
		||||
        {
 | 
			
		||||
            let task = self.get_tasks_in_active_column_mut().remove(task_idx);
 | 
			
		||||
            *self.selected_task_idx_mut() = self.selected_task_idx().saturating_sub(1);
 | 
			
		||||
            self.select_next_column();
 | 
			
		||||
@ -197,4 +205,3 @@ impl AppState {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										91
									
								
								src/ui.rs
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								src/ui.rs
									
									
									
									
									
								
							@ -1,53 +1,59 @@
 | 
			
		||||
use tui::backend::{Backend};
 | 
			
		||||
use crate::app::*;
 | 
			
		||||
use tui::backend::Backend;
 | 
			
		||||
use tui::layout::*;
 | 
			
		||||
use tui::{Frame};
 | 
			
		||||
use tui::style::{Color, Modifier, Style};
 | 
			
		||||
use tui::text::{Span, Spans};
 | 
			
		||||
use tui::widgets::*;
 | 
			
		||||
use crate::app::*;
 | 
			
		||||
use tui::Frame;
 | 
			
		||||
 | 
			
		||||
fn draw_tasks<B: Backend>(f: &mut Frame<B>, area: &Rect, state: &AppState) {
 | 
			
		||||
    let columns = Layout::default()
 | 
			
		||||
        .direction(Direction::Horizontal)
 | 
			
		||||
        .constraints(
 | 
			
		||||
            vec![Constraint::Percentage(100 / state.project.tasks_per_column.len() as u16);
 | 
			
		||||
                 state.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.project.tasks_per_column.iter().enumerate() {
 | 
			
		||||
        let items: Vec<ListItem> = tasks.iter().enumerate().map(|(j, task)| {
 | 
			
		||||
            let mut style = Style::default();
 | 
			
		||||
            if i == state.selected_column && j == state.selected_task[state.selected_column] {
 | 
			
		||||
                style = style.fg(Color::White).add_modifier(Modifier::BOLD);
 | 
			
		||||
            } else {
 | 
			
		||||
                style = style.fg(Color::White);
 | 
			
		||||
            }
 | 
			
		||||
            let mut s = Span::raw(task.title.as_str());
 | 
			
		||||
            s.style = style;
 | 
			
		||||
            ListItem::new(vec![Spans::from(s)])
 | 
			
		||||
        }).collect();
 | 
			
		||||
        let items: Vec<ListItem> = tasks
 | 
			
		||||
            .iter()
 | 
			
		||||
            .enumerate()
 | 
			
		||||
            .map(|(j, task)| {
 | 
			
		||||
                let mut style = Style::default();
 | 
			
		||||
                if i == state.selected_column && j == state.selected_task[state.selected_column] {
 | 
			
		||||
                    style = style.fg(Color::White).add_modifier(Modifier::BOLD);
 | 
			
		||||
                } else {
 | 
			
		||||
                    style = style.fg(Color::White);
 | 
			
		||||
                }
 | 
			
		||||
                let mut s = Span::raw(task.title.as_str());
 | 
			
		||||
                s.style = style;
 | 
			
		||||
                ListItem::new(vec![Spans::from(s)])
 | 
			
		||||
            })
 | 
			
		||||
            .collect();
 | 
			
		||||
        let mut style = Style::default();
 | 
			
		||||
        if i == state.selected_column { style = style.fg(Color::Green); };
 | 
			
		||||
        if i == state.selected_column {
 | 
			
		||||
            style = style.fg(Color::Green);
 | 
			
		||||
        };
 | 
			
		||||
        let mut s = Span::raw(format!("{:?}", status));
 | 
			
		||||
        s.style = Style::default()
 | 
			
		||||
            .add_modifier(Modifier::BOLD | Modifier::ITALIC | Modifier::UNDERLINED)
 | 
			
		||||
            .fg(Color::White);
 | 
			
		||||
        let block = Block::default()
 | 
			
		||||
            .style(style)
 | 
			
		||||
            .title(s)
 | 
			
		||||
            .borders(Borders::ALL);
 | 
			
		||||
        let block = Block::default().style(style).title(s).borders(Borders::ALL);
 | 
			
		||||
        let list = List::new(items).block(block);
 | 
			
		||||
        f.render_widget(list, columns[i])
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn draw_task_info<B: Backend>(f: &mut Frame<B>, area: &Rect, state: &AppState) {
 | 
			
		||||
    let block = Block::default()
 | 
			
		||||
        .title("TASK INFO")
 | 
			
		||||
        .borders(Borders::ALL);
 | 
			
		||||
    let block = Block::default().title("TASK INFO").borders(Borders::ALL);
 | 
			
		||||
    if let Some(task) = state.get_selected_task() {
 | 
			
		||||
        let p = Paragraph::new(task.description.as_str()).block(block).wrap(Wrap { trim: true });
 | 
			
		||||
        let p = Paragraph::new(task.description.as_str())
 | 
			
		||||
            .block(block)
 | 
			
		||||
            .wrap(Wrap { trim: true });
 | 
			
		||||
        f.render_widget(p, *area);
 | 
			
		||||
    } else {
 | 
			
		||||
        let p = Paragraph::new("No tasks for this column").block(block);
 | 
			
		||||
@ -63,7 +69,7 @@ fn centered_rect_for_popup(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
 | 
			
		||||
                Constraint::Percentage(percent_y),
 | 
			
		||||
                Constraint::Percentage((100 - percent_y) / 2),
 | 
			
		||||
            ]
 | 
			
		||||
                .as_ref(),
 | 
			
		||||
            .as_ref(),
 | 
			
		||||
        )
 | 
			
		||||
        .split(r);
 | 
			
		||||
 | 
			
		||||
@ -75,7 +81,7 @@ fn centered_rect_for_popup(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
 | 
			
		||||
                Constraint::Percentage(percent_x),
 | 
			
		||||
                Constraint::Percentage((100 - percent_x) / 2),
 | 
			
		||||
            ]
 | 
			
		||||
                .as_ref(),
 | 
			
		||||
            .as_ref(),
 | 
			
		||||
        )
 | 
			
		||||
        .split(popup_layout[1])[1]
 | 
			
		||||
}
 | 
			
		||||
@ -86,12 +92,12 @@ pub fn draw_new_task_popup<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
 | 
			
		||||
    match &state.popup_text {
 | 
			
		||||
        None => {}
 | 
			
		||||
        Some(s) => {
 | 
			
		||||
            let block = Block::default().title("Add Task")
 | 
			
		||||
            let block = Block::default()
 | 
			
		||||
                .title("Add Task")
 | 
			
		||||
                .title_alignment(Alignment::Center)
 | 
			
		||||
                .borders(Borders::ALL);
 | 
			
		||||
            let block_inner = block.inner(area);
 | 
			
		||||
            let main = Paragraph::new(s.as_ref())
 | 
			
		||||
                .block(block);
 | 
			
		||||
            let main = Paragraph::new(s.as_ref()).block(block);
 | 
			
		||||
            let layout = Layout::default()
 | 
			
		||||
                .direction(Direction::Vertical)
 | 
			
		||||
                .constraints(
 | 
			
		||||
@ -99,8 +105,10 @@ pub fn draw_new_task_popup<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
 | 
			
		||||
                        Constraint::Length(3),
 | 
			
		||||
                        Constraint::Max(100),
 | 
			
		||||
                        Constraint::Length(2),
 | 
			
		||||
                    ].as_ref()
 | 
			
		||||
                ).split(block_inner);
 | 
			
		||||
                    ]
 | 
			
		||||
                    .as_ref(),
 | 
			
		||||
                )
 | 
			
		||||
                .split(block_inner);
 | 
			
		||||
            let b1 = Block::default().title("Title").borders(Borders::ALL);
 | 
			
		||||
            let title = Paragraph::new("Hello I am text")
 | 
			
		||||
                // .style(Style::default().fg(Color::Yellow))
 | 
			
		||||
@ -110,8 +118,7 @@ pub fn draw_new_task_popup<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
 | 
			
		||||
                // .style(Style::default().fg(Color::Yellow))
 | 
			
		||||
                .block(b2);
 | 
			
		||||
            let b3 = Block::default().title("Keys").borders(Borders::TOP);
 | 
			
		||||
            let footer = Paragraph::new("p : Cancel")
 | 
			
		||||
                .block(b3);
 | 
			
		||||
            let footer = Paragraph::new("p : Cancel").block(b3);
 | 
			
		||||
            f.render_widget(main, area);
 | 
			
		||||
            f.render_widget(title, layout[0]);
 | 
			
		||||
            f.render_widget(description, layout[1]);
 | 
			
		||||
@ -129,21 +136,19 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
 | 
			
		||||
                Constraint::Percentage(65),
 | 
			
		||||
                Constraint::Percentage(20),
 | 
			
		||||
                Constraint::Length(3),
 | 
			
		||||
            ].as_ref()
 | 
			
		||||
        ).split(f.size());
 | 
			
		||||
            ]
 | 
			
		||||
            .as_ref(),
 | 
			
		||||
        )
 | 
			
		||||
        .split(f.size());
 | 
			
		||||
 | 
			
		||||
    let block = Block::default()
 | 
			
		||||
        .title("KANBAN BOARD")
 | 
			
		||||
        .borders(Borders::ALL);
 | 
			
		||||
    let block = Block::default().title("KANBAN BOARD").borders(Borders::ALL);
 | 
			
		||||
    f.render_widget(block, main_layout[0]);
 | 
			
		||||
 | 
			
		||||
    draw_tasks(f, &main_layout[1], &state);
 | 
			
		||||
 | 
			
		||||
    draw_task_info(f, &main_layout[2], &state);
 | 
			
		||||
 | 
			
		||||
    let block = Block::default()
 | 
			
		||||
        .title("KEYBINDINGS")
 | 
			
		||||
        .borders(Borders::TOP);
 | 
			
		||||
    let block = Block::default().title("KEYBINDINGS").borders(Borders::TOP);
 | 
			
		||||
 | 
			
		||||
    let foot_txt =
 | 
			
		||||
        Paragraph::new("q : Quit | ⏪🔽🔼⏩ or hjkl : Navigation | < > or H L : Shift task left/right | = - or J K : Shift task up/down")
 | 
			
		||||
@ -153,4 +158,4 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
 | 
			
		||||
    if state.popup_text.is_some() {
 | 
			
		||||
        draw_new_task_popup(f, state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user