finalize
This commit is contained in:
parent
91b86000ef
commit
dc35f04f2e
6 changed files with 166 additions and 13 deletions
49
Cargo.lock
generated
49
Cargo.lock
generated
|
@ -262,6 +262,27 @@ dependencies = [
|
||||||
"winapi",
|
"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]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.34"
|
version = "0.8.34"
|
||||||
|
@ -593,6 +614,16 @@ version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
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]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -763,6 +794,12 @@ dependencies = [
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
|
@ -881,6 +918,17 @@ dependencies = [
|
||||||
"bitflags 2.5.0",
|
"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]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
@ -1413,6 +1461,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
"dirs",
|
||||||
"moka",
|
"moka",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -8,6 +8,7 @@ authors = ["JMARyA <jmarya@hydrar.de>"]
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
clap = { version = "4.5.4", features = ["cargo"] }
|
clap = { version = "4.5.4", features = ["cargo"] }
|
||||||
crossterm = "0.27.0"
|
crossterm = "0.27.0"
|
||||||
|
dirs = "5.0.1"
|
||||||
moka = { version = "0.12.7", features = ["sync"] }
|
moka = { version = "0.12.7", features = ["sync"] }
|
||||||
reqwest = { version = "0.12.4", features = ["blocking", "json"] }
|
reqwest = { version = "0.12.4", features = ["blocking", "json"] }
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
serde = { version = "1.0.203", features = ["derive"] }
|
||||||
|
|
80
README.md
80
README.md
|
@ -1,2 +1,80 @@
|
||||||
# vk
|
# 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
|
||||||
|
```
|
||||||
|
|
|
@ -270,6 +270,7 @@ impl VikunjaAPI {
|
||||||
"title": title
|
"title": title
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// todo :
|
||||||
// description
|
// description
|
||||||
// due_date
|
// due_date
|
||||||
// end_date
|
// end_date
|
||||||
|
|
|
@ -57,13 +57,14 @@ pub fn get_args() -> clap::ArgMatches {
|
||||||
.about("Get a JWT Token for authentication")
|
.about("Get a JWT Token for authentication")
|
||||||
.arg(arg!(-u --username <username> "Username").required(true))
|
.arg(arg!(-u --username <username> "Username").required(true))
|
||||||
.arg(arg!(-p --password <password> "Password").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)),
|
.arg(arg!(--totp <totp> "TOTP Code").required(false)),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
command!()
|
command!()
|
||||||
.name("assign")
|
.name("assign")
|
||||||
.about("Assign a user to a task")
|
.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!([user] "User").required(true))
|
||||||
.arg(arg!([task_id] "Task ID").required(true)),
|
.arg(arg!([task_id] "Task ID").required(true)),
|
||||||
)
|
)
|
||||||
|
|
45
src/main.rs
45
src/main.rs
|
@ -6,24 +6,47 @@ mod ui;
|
||||||
use api::{ProjectID, VikunjaAPI};
|
use api::{ProjectID, VikunjaAPI};
|
||||||
|
|
||||||
fn main() {
|
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 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() {
|
match arg.subcommand() {
|
||||||
Some(("info", task_info_arg)) => {
|
Some(("info", task_info_arg)) => {
|
||||||
let task_id: &String = task_info_arg.get_one("task_id").unwrap();
|
let task_id: &String = task_info_arg.get_one("task_id").unwrap();
|
||||||
ui::task::print_task_info(task_id.parse().unwrap(), &api);
|
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(("prj", prj_arg)) => match prj_arg.subcommand() {
|
||||||
Some(("ls", _)) => {
|
Some(("ls", _)) => {
|
||||||
ui::project::list_projects(&api);
|
ui::project::list_projects(&api);
|
||||||
|
|
Loading…
Reference in a new issue