move components in separate files

This commit is contained in:
rick 2022-10-28 18:57:08 +02:00
parent cd6fcbe3d9
commit 77f94a9fad
Signed by: Rick
GPG key ID: 4A6223D66294EB20
4 changed files with 345 additions and 329 deletions

View file

@ -0,0 +1,151 @@
use gloo_net::http::Request;
use gloo_net::Error;
use gloo_storage::errors::StorageError;
use gloo_storage::{LocalStorage, Storage};
use patternfly_yew::{Toast, ToastDispatcher, ToastViewer, Type};
use yew::prelude::*;
use crate::components::{ListGroups, User};
pub struct Home {
user: Option<User>,
}
#[derive(PartialEq)]
pub enum TestMessage {
Toast(ToastType),
ConnexionOk(User),
}
#[derive(PartialEq)]
pub struct ToastFields {
pub title: String,
pub body: String,
}
#[derive(PartialEq)]
pub enum ToastType {
Info(ToastFields),
Error(ToastFields),
}
impl Component for Home {
type Message = TestMessage;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
user: None,
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let user: Result<User, StorageError> = LocalStorage::get("auth");
if let Ok(user) = user {
if let None = self.user {
ctx.link().send_message(TestMessage::ConnexionOk(user));
}
} else {
ctx.link().send_future_batch(async {
match Request::get("/api/users/current").send().await {
Ok(resp) => {
if resp.ok() {
let json: Result<User, Error> = resp.json().await;
match json {
Ok(json) => {
let user = json.clone();
match LocalStorage::set("auth", json) {
Ok(_) => vec![
TestMessage::Toast(ToastType::Info(ToastFields {
title: String::from("Connexion réussie !"),
body: String::new(),
})),
TestMessage::ConnexionOk(user),
],
Err(err) => vec![TestMessage::Toast(ToastType::Error(
ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
},
))],
}
}
Err(err) => {
LocalStorage::delete("auth");
vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
}))]
}
}
} else {
vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: String::from("L'API ne retourne pas un code 200."),
}))]
}
}
Err(err) => vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
}))],
}
});
}
//let onclick = ctx.link().callback(|_| TestMessage::Test);
html! {
<>
<ToastViewer />
if let Some(user) = &self.user {
<h1>{ format!("Bienvenue {} !", user.discordname) }</h1>
if user.discordid.is_empty() {
<p><a href="/login/discord">{ "SE CONNECTER VIA DISCORD ICI" }</a></p>
}
if user.steamid.is_empty() {
<p><a href="/login/steam">{ "SE CONNECTER VIA STEAM ICI" }</a></p>
}
<div>
<ListGroups id={user.id.clone()} />
</div>
} else {
<p><a href="/login/discord">{ "SE CONNECTER VIA DISCORD ICI" }</a></p>
<p><a href="/login/steam">{ "SE CONNECTER VIA STEAM ICI" }</a></p>
}
//<button {onclick}>{"test"}</button>
</>
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
TestMessage::ConnexionOk(user) => {
self.user = Some(user);
return true;
}
TestMessage::Toast(toast) => match toast {
ToastType::Info(infos) => ToastDispatcher::new().toast(Toast {
title: infos.title,
r#type: Type::Info,
..Default::default()
}),
ToastType::Error(infos) => ToastDispatcher::new().toast(Toast {
title: infos.title,
r#type: Type::Danger,
body: html! { <p>{ infos.body }</p> },
..Default::default()
}),
},
//_ => ToastDispatcher::new().toast(html! {<Alert title="Coucou"></Alert>}),
_ => ToastDispatcher::new().toast(Toast {
title: String::from("Un callback n'a pas été implémenté !"),
r#type: Type::Warning,
..Default::default()
}),
}
false
}
}

View file

@ -0,0 +1,136 @@
use gloo_net::http::Request;
use gloo_net::Error;
use patternfly_yew::ToastViewer;
use yew::prelude::*;
use crate::components::{Group, Home, TestMessage, ToastFields, ToastType};
pub struct ListGroups {
idUser: String,
groups: Vec<Group>,
nb_show: usize,
}
#[derive(PartialEq, Properties)]
pub struct PropGroups {
pub id: String,
}
#[derive(PartialEq)]
pub enum MsgListGroups {
Done(Vec<Group>),
Info(String, String),
Error(String, String),
More,
}
impl Component for ListGroups {
type Message = MsgListGroups;
type Properties = PropGroups;
fn create(ctx: &Context<Self>) -> Self {
Self {
idUser: ctx.props().id.clone(),
groups: Vec::new(),
nb_show: 0,
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
if self.groups.len() == 0 {
let id = self.idUser.clone();
ctx.link().send_future(async move {
match Request::get(&format!("/api/users/{}/groups", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Vec<Group>, Error> = resp.json().await;
match json {
Ok(mut json) => {
for item in json.iter_mut() {
item.get_game_name().await;
}
return MsgListGroups::Done(json);
}
Err(err) => {
log::info!("{}", err.to_string());
()
}
}
}
}
Err(_) => (),
};
MsgListGroups::Info(String::from("Ok"), String::new())
});
}
let onclick = ctx.link().callback(|_| MsgListGroups::More);
html! {
<>
<ToastViewer />
if self.groups.len() > 0 {
{
self.groups[..self.nb_show].iter().map(|group| { html!{
<p>{ group.name.clone() }</p>
} }).collect::<Html>()
}
if self.nb_show < self.groups.len() {
<button onclick={onclick}>{ "Plus de groupes" }</button>
}
} else {
<p>{ "Vous n'êtes dans aucun groupe." }</p>
}
//<p>{ "coucou" }</p>
</>
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MsgListGroups::Info(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Info(ToastFields {
title,
body,
})))
}
}
MsgListGroups::Error(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Error(ToastFields {
title,
body,
})))
}
}
MsgListGroups::Done(groups) => {
let len = groups.len();
self.groups = groups;
self.nb_show = if len < 3 {
len
} else {
3
};
return true;
}
MsgListGroups::More => {
self.nb_show += 3;
if self.nb_show > self.groups.len() {
self.nb_show -= self.nb_show - self.groups.len();
}
return true;
}
}
false
}
}

View file

@ -0,0 +1,54 @@
mod home;
mod list_groups;
pub use home::*;
use list_groups::ListGroups;
use gloo_net::Error;
use gloo_net::http::Request;
use serde::{Deserialize, Serialize};
#[derive(Clone, Deserialize, PartialEq, Serialize)]
pub struct User {
id: String,
banned: bool,
blacklisted: bool,
experience: u32,
level: u32,
money: u32,
moneylimit: u32,
steamid: String,
discordid: String,
discordname: String,
}
#[derive(Deserialize, Serialize)]
struct Game {
name: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Group {
pub name: String,
pub game: String,
}
impl Group {
pub async fn get_game_name(&mut self) {
match Request::get(&format!("/api/games/{}", self.game))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Game, Error> = resp.json().await;
match json {
Ok(json) => self.game = json.name,
Err(err) => log::info!("{}", err.to_string()),
}
}
}
Err(_) => (),
}
}
}

View file

@ -1,26 +1,12 @@
mod components;
use components::*;
use gloo_net::http::Request;
use gloo_net::Error;
use gloo_storage::errors::StorageError;
use gloo_storage::{LocalStorage, Storage};
use patternfly_yew::{Toast, ToastDispatcher, ToastViewer, Type};
use serde::{Deserialize, Serialize};
use yew::prelude::*;
use yew_router::prelude::*;
#[derive(Clone, Deserialize, PartialEq, Serialize)]
struct User {
id: String,
banned: bool,
blacklisted: bool,
experience: u32,
level: u32,
money: u32,
moneylimit: u32,
steamid: String,
discordid: String,
discordname: String,
}
#[derive(Clone, Routable, PartialEq)]
enum Route {
#[at("/")]
@ -45,317 +31,6 @@ fn about() -> Html {
}
}
struct Home {
value: String,
user: Option<User>,
}
#[derive(PartialEq)]
enum TestMessage {
Test,
Toast(ToastType),
ConnexionOk(User),
}
#[derive(PartialEq)]
struct ToastFields {
pub title: String,
pub body: String,
}
#[derive(PartialEq)]
enum ToastType {
Info(ToastFields),
Error(ToastFields),
}
impl Component for Home {
type Message = TestMessage;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
value: String::from("coucou"),
user: None,
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let user: Result<User, StorageError> = LocalStorage::get("auth");
if let Ok(user) = user {
if let None = self.user {
ctx.link().send_message(TestMessage::ConnexionOk(user));
}
} else {
ctx.link().send_future_batch(async {
match Request::get("/api/users/current").send().await {
Ok(resp) => {
if resp.ok() {
let json: Result<User, Error> = resp.json().await;
match json {
Ok(json) => {
let user = json.clone();
match LocalStorage::set("auth", json) {
Ok(_) => vec![
TestMessage::Toast(ToastType::Info(ToastFields {
title: String::from("Connexion réussie !"),
body: String::new(),
})),
TestMessage::ConnexionOk(user),
],
Err(err) => vec![TestMessage::Toast(ToastType::Error(
ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
},
))],
}
}
Err(err) => {
LocalStorage::delete("auth");
vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
}))]
}
}
} else {
vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: String::from("L'API ne retourne pas un code 200."),
}))]
}
}
Err(err) => vec![TestMessage::Toast(ToastType::Error(ToastFields {
title: String::from("Error from the promise"),
body: err.to_string(),
}))],
}
});
}
//let onclick = ctx.link().callback(|_| TestMessage::Test);
html! {
<>
<ToastViewer />
if let Some(user) = &self.user {
<h1>{ format!("Bienvenue {} !", user.discordname) }</h1>
if user.discordid.is_empty() {
<p><a href="/login/discord">{ "SE CONNECTER VIA DISCORD ICI" }</a></p>
}
if user.steamid.is_empty() {
<p><a href="/login/steam">{ "SE CONNECTER VIA STEAM ICI" }</a></p>
}
<div>
<ListGroups id={user.id.clone()} />
</div>
} else {
<p><a href="/login/discord">{ "SE CONNECTER VIA DISCORD ICI" }</a></p>
<p><a href="/login/steam">{ "SE CONNECTER VIA STEAM ICI" }</a></p>
}
//<button {onclick}>{"test"}</button>
</>
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
TestMessage::ConnexionOk(user) => {
self.user = Some(user);
return true;
}
TestMessage::Toast(toast) => match toast {
ToastType::Info(infos) => ToastDispatcher::new().toast(Toast {
title: infos.title,
r#type: Type::Info,
..Default::default()
}),
ToastType::Error(infos) => ToastDispatcher::new().toast(Toast {
title: infos.title,
r#type: Type::Danger,
body: html! { <p>{ infos.body }</p> },
..Default::default()
}),
},
//_ => ToastDispatcher::new().toast(html! {<Alert title="Coucou"></Alert>}),
_ => ToastDispatcher::new().toast(Toast {
title: String::from("Un callback n'a pas été implémenté !"),
r#type: Type::Warning,
..Default::default()
}),
}
false
/*
if msg == TestMessage::Test {
self.value = String::from("nouveau");
true
} else if let TestMessage::StatusConnection(_) = msg {
self.value = String::from("yes ça marche");
true
} else {
false
}
*/
}
}
#[derive(Deserialize, Serialize)]
struct Game {
name: String,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
struct Group {
pub name: String,
pub game: String,
}
impl Group {
pub async fn get_game_name(&mut self) {
match Request::get(&format!("/api/games/{}", self.game))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Game, Error> = resp.json().await;
match json {
Ok(json) => self.game = json.name,
Err(err) => log::info!("{}", err.to_string()),
}
}
}
Err(err) => (),
}
}
}
struct ListGroups {
idUser: String,
groups: Vec<Group>,
nb_show: usize,
}
#[derive(PartialEq, Properties)]
struct PropGroups {
id: String,
}
#[derive(PartialEq)]
enum MsgListGroups {
Done(Vec<Group>),
Info(String, String),
Error(String, String),
More,
}
impl Component for ListGroups {
type Message = MsgListGroups;
type Properties = PropGroups;
fn create(ctx: &Context<Self>) -> Self {
Self {
idUser: ctx.props().id.clone(),
groups: Vec::new(),
nb_show: 0,
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
if self.groups.len() == 0 {
let id = self.idUser.clone();
ctx.link().send_future(async move {
match Request::get(&format!("/api/users/{}/groups", id))
.send()
.await
{
Ok(resp) => {
if resp.ok() {
let json: Result<Vec<Group>, Error> = resp.json().await;
match json {
Ok(mut json) => {
for item in json.iter_mut() {
item.get_game_name().await;
}
return MsgListGroups::Done(json);
}
Err(err) => {
log::info!("{}", err.to_string());
()
}
}
}
}
Err(err) => (),
};
MsgListGroups::Info(String::from("Ok"), String::new())
});
}
let onclick = ctx.link().callback(|_| MsgListGroups::More);
html! {
<>
<ToastViewer />
if self.groups.len() > 0 {
{
self.groups[..self.nb_show].iter().map(|group| { html!{
<p>{ group.name.clone() }</p>
} }).collect::<Html>()
}
if self.nb_show < self.groups.len() {
<button onclick={onclick}>{ "Plus de groupes" }</button>
}
} else {
<p>{ "Vous n'êtes dans aucun groupe." }</p>
}
//<p>{ "coucou" }</p>
</>
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
MsgListGroups::Info(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Info(ToastFields {
title,
body,
})))
}
}
MsgListGroups::Error(title, body) => {
if let Some(parent) = ctx.link().get_parent() {
(parent.clone())
.downcast::<Home>()
.send_message(TestMessage::Toast(ToastType::Error(ToastFields {
title,
body,
})))
}
}
MsgListGroups::Done(groups) => {
self.groups = groups;
return true;
}
MsgListGroups::More => {
self.nb_show += 3;
if self.nb_show > self.groups.len() {
self.nb_show -= self.nb_show - self.groups.len();
}
return true;
}
}
false
}
}
fn switch(route: &Route) -> Html {
match route {
Route::Home => html! { <Home /> },