From edf236ef8c4fe1faaf71473596435dd89a1716e1 Mon Sep 17 00:00:00 2001 From: Artus Date: Sun, 20 Oct 2019 16:09:16 +0200 Subject: [PATCH] routing the rest of implemented features, hits response problem --- lootalot_db/src/models/player/mod.rs | 19 +++++++++++++++---- lootalot_db/src/models/player/notification.rs | 13 +++++++++++-- lootalot_front/src/App.vue | 5 ++++- src/api.rs | 13 ++++++++++++- src/server.rs | 19 ++++++++++++++++++- 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/lootalot_db/src/models/player/mod.rs b/lootalot_db/src/models/player/mod.rs index 6f3cdda..820dbcd 100644 --- a/lootalot_db/src/models/player/mod.rs +++ b/lootalot_db/src/models/player/mod.rs @@ -49,13 +49,20 @@ impl<'q> Players<'q> { } /// Notify all players of an event - pub fn notifiy_all>(&self, text: S) -> QueryResult<()> { - Err(diesel::result::Error::NotFound) + pub fn notifiy_all(&self, text: &str) -> QueryResult<()> { + for id in self.all()? + .into_iter() + .map(|p| p.id) + { + self.notify(id, text); + } + Ok(()) } /// Notify a single player of an event - pub fn notify>(&self, id: i32, text: S) -> QueryResult<()> { - Err(diesel::result::Error::NotFound) + pub fn notify(&self, id: i32, text: &str) -> QueryResult<()> { + let _ = notification::Notification::add(self.0, id, text)?; + Ok(()) } } @@ -63,6 +70,10 @@ impl<'q> Players<'q> { pub struct AsPlayer<'q>(pub &'q DbConnection, pub i32); impl<'q> AsPlayer<'q> { + /// Fetch notifications for this player + pub fn notifications(&self) -> QueryResult> { + notification::pop_all_for(self.1, self.0) + } /// Updates this player's wealth, returning the difference pub fn update_wealth(&self, value_in_gp: f64) -> QueryResult { use crate::schema::players::dsl::*; diff --git a/lootalot_db/src/models/player/notification.rs b/lootalot_db/src/models/player/notification.rs index 1b85a7c..5064a38 100644 --- a/lootalot_db/src/models/player/notification.rs +++ b/lootalot_db/src/models/player/notification.rs @@ -5,16 +5,25 @@ use crate::{ models::player::Player, }; + +/// Pops all notification for a player, deleting the database entities +pub(super) fn pop_all_for(id: i32, conn: &DbConnection) -> QueryResult> { + let select = notifications::table.filter(notifications::dsl::player_id.eq(id)); + let popped = select.load(conn)?; + diesel::delete(select).execute(conn)?; + Ok(popped.into_iter().map(|n: Notification| n.text).collect()) +} + #[derive(Identifiable, Queryable, Associations, Serialize, Debug)] #[belongs_to(Player)] -struct Notification { +pub(super) struct Notification { pub id: i32, pub player_id: i32, pub text: String, } impl Notification { - fn add<'a, S: Into<&'a str>>(conn: &DbConnection, id: i32, text: S) -> QueryResult { + pub(super) fn add<'a, S: Into<&'a str>>(conn: &DbConnection, id: i32, text: S) -> QueryResult { diesel::insert_into(notifications::table) .values(&NewNotification { player_id: id, diff --git a/lootalot_front/src/App.vue b/lootalot_front/src/App.vue index 35dfeb6..1a2c897 100644 --- a/lootalot_front/src/App.vue +++ b/lootalot_front/src/App.vue @@ -161,7 +161,10 @@ export default { this.activeView = viewId; }, addNewLoot () { - api.fetch("admin/add-loot", "POST", this.pending_loot) + api.fetch("players/0/loot", "POST", { + source_name: "Dummy name", + items: this.pending_loot, + }) .then(() => { this.pending_loot = [] this.switchView('group'); diff --git a/src/api.rs b/src/api.rs index 992787f..3a1bf93 100644 --- a/src/api.rs +++ b/src/api.rs @@ -19,6 +19,7 @@ pub enum Value { ItemList(Vec), ClaimList(Vec), PlayerList(Vec), + Notifications(Vec), } impl serde::Serialize for Value { @@ -30,6 +31,7 @@ impl serde::Serialize for Value { Value::ItemList(v) => v.serialize(serializer), Value::ClaimList(v) => v.serialize(serializer), Value::PlayerList(v) => v.serialize(serializer), + Value::Notifications(v) => v.serialize(serializer), } } } @@ -85,6 +87,7 @@ pub enum ApiActions { FetchClaims, // Player actions FetchPlayer(i32), + FetchNotifications(i32), FetchLoot(i32), UpdateWealth(i32, f64), BuyItems(i32, Vec<(i32, Option)>), @@ -120,6 +123,9 @@ pub fn execute( ApiActions::FetchPlayer(id) => { response.set_value(Value::Player(db::Players(conn).find(id)?)); } + ApiActions::FetchNotifications(id) => { + response.set_value(Value::Notifications(db::AsPlayer(conn, id).notifications()?)); + } ApiActions::FetchLoot(id) => { response.set_value(Value::ItemList(db::LootManager(conn, id).all()?)); } @@ -190,7 +196,12 @@ pub fn execute( } } response.notify(format!("{} objets lootés !", added_items)); - // TODO: notify players throught persistent notifications + // Notify players through persistent notifications + if let Err(e) = db::Players(conn) + .notifiy_all("De nouveaux objets ont été ajoutés au coffre de groupe !") + { + response.push_error(format!("Erreur durant la notification : {:?}", e)); + }; } } Ok(response) diff --git a/src/server.rs b/src/server.rs index b08074e..5659e67 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,7 +1,7 @@ use actix_cors::Cors; use actix_files as fs; use actix_web::{web, middleware, App, Error, HttpResponse, HttpServer}; -use futures::Future; +use futures::{Future, IntoFuture}; use std::env; use lootalot_db as db; @@ -12,6 +12,12 @@ type PlayerId = web::Path; type ItemId = web::Json; type ItemListWithMods = web::Json)>>; +#[derive(Serialize, Deserialize, Debug)] +struct NewGroupLoot { + source_name: String, + items: Vec, +} + /// Wraps call to the database query and convert its result as a async HttpResponse pub fn db_call( pool: AppPool, @@ -44,6 +50,9 @@ fn configure_app(config: &mut web::ServiceConfig) { .route("/", web::get().to_async(|pool, player: PlayerId| { db_call(pool, Q::FetchPlayer(*player)) })) + .route("/notifications", web::get().to_async(|pool, player: PlayerId| { + db_call(pool, Q::FetchNotifications(*player)) + })) .service( web::resource("/claims") //.route(web::get().to_async(endpoints::player_claims)) @@ -83,6 +92,14 @@ fn configure_app(config: &mut web::ServiceConfig) { db_call(pool, Q::BuyItems(*player, data.into_inner())) }, )) + .route(web::post().to_async( + move |pool, (player, data): (PlayerId, web::Json)| { + match *player { + 0 => db_call(pool, Q::AddLoot(data.items.clone())), + _ => HttpResponse::Forbidden().finish().into_future(), + } + }, + )) .route(web::delete().to_async( move |pool, (player, data): (PlayerId, ItemListWithMods)| { db_call(pool, Q::SellItems(*player, data.into_inner()))