forked from Roflin/gamenight
Added some more gamenight-cli Flows.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Abort {
|
||||
|
||||
}
|
||||
|
||||
44
gamenight-cli/src/flows/add_gamenight.rs
Normal file
44
gamenight-cli/src/flows/add_gamenight.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
use gamenight_api_client_rs::{apis::default_api::post_gamenight, models};
|
||||
use inquire::{Text, DateSelect};
|
||||
use chrono::{self, Local, NaiveTime};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AddGamenight {
|
||||
|
||||
}
|
||||
|
||||
impl AddGamenight {
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for AddGamenight {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let mut add_gamenight = models::AddGamenightRequestBody::new();
|
||||
|
||||
add_gamenight.name = Some(Text::new("What should we call your gamenight").prompt()?);
|
||||
add_gamenight.datetime = Some(DateSelect::new("When is your gamenight").prompt()?
|
||||
.and_time(NaiveTime::default())
|
||||
.and_local_timezone(Local)
|
||||
.earliest()
|
||||
.unwrap()
|
||||
.to_utc()
|
||||
.to_rfc3339());
|
||||
|
||||
post_gamenight(&state.configuration, Some(add_gamenight)).await?;
|
||||
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AddGamenight {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Add Gamenight.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
|
||||
use gamenight_api_client_rs::apis::default_api::get_gamenights;
|
||||
use inquire::Select;
|
||||
|
||||
use super::*;
|
||||
use crate::flows::view_gamenight::ViewGamenight;
|
||||
|
||||
use super::{abort::Abort, *};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ListGamenights {
|
||||
|
||||
}
|
||||
@@ -17,8 +21,16 @@ impl ListGamenights {
|
||||
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))
|
||||
|
||||
let mut view_flows = response.into_iter().map(|gamenight| -> Box<dyn Flow<'a> + Send> {
|
||||
Box::new(ViewGamenight::new(gamenight))
|
||||
}).collect::<Vec<Box<dyn Flow<'a> + Send>>>();
|
||||
view_flows.push(Box::new(Abort::new()));
|
||||
|
||||
let choice = Select::new("What gamenight would you like to view?", view_flows)
|
||||
.prompt_skippable()?;
|
||||
|
||||
handle_choice_option(&choice, self, state).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ use inquire::{Password, Text};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Login {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
use super::{abort::Abort, list_gamenights::ListGamenights, login::Login, main_menu::MainMenu, *};
|
||||
|
||||
use super::{abort::Abort, add_gamenight::AddGamenight, list_gamenights::ListGamenights, login::Login, main_menu::MainMenu, *};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Main {
|
||||
login: Box<dyn for<'a> Flow<'a>>,
|
||||
main_menu: MainMenu
|
||||
@@ -11,6 +11,7 @@ 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(AddGamenight::new()));
|
||||
main_menu.menu.push(Box::new(Abort::new()));
|
||||
Self {
|
||||
login: Box::new(Login::new()),
|
||||
|
||||
@@ -3,6 +3,7 @@ use inquire::{ui::RenderConfig, Select};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MainMenu {
|
||||
pub menu: Vec<Box<dyn for<'a> Flow<'a> + Send>>
|
||||
}
|
||||
@@ -22,7 +23,7 @@ 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)
|
||||
let choice = Select::new("What would you like to do?", self.menu.clone())
|
||||
.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,
|
||||
@@ -30,19 +31,7 @@ impl<'a> Flow<'a> for MainMenu {
|
||||
})
|
||||
.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))
|
||||
}
|
||||
handle_choice_option(&choice, self, state).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::ParseError;
|
||||
use gamenight_api_client_rs::apis::configuration::Configuration;
|
||||
use inquire::InquireError;
|
||||
use dyn_clone::DynClone;
|
||||
|
||||
pub mod main;
|
||||
pub mod login;
|
||||
mod login;
|
||||
mod main_menu;
|
||||
mod abort;
|
||||
mod list_gamenights;
|
||||
mod add_gamenight;
|
||||
mod view_gamenight;
|
||||
|
||||
pub struct GamenightState {
|
||||
configuration: Configuration,
|
||||
@@ -43,6 +47,14 @@ impl<T> From<gamenight_api_client_rs::apis::Error<T>> for FlowError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseError> for FlowError {
|
||||
fn from(value: ParseError) -> Self {
|
||||
Self {
|
||||
error: value.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum FlowOutcome {
|
||||
Successful,
|
||||
@@ -53,7 +65,29 @@ pub enum FlowOutcome {
|
||||
|
||||
type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>;
|
||||
|
||||
dyn_clone::clone_trait_object!(for<'a> Flow<'a>);
|
||||
|
||||
#[async_trait]
|
||||
pub trait Flow<'a>: Sync + Display {
|
||||
pub trait Flow<'a>: Sync + Display + DynClone + Send {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a>;
|
||||
}
|
||||
|
||||
async fn handle_choice<'a>(choice: &Box<dyn Flow<'a> + Send>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
let (outcome, new_state) = choice.run(state).await?;
|
||||
|
||||
if outcome == FlowOutcome::Abort {
|
||||
Ok((FlowOutcome::Successful, new_state))
|
||||
}
|
||||
else {
|
||||
flow.run(new_state).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_choice_option<'a>(choice: &Option<Box<dyn Flow<'a> + Send>>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
if let Some(choice) = choice {
|
||||
handle_choice(&choice, flow, state).await
|
||||
}
|
||||
else {
|
||||
Ok((FlowOutcome::Abort, state))
|
||||
}
|
||||
}
|
||||
43
gamenight-cli/src/flows/view_gamenight.rs
Normal file
43
gamenight-cli/src/flows/view_gamenight.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
use chrono::DateTime;
|
||||
use gamenight_api_client_rs::models::Gamenight;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ViewGamenight {
|
||||
gamenight: Gamenight
|
||||
}
|
||||
|
||||
impl ViewGamenight {
|
||||
pub fn new(gamenight: Gamenight) -> Self {
|
||||
Self {
|
||||
gamenight
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gamenight_localtime(&self) -> Result<String, FlowError> {
|
||||
let datetime = DateTime::parse_from_rfc3339(&self.gamenight.datetime)?;
|
||||
let offset = *chrono::offset::Local::now().offset();
|
||||
Ok(format!("{}", datetime.naive_local().checked_add_offset(offset).unwrap().format("%d-%m-%Y %H:%M")))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> Flow<'a> for ViewGamenight {
|
||||
async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a> {
|
||||
println!("Name: {}", self.gamenight.name);
|
||||
println!("When: {}", self.gamenight_localtime()?);
|
||||
|
||||
|
||||
|
||||
Ok((FlowOutcome::Successful, state))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ViewGamenight {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{} {}", self.gamenight.name, self.gamenight.datetime)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user