This commit is contained in:
JMARyA 2024-06-06 16:37:29 +02:00
parent 91b86000ef
commit dc35f04f2e
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 166 additions and 13 deletions

49
Cargo.lock generated
View file

@ -262,6 +262,27 @@ dependencies = [
"winapi",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]]
name = "encoding_rs"
version = "0.8.34"
@ -593,6 +614,16 @@ version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"libc",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
@ -763,6 +794,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -881,6 +918,17 @@ dependencies = [
"bitflags 2.5.0",
]
[[package]]
name = "redox_users"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "reqwest"
version = "0.12.4"
@ -1413,6 +1461,7 @@ dependencies = [
"chrono",
"clap",
"crossterm",
"dirs",
"moka",
"reqwest",
"serde",

View file

@ -8,6 +8,7 @@ authors = ["JMARyA <jmarya@hydrar.de>"]
chrono = "0.4.38"
clap = { version = "4.5.4", features = ["cargo"] }
crossterm = "0.27.0"
dirs = "5.0.1"
moka = { version = "0.12.7", features = ["sync"] }
reqwest = { version = "0.12.4", features = ["blocking", "json"] }
serde = { version = "1.0.203", features = ["derive"] }

View file

@ -1,2 +1,80 @@
# vk
`vk` is a command line todo tool for Vikunja.
`vk` is a command line todo tool for Vikunja.
## Setup
vk saves it's configuration at `$HOME/.config/vk.toml`.
To log in to your Vikunja Instance you can either use a API Token which you have to create manually or sign in using:
```shell
vk login --username user --password somepass --totp code --host vikunja.example.com
```
## Usage
**Show your current todos:**
```shell
# Just this
vk
# See done tasks as well
vk -d
vk --done
# Show favorites only
vk -f
vk --favorite
# Show tasks from specific project
vk --from myproject
# Show tasks which have a label
vk -l label
vk --label label
```
**Working with tasks:**
```shell
# Create a task
vk new mytask
# Task Detail View
vk info 42 # Tasks are referenced by their ID
# Remove a task
vk rm 42
# Mark as done
vk done 42
# Assign a user to a task
vk assign me 42
vk assign -u me 42 # You can undo this
```
**Working with projects:**
```shell
# List your projects
vk prj ls
# Create a new project
vk prj add MyPrj --description "My project"
# Remove a project
vk prj rm MyPrj
```
**Working with labels:**
```shell
# Assign a label to a task
vk label mylabel 42
vk label -u mylabel 42 # Undo as well
# List your labels
vk labels ls
# Create a new label
vk labels new mylabel
# Remove a label
vk labels rm mylabel
```

View file

@ -270,6 +270,7 @@ impl VikunjaAPI {
"title": title
});
// todo :
// description
// due_date
// end_date

View file

@ -57,13 +57,14 @@ pub fn get_args() -> clap::ArgMatches {
.about("Get a JWT Token for authentication")
.arg(arg!(-u --username <username> "Username").required(true))
.arg(arg!(-p --password <password> "Password").required(true))
.arg(arg!(--host <host> "Vikunja Host").required(true))
.arg(arg!(--totp <totp> "TOTP Code").required(false)),
)
.subcommand(
command!()
.name("assign")
.about("Assign a user to a task")
.arg(arg!(-u --undo "Remove label from task").required(false))
.arg(arg!(-u --undo "Remove user from task").required(false))
.arg(arg!([user] "User").required(true))
.arg(arg!([task_id] "Task ID").required(true)),
)

View file

@ -6,24 +6,47 @@ mod ui;
use api::{ProjectID, VikunjaAPI};
fn main() {
let config: config::Config =
toml::from_str(&std::fs::read_to_string("config.toml").unwrap()).unwrap();
let api = VikunjaAPI::new(&config.host, &config.token);
let arg = args::get_args();
let config_path = dirs::home_dir().unwrap().join(".config").join("vk.toml");
if let Some(("login", login_arg)) = arg.subcommand() {
let username: &String = login_arg.get_one("username").unwrap();
let password: &String = login_arg.get_one("password").unwrap();
let totp: Option<&String> = login_arg.get_one("totp");
let host: &String = login_arg.get_one("host").unwrap();
let host = if host.starts_with("http") {
host.to_string()
} else {
format!("https://{host}")
};
let api = VikunjaAPI::new(&host, "");
let token = api.login(username, password, totp.map(|x| x.as_str()));
let config = format!("host = \"{host}\"\ntoken = \"{token}\"");
std::fs::write(config_path, config).unwrap();
std::process::exit(0);
}
let content = &std::fs::read_to_string(config_path).unwrap_or_else(|e| {
ui::print_color(
crossterm::style::Color::Red,
&format!("Could not read config file: {e}"),
);
println!("\nTo setup vk run `vk login --help`");
std::process::exit(1);
});
let config: config::Config = toml::from_str(content).unwrap();
let api = VikunjaAPI::new(&config.host, &config.token);
match arg.subcommand() {
Some(("info", task_info_arg)) => {
let task_id: &String = task_info_arg.get_one("task_id").unwrap();
ui::task::print_task_info(task_id.parse().unwrap(), &api);
}
Some(("login", login_arg)) => {
let username: &String = login_arg.get_one("username").unwrap();
let password: &String = login_arg.get_one("password").unwrap();
let totp: Option<&String> = login_arg.get_one("totp");
let token = api.login(username, password, totp.map(|x| x.as_str()));
println!("\"token\" = \"{token}\"");
}
Some(("prj", prj_arg)) => match prj_arg.subcommand() {
Some(("ls", _)) => {
ui::project::list_projects(&api);