This commit is contained in:
JMARyA 2024-06-06 11:32:39 +02:00
parent a11fe29048
commit 09f6dd0625
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 53 additions and 70 deletions

View file

@ -1,5 +1,3 @@
use std::collections::HashSet;
use serde::{Deserialize, Serialize};
mod project;
@ -47,24 +45,11 @@ where
ret
}
fn unique_tasks(tasks: Vec<Task>) -> Vec<Task> {
let mut seen_ids = HashSet::new();
let mut unique_tasks = Vec::with_capacity(tasks.len());
for task in tasks {
if seen_ids.insert(task.id) {
unique_tasks.push(task);
}
}
unique_tasks
}
pub struct ProjectID(pub isize);
impl ProjectID {
pub fn parse(api: &VikunjaAPI, project: &str) -> Option<Self> {
let project = project.trim_start_matches("#");
let project = project.trim_start_matches('#');
if let Ok(num) = project.parse() {
Some(Self(num))
@ -95,29 +80,30 @@ impl VikunjaAPI {
}
fn get_request(&self, path: &str) -> String {
if let Some(cached) = self.cache.get(path) {
cached
} else {
let client = reqwest::blocking::Client::new();
self.cache.get(path).map_or_else(
|| {
let client = reqwest::blocking::Client::new();
let ret = client
.get(&format!("{}/api/v1{}", self.host, path))
.header("Authorization", format!("Bearer {}", self.token))
.send()
.unwrap()
.text()
.unwrap();
let ret = client
.get(format!("{}/api/v1{}", self.host, path))
.header("Authorization", format!("Bearer {}", self.token))
.send()
.unwrap()
.text()
.unwrap();
self.cache.insert(path.to_string(), ret.clone());
ret
}
self.cache.insert(path.to_string(), ret.clone());
ret
},
|cached| cached,
)
}
fn put_request(&self, path: &str, data: serde_json::Value) -> String {
fn put_request(&self, path: &str, data: &serde_json::Value) -> String {
let client = reqwest::blocking::Client::new();
client
.put(&format!("{}/api/v1{}", self.host, path))
.put(format!("{}/api/v1{}", self.host, path))
.header("Authorization", format!("Bearer {}", self.token))
.json(&data)
.send()
@ -126,11 +112,11 @@ impl VikunjaAPI {
.unwrap()
}
fn post_request(&self, path: &str, data: serde_json::Value) -> String {
fn post_request(&self, path: &str, data: &serde_json::Value) -> String {
let client = reqwest::blocking::Client::new();
client
.post(&format!("{}/api/v1{}", self.host, path))
.post(format!("{}/api/v1{}", self.host, path))
.header("Authorization", format!("Bearer {}", self.token))
.json(&data)
.send()
@ -180,7 +166,7 @@ impl VikunjaAPI {
serde_json::from_str(&resp).unwrap()
}
pub fn new_task(&self, title: &str, project: ProjectID) -> Task {
pub fn new_task(&self, title: &str, project: &ProjectID) -> Task {
let id = project.0;
let data = serde_json::json!({
@ -194,14 +180,14 @@ impl VikunjaAPI {
// labels
// priority
let resp = self.put_request(&format!("/projects/{id}/tasks"), data);
let resp = self.put_request(&format!("/projects/{id}/tasks"), &data);
serde_json::from_str(&resp).unwrap()
}
pub fn done_task(&self, task_id: isize) -> Task {
let resp = self.post_request(
&format!("/tasks/{task_id}"),
serde_json::json!({
&serde_json::json!({
"done": true
}),
);

View file

@ -18,6 +18,8 @@ pub fn get_args() -> clap::ArgMatches {
.name("prj")
.about("Commands about projects")
.subcommand(command!().name("ls").about("List projects")),
// todo : prj add <project>
// todo : prj rm <project>
)
.subcommand(
command!()
@ -35,6 +37,9 @@ pub fn get_args() -> clap::ArgMatches {
.name("label")
.about("Manage labels")
.subcommand(command!().name("ls").about("List all labels")),
// todo : label new
// todo : label rm
// todo : label <label> <task>
)
.subcommand(
command!()

View file

@ -20,6 +20,7 @@ fn main() {
Some(("ls", _)) => {
ui::project::list_projects(&api);
}
Some(("add", add_prj_arg)) => {}
_ => {
ui::project::list_projects(&api);
}
@ -28,15 +29,16 @@ fn main() {
Some(("ls", _)) => {
ui::print_all_labels(&api);
}
Some(("new", new_label_arg)) => {}
_ => {
ui::print_all_labels(&api);
// todo : label tasks
}
},
Some(("new", new_task_arg)) => {
let title: &String = new_task_arg.get_one("title").unwrap();
let project: &String = new_task_arg.get_one("project").unwrap();
let project = ProjectID::parse(&api, project).unwrap();
let task = api.new_task(title.as_str(), project);
let task = api.new_task(title.as_str(), &project);
ui::task::print_task_info(task.id, &api);
}
Some(("done", done_args)) => {

View file

@ -46,10 +46,7 @@ fn parse_datetime(datetime_str: &str) -> Option<DateTime<Utc>> {
return None;
}
match DateTime::parse_from_rfc3339(datetime_str) {
Ok(dt) => Some(dt.with_timezone(&Utc)),
Err(_) => None, // Return None if parsing fails
}
DateTime::parse_from_rfc3339(datetime_str).map_or(None, |dt| Some(dt.with_timezone(&Utc)))
}
/// Return a formatted time duration
@ -58,19 +55,19 @@ pub fn time_since(event: DateTime<Utc>) -> String {
let duration = now.signed_duration_since(event);
if duration.num_days() > 0 {
return format!("{}d ago", duration.num_days());
format!("{}d ago", duration.num_days())
} else if duration.num_hours() > 0 {
return format!("{}h ago", duration.num_hours());
format!("{}h ago", duration.num_hours())
} else if duration.num_minutes() > 0 {
return format!("{}m ago", duration.num_minutes());
format!("{}m ago", duration.num_minutes())
} else {
return "Just now".to_string();
"Just now".to_string()
}
}
fn print_label(label: &Label) {
let color = hex_to_color(&label.hex_color).unwrap();
print_color_bg(color, &label.title.trim());
print_color_bg(color, label.title.trim());
}
pub fn print_all_labels(api: &VikunjaAPI) {

View file

@ -15,7 +15,7 @@ pub fn list_projects(api: &VikunjaAPI) {
for prj in projects {
project_map
.entry(prj.parent_project_id)
.or_insert_with(Vec::new)
.or_default()
.push(prj);
}
@ -26,7 +26,7 @@ pub fn list_projects(api: &VikunjaAPI) {
hex_to_color(&prj.hex_color).unwrap()
};
print_color(color, &prj.title);
print!(" [{}]\n", prj.id);
println!(" [{}]", prj.id);
if let Some(sub_projects) = project_map.get(&(prj.id as usize)) {
for sub_prj in sub_projects {
@ -36,7 +36,7 @@ pub fn list_projects(api: &VikunjaAPI) {
hex_to_color(&sub_prj.hex_color).unwrap()
};
print_color(color, &format!(" - {}", sub_prj.title));
print!(" [{}]\n", sub_prj.id);
println!(" [{}]", sub_prj.id);
}
}
}

View file

@ -1,6 +1,6 @@
use crate::{
api::{Label, ProjectID, Task, VikunjaAPI},
ui::{hex_to_color, parse_datetime, print_color, print_color_bg, print_label, time_since},
api::{ProjectID, Task, VikunjaAPI},
ui::{parse_datetime, print_color, print_label, time_since},
};
fn print_task_oneline(task: &Task, api: &VikunjaAPI) {
@ -30,7 +30,7 @@ fn print_task_oneline(task: &Task, api: &VikunjaAPI) {
}
}
print!("\n");
println!();
}
pub fn print_current_tasks(
@ -57,27 +57,20 @@ pub fn print_current_tasks(
if let Some(project) = project {
let p_id = ProjectID::parse(api, project).unwrap();
selection = selection
.into_iter()
.filter(|x| x.project_id == p_id.0)
.collect();
selection.retain(|x| x.project_id == p_id.0);
}
if let Some(label_match) = label {
selection = selection
.into_iter()
.filter(|x| {
if let Some(labels) = &x.labels {
for label in labels {
if label.title.trim() == *label_match {
return true;
}
selection.retain(|x| {
if let Some(labels) = &x.labels {
for label in labels {
if label.title.trim() == *label_match {
return true;
}
}
false
})
.collect();
}
false
});
}
for task in selection {