forked from Roflin/gamenight
Started working on a cli frontend.
This commit is contained in:
1
gamenight-cli/.gitignore
vendored
Normal file
1
gamenight-cli/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
target
|
||||
1933
gamenight-cli/Cargo.lock
generated
Normal file
1933
gamenight-cli/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
gamenight-cli/Cargo.toml
Normal file
10
gamenight-cli/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "gamenight-cli"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
gamenight-api-client-rs = { path = "../gamenight-api-client-rs" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
inquire = "0.7.5"
|
||||
async-trait = "0.1"
|
||||
24
gamenight-cli/src/flows/abort.rs
Normal file
24
gamenight-cli/src/flows/abort.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use super::*;
|
||||
|
||||
pub struct Abort {
|
||||
|
||||
}
|
||||
|
||||
impl Abort {
|
||||
pub fn new() -> Self {
|
||||
Self{}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Abort {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
Ok((FlowOutcome::Abort, state))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Abort {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Abort")
|
||||
}
|
||||
}
|
||||
30
gamenight-cli/src/flows/list_gamenights.rs
Normal file
30
gamenight-cli/src/flows/list_gamenights.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
use gamenight_api_client_rs::apis::default_api::get_gamenights;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct ListGamenights {
|
||||
|
||||
}
|
||||
|
||||
impl ListGamenights {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for ListGamenights {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let response = get_gamenights(&state.configuration).await?;
|
||||
println!("{:?}", response);
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ListGamenights {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "List all gamenights")
|
||||
}
|
||||
}
|
||||
|
||||
43
gamenight-cli/src/flows/login.rs
Normal file
43
gamenight-cli/src/flows/login.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::{apis::{configuration::Configuration, default_api::get_token}, models};
|
||||
use inquire::{Password, Text};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct Login {
|
||||
|
||||
}
|
||||
|
||||
impl Login {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Login {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let configuration = Configuration::new();
|
||||
|
||||
let username = Text::new("What is your login?").prompt()?;
|
||||
let password = Password::new("what is your password?")
|
||||
.without_confirmation()
|
||||
.prompt()?;
|
||||
|
||||
let login = models::Login::new(username, password);
|
||||
|
||||
let result = get_token(&configuration, Some(login)).await?;
|
||||
if let Some(token) = result.jwt_token {
|
||||
state.configuration.bearer_access_token = Some(token);
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
} else {
|
||||
Err(FlowError{error: "Unexpected response".to_string()})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Login {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Login")
|
||||
}
|
||||
}
|
||||
35
gamenight-cli/src/flows/main.rs
Normal file
35
gamenight-cli/src/flows/main.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
use super::{abort::Abort, list_gamenights::ListGamenights, login::Login, main_menu::MainMenu, *};
|
||||
|
||||
|
||||
pub struct Main {
|
||||
login: Box<dyn for<'a> Flow<'a>>,
|
||||
main_menu: MainMenu
|
||||
}
|
||||
|
||||
impl Main {
|
||||
pub fn new() -> Self {
|
||||
let mut main_menu = MainMenu::new();
|
||||
main_menu.menu.push(Box::new(ListGamenights::new()));
|
||||
main_menu.menu.push(Box::new(Abort::new()));
|
||||
Self {
|
||||
login: Box::new(Login::new()),
|
||||
main_menu: main_menu
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for Main {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let (_outcome, state) = self.login.run(state).await?;
|
||||
let (_outcome, state) = self.main_menu.run(state).await?;
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Main {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "main")
|
||||
}
|
||||
}
|
||||
53
gamenight-cli/src/flows/main_menu.rs
Normal file
53
gamenight-cli/src/flows/main_menu.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
use inquire::{ui::RenderConfig, Select};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct MainMenu {
|
||||
pub menu: Vec<Box<dyn for<'a> Flow<'a> + Send>>
|
||||
}
|
||||
|
||||
impl MainMenu {
|
||||
pub fn new() -> Self {
|
||||
MainMenu {
|
||||
menu: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for MainMenu {
|
||||
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for MainMenu {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let choice = Select::new("What would you like to do?", self.menu)
|
||||
.with_help_message("Select the action you want to take or quit the program")
|
||||
.with_render_config(RenderConfig {
|
||||
option_index_prefix: inquire::ui::IndexPrefix::Simple,
|
||||
..Default::default()
|
||||
})
|
||||
.prompt_skippable()?;
|
||||
|
||||
if let Some(choice) = choice {
|
||||
let (outcome, new_state) = choice.run(state).await?;
|
||||
|
||||
if outcome == FlowOutcome::Abort {
|
||||
Ok((outcome, new_state))
|
||||
}
|
||||
else {
|
||||
self.run(new_state).await
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Ok((FlowOutcome::Abort, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MainMenu {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Main menu")
|
||||
}
|
||||
}
|
||||
59
gamenight-cli/src/flows/mod.rs
Normal file
59
gamenight-cli/src/flows/mod.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use gamenight_api_client_rs::apis::configuration::Configuration;
|
||||
use inquire::InquireError;
|
||||
|
||||
pub mod main;
|
||||
pub mod login;
|
||||
mod main_menu;
|
||||
mod abort;
|
||||
mod list_gamenights;
|
||||
|
||||
pub struct GamenightState {
|
||||
configuration: Configuration,
|
||||
}
|
||||
|
||||
impl GamenightState {
|
||||
pub fn new() -> Self{
|
||||
Self {
|
||||
configuration: Configuration::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FlowError {
|
||||
pub error: String
|
||||
}
|
||||
|
||||
impl From<InquireError> for FlowError {
|
||||
fn from(value: InquireError) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<gamenight_api_client_rs::apis::Error<T>> for FlowError {
|
||||
fn from(value: gamenight_api_client_rs::apis::Error<T>) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum FlowOutcome {
|
||||
Successful,
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Abort
|
||||
}
|
||||
|
||||
type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Flow<'a>: Sync + Display {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a>;
|
||||
}
|
||||
14
gamenight-cli/src/main.rs
Normal file
14
gamenight-cli/src/main.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
pub mod flows;
|
||||
|
||||
use flows::{main::Main, Flow, GamenightState};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let mut state = GamenightState::new();
|
||||
let mainflow = Main::new();
|
||||
if let Err(x) = mainflow.run(&mut state).await {
|
||||
println!("{}", x.error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user