Skip to content

Commit

Permalink
Merge pull request #2 from mark-pitblado/develop
Browse files Browse the repository at this point in the history
Add priority parsing and adjust column widths
  • Loading branch information
mark-pitblado authored Oct 28, 2024
2 parents 04b8018 + 7a37545 commit 1b5c6e6
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 17 deletions.
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
regex = "1"
toml = "0.5"
dirs = "4.0"
tokio = { version = "1", features = ["full"] }
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,14 @@ api_key = "<your-key-here>"
## Current Features

- View current tasks, with the ability to get details for any given task
- Add tasks (title only)
- Toggle between showing complete tasks and incomplete tasks (shows incomplete by default)
- Pagination of tasks.
- Add tasks
- Title
- Priority, via ![1-5] (vikunja quick add magic syntax)

## Roadmap

- [ ] Parse labels via `*label`
- [ ] Edit existing tasks

17 changes: 12 additions & 5 deletions src/api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::models::{Task, TaskDetail};
use reqwest::Client;
use std::collections::HashMap;
use serde_json::json;
use std::error::Error;

pub async fn fetch_tasks(
instance_url: &str,
Expand Down Expand Up @@ -48,17 +49,23 @@ pub async fn create_new_task(
instance_url: &str,
api_key: &str,
task_title: &str,
) -> Result<(), Box<dyn std::error::Error>> {
priority: Option<u8>,
) -> Result<(), Box<dyn Error>> {
let client = Client::new();
let url = format!("{}/api/v1/projects/1/tasks", instance_url);

let mut map = HashMap::new();
map.insert("title", task_title);
let mut task_data = json!({
"title": task_title
});

if let Some(priority_value) = priority {
task_data["priority"] = json!(priority_value);
}

let res = client
.put(&url)
.header("Authorization", format!("Bearer {}", api_key))
.json(&map)
.json(&task_data)
.send()
.await?;

Expand Down
15 changes: 12 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::api::{create_new_task, fetch_task_detail, fetch_tasks};
use crate::models::{Task, TaskDetail};
use crate::parser::parse_task_input;
use crossterm::event::KeyCode;
use ratatui::widgets::ListState;
use std::io;
Expand Down Expand Up @@ -149,10 +150,18 @@ impl App {
InputMode::Editing => {
match key.code {
KeyCode::Enter => {
// Handle task submission
if !self.new_task_title.trim().is_empty() {
if let Err(err) =
create_new_task(instance_url, api_key, &self.new_task_title).await
// Use the parser to extract the task title, priority, and label titles
let parsed_task = parse_task_input(&self.new_task_title);

// Create the new task with the parsed title, priority, and labels
if let Err(err) = create_new_task(
instance_url,
api_key,
&parsed_task.title,
parsed_task.priority,
)
.await
{
eprintln!("Error creating task: {}", err);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod api;
mod app;
mod models;
mod parser;
mod ui;

use crate::api::fetch_tasks;
Expand Down
29 changes: 29 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use regex::Regex;

pub struct ParsedTask {
pub title: String,
pub priority: Option<u8>,
}

pub fn parse_task_input(input: &str) -> ParsedTask {
// Regex for priority pattern, e.g. !1 to !5
let priority_re = Regex::new(r"!(\d)").unwrap();

let mut priority = None;
let mut title = input.to_string();

// Capture priority if it exists
if let Some(caps) = priority_re.captures(input) {
if let Some(priority_match) = caps.get(1) {
if let Ok(p) = priority_match.as_str().parse::<u8>() {
if (1..=5).contains(&p) {
priority = Some(p);
}
}
}
// Remove the priority pattern from the title
title = priority_re.replace(input, "").trim().to_string();
}

ParsedTask { title, priority }
}
10 changes: 2 additions & 8 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,7 @@ pub async fn run_app<B: Backend>(
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(0)
.constraints(
[
Constraint::Min(0), // Body takes up the remaining space
Constraint::Length(2), // Footer is 3 rows high
]
.as_ref(),
)
.constraints([Constraint::Min(0), Constraint::Length(2)].as_ref())
.split(size);

let body_chunk = chunks[0];
Expand All @@ -116,7 +110,7 @@ pub async fn run_app<B: Backend>(
let chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[Constraint::Percentage(50), Constraint::Percentage(50)].as_ref(),
[Constraint::Percentage(65), Constraint::Percentage(35)].as_ref(),
)
.split(body_chunk);

Expand Down

0 comments on commit 1b5c6e6

Please sign in to comment.