refactor
This commit is contained in:
parent
a11fe29048
commit
09f6dd0625
6 changed files with 53 additions and 70 deletions
|
@ -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
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -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!()
|
||||
|
|
|
@ -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)) => {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue