diff --git a/Cargo.lock b/Cargo.lock index 1d74698e..88e2b181 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1737,38 +1737,21 @@ version = "0.1.0" dependencies = [ "actix", "amazon-actor", - "async-trait", - "bigdecimal", - "bincode", - "bitflags", - "byteorder", - "chrono", "common", "database-actor", "dotenv", - "env_logger", "filesystem-actor", "futures", "highlight-actor", - "ipnetwork 0.16.0", "jirs-config", "jirs-data", "libc", - "log", "mail-actor", - "num-bigint", - "num-integer", - "num-traits", "openssl-sys", - "percent-encoding", - "pretty_env_logger", "serde", "serde_json", - "time 0.1.43", "tokio 0.2.25", "toml", - "url", - "uuid 0.8.2", "web-actor", "websocket-actor", ] @@ -3968,6 +3951,7 @@ name = "websocket-actor" version = "0.1.0" dependencies = [ "actix", + "async-trait", "bincode", "common", "comrak", diff --git a/actors/websocket-actor/Cargo.toml b/actors/websocket-actor/Cargo.toml index 9a66909b..ba409ace 100644 --- a/actors/websocket-actor/Cargo.toml +++ b/actors/websocket-actor/Cargo.toml @@ -30,6 +30,8 @@ lazy_static = { version = "*" } uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } +async-trait = { version = "*" } + [dependencies.comrak] version = "*" diff --git a/actors/websocket-actor/src/handlers/auth.rs b/actors/websocket-actor/src/handlers/auth.rs index b368e54c..b37ef96b 100644 --- a/actors/websocket-actor/src/handlers/auth.rs +++ b/actors/websocket-actor/src/handlers/auth.rs @@ -15,24 +15,25 @@ pub struct Authenticate { pub email: String, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: Authenticate, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: Authenticate) -> WsResult { let Authenticate { name, email } = msg; // TODO check attempt number, allow only 5 times per day let user = db_or_debug_and_return!( self, LookupUser { name, email }, Ok(Some(WsMsg::Error(WsError::InvalidLoginPair))), - Ok(Some(WsMsg::Error(WsError::InvalidLoginPair))) + Ok(Some(WsMsg::Error(WsError::InvalidLoginPair))); async ); - let token = db_or_debug_and_return!(self, CreateBindToken { user_id: user.id }); + + let token = db_or_debug_and_return!(self, CreateBindToken { user_id: user.id }; async); if let Some(bind_token) = token.bind_token.as_ref().cloned() { let _ = mail_or_debug_and_return!( self, - Welcome { - bind_token, + Welcome {bind_token, email: user.email, - } + }; async ); } Ok(Some(WsMsg::AuthenticateSuccess)) @@ -76,15 +77,16 @@ pub struct CheckBindToken { pub bind_token: uuid::Uuid, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: CheckBindToken, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: CheckBindToken) -> WsResult { let token: Token = db_or_debug_and_return!( self, FindBindToken { token: msg.bind_token, }, Ok(Some(WsMsg::BindTokenBad)), - Ok(None) + Ok(None); async ); Ok(Some(WsMsg::BindTokenOk(token.access_token))) } diff --git a/actors/websocket-actor/src/handlers/comments.rs b/actors/websocket-actor/src/handlers/comments.rs index 5d05d87f..d178a28d 100644 --- a/actors/websocket-actor/src/handlers/comments.rs +++ b/actors/websocket-actor/src/handlers/comments.rs @@ -1,29 +1,53 @@ -use futures::executor::block_on; +use jirs_data::msg::WsMsgComment; use jirs_data::{CommentId, CreateCommentPayload, IssueId, UpdateCommentPayload, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; + +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgComment) -> WsResult { + match msg { + WsMsgComment::IssueCommentsLoad(issue_id) => { + self.exec(LoadIssueComments { issue_id }).await + } + WsMsgComment::CommentCreate(payload) => self.exec(payload).await, + WsMsgComment::CommentUpdate(payload) => self.exec(payload).await, + WsMsgComment::CommentDelete(comment_id) => { + self.exec(DeleteComment { comment_id }).await + } + WsMsgComment::IssueCommentsLoaded(_) => Ok(None), + WsMsgComment::CommentCreated(_) => Ok(None), + WsMsgComment::CommentUpdated(_) => Ok(None), + WsMsgComment::CommentDeleted(_, _) => Ok(None), + } + } +} pub struct LoadIssueComments { pub issue_id: IssueId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: LoadIssueComments, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: LoadIssueComments) -> WsResult { self.require_user()?; let comments = db_or_debug_and_return!( self, database_actor::comments::LoadIssueComments { issue_id: msg.issue_id, - } + }; async ); - Ok(Some(WsMsg::IssueCommentsLoaded(comments))) + Ok(Some(WsMsg::Comment(WsMsgComment::IssueCommentsLoaded( + comments, + )))) } } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, mut msg: CreateCommentPayload, ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, mut msg: CreateCommentPayload) -> WsResult { use database_actor::comments::CreateComment; let user_id = self.require_user()?.id; @@ -37,14 +61,15 @@ impl WsHandler for WebSocketActor { user_id, issue_id, body: msg.body, - } + }; async ); - self.handle_msg(LoadIssueComments { issue_id }, ctx) + self.exec(LoadIssueComments { issue_id }).await } } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateCommentPayload, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateCommentPayload) -> WsResult { use database_actor::comments::UpdateComment; let user_id = self.require_user()?.id; @@ -60,9 +85,9 @@ impl WsHandler for WebSocketActor { comment_id, user_id, body, - } + }; async ); - self.broadcast(&WsMsg::CommentUpdated(comment)); + self.broadcast(&WsMsg::Comment(WsMsgComment::CommentUpdated(comment))); Ok(None) } } @@ -71,8 +96,9 @@ pub struct DeleteComment { pub comment_id: CommentId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: DeleteComment, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: DeleteComment) -> WsResult { use database_actor::comments::DeleteComment; let user_id = self.require_user()?.id; @@ -82,8 +108,11 @@ impl WsHandler for WebSocketActor { DeleteComment { comment_id: msg.comment_id, user_id, - } + }; async ); - Ok(Some(WsMsg::CommentDeleted(msg.comment_id, n))) + Ok(Some(WsMsg::Comment(WsMsgComment::CommentDeleted( + msg.comment_id, + n, + )))) } } diff --git a/actors/websocket-actor/src/handlers/epics.rs b/actors/websocket-actor/src/handlers/epics.rs index 740f313f..c028ac80 100644 --- a/actors/websocket-actor/src/handlers/epics.rs +++ b/actors/websocket-actor/src/handlers/epics.rs @@ -1,17 +1,59 @@ -use futures::executor::block_on; +use jirs_data::msg::{WsMsgEpic, WsMsgIssue}; use jirs_data::{ DescriptionString, EndsAt, EpicId, IssueType, NameString, StartsAt, UserProject, WsMsg, }; use crate::{db_or_debug_and_return, *}; +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgEpic) -> WsResult { + match msg { + WsMsgEpic::EpicsLoad => self.exec(epics::LoadEpics).await, + WsMsgEpic::EpicCreate(name, description, description_html) => { + self.exec(epics::CreateEpic { + name, + description, + description_html, + }) + .await + } + WsMsgEpic::EpicUpdateName(epic_id, name) => { + self.exec(epics::UpdateEpicName { epic_id, name }).await + } + WsMsgEpic::EpicUpdateStartsAt(epic_id, starts_at) => { + self.exec(epics::UpdateEpicStartsAt { epic_id, starts_at }) + .await + } + WsMsgEpic::EpicUpdateEndsAt(epic_id, ends_at) => { + self.exec(epics::UpdateEpicEndsAt { epic_id, ends_at }) + .await + } + WsMsgEpic::EpicDelete(epic_id) => self.exec(epics::DeleteEpic { epic_id }).await, + WsMsgEpic::EpicTransform(epic_id, issue_type) => { + self.exec(epics::TransformEpic { + epic_id, + issue_type, + }) + .await + } + WsMsgEpic::EpicsLoaded(_) => Ok(None), + WsMsgEpic::EpicCreated(_) => Ok(None), + WsMsgEpic::EpicUpdated(_) => Ok(None), + WsMsgEpic::EpicDeleted(_, _) => Ok(None), + } + } +} + pub struct LoadEpics; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadEpics, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadEpics) -> WsResult { let project_id = self.require_user_project()?.project_id; - let epics = db_or_debug_and_return!(self, database_actor::epics::LoadEpics { project_id }); - Ok(Some(WsMsg::EpicsLoaded(epics))) + let epics = + db_or_debug_and_return!(self, database_actor::epics::LoadEpics { project_id }; async); + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicsLoaded(epics)))) } } @@ -21,8 +63,9 @@ pub struct CreateEpic { pub description_html: Option, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: CreateEpic, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: CreateEpic) -> WsResult { let CreateEpic { name, description, @@ -41,9 +84,9 @@ impl WsHandler for WebSocketActor { description, description_html, name, - } + }; async ); - Ok(Some(WsMsg::EpicCreated(epic))) + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicCreated(epic)))) } } @@ -52,8 +95,9 @@ pub struct UpdateEpicName { pub name: NameString, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateEpicName, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateEpicName) -> WsResult { let UserProject { project_id, .. } = self.require_user_project()?; let epic = db_or_debug_and_return!( self, @@ -61,9 +105,9 @@ impl WsHandler for WebSocketActor { project_id: *project_id, epic_id: msg.epic_id, name: msg.name, - } + }; async ); - Ok(Some(WsMsg::EpicUpdated(epic))) + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicUpdated(epic)))) } } @@ -72,8 +116,9 @@ pub struct UpdateEpicStartsAt { pub starts_at: Option, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateEpicStartsAt, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateEpicStartsAt) -> WsResult { let UserProject { project_id, .. } = self.require_user_project()?; let epic = db_or_debug_and_return!( self, @@ -81,9 +126,9 @@ impl WsHandler for WebSocketActor { project_id: *project_id, epic_id: msg.epic_id, starts_at: msg.starts_at, - } + }; async ); - Ok(Some(WsMsg::EpicUpdated(epic))) + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicUpdated(epic)))) } } @@ -92,8 +137,9 @@ pub struct UpdateEpicEndsAt { pub ends_at: Option, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateEpicEndsAt, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateEpicEndsAt) -> WsResult { let UserProject { project_id, .. } = self.require_user_project()?; let epic = db_or_debug_and_return!( self, @@ -101,9 +147,9 @@ impl WsHandler for WebSocketActor { project_id: *project_id, epic_id: msg.epic_id, ends_at: msg.ends_at, - } + }; async ); - Ok(Some(WsMsg::EpicUpdated(epic))) + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicUpdated(epic)))) } } @@ -111,8 +157,9 @@ pub struct DeleteEpic { pub epic_id: EpicId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: DeleteEpic, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: DeleteEpic) -> WsResult { let DeleteEpic { epic_id } = msg; let UserProject { user_id, .. } = self.require_user_project()?; let n = db_or_debug_and_return!( @@ -120,9 +167,9 @@ impl WsHandler for WebSocketActor { database_actor::epics::DeleteEpic { user_id: *user_id, epic_id, - } + }; async ); - Ok(Some(WsMsg::EpicDeleted(epic_id, n))) + Ok(Some(WsMsg::Epic(WsMsgEpic::EpicDeleted(epic_id, n)))) } } @@ -131,13 +178,14 @@ pub struct TransformEpic { pub issue_type: IssueType, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: TransformEpic, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: TransformEpic) -> WsResult { let epic: jirs_data::Epic = db_or_debug_and_return!( self, database_actor::epics::FindEpic { epic_id: msg.epic_id - } + }; async ); let issue: database_actor::models::Issue = db_or_debug_and_return!( self, @@ -155,17 +203,17 @@ impl WsHandler for WebSocketActor { reporter_id: epic.user_id, user_ids: vec![epic.user_id], epic_id: None - } + }; async ); let n = db_or_debug_and_return!( self, database_actor::epics::DeleteEpic { user_id: epic.user_id, epic_id: epic.id - } + }; async ); - self.broadcast(&WsMsg::EpicDeleted(msg.epic_id, n)); - self.broadcast(&WsMsg::IssueCreated(issue.into())); + self.broadcast(&WsMsg::Epic(WsMsgEpic::EpicDeleted(msg.epic_id, n))); + self.broadcast(&WsMsg::Issue(WsMsgIssue::IssueCreated(issue.into()))); Ok(None) } } diff --git a/actors/websocket-actor/src/handlers/hi.rs b/actors/websocket-actor/src/handlers/hi.rs index 863c5bb2..93e439be 100644 --- a/actors/websocket-actor/src/handlers/hi.rs +++ b/actors/websocket-actor/src/handlers/hi.rs @@ -1,12 +1,12 @@ -use futures::executor::block_on; use jirs_data::{Code, Lang, WsMsg}; -use crate::{actor_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{actor_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; pub struct HighlightCode(pub Lang, pub Code); -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: HighlightCode, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: HighlightCode) -> WsResult { self.require_user()?; let res = actor_or_debug_and_return!( self, @@ -14,7 +14,7 @@ impl WsHandler for WebSocketActor { highlight_actor::HighlightCode { code: msg.1, lang: msg.0, - } + }; async ); Ok(Some(WsMsg::HighlightedCode(res))) } diff --git a/actors/websocket-actor/src/handlers/invitations.rs b/actors/websocket-actor/src/handlers/invitations.rs index b5658bd8..6f83e50f 100644 --- a/actors/websocket-actor/src/handlers/invitations.rs +++ b/actors/websocket-actor/src/handlers/invitations.rs @@ -1,26 +1,64 @@ use database_actor::invitations; use database_actor::messages::CreateMessageReceiver; use futures::executor::block_on; +use jirs_data::msg::WsMsgInvitation; use jirs_data::{ EmailString, InvitationId, InvitationToken, MessageType, UserRole, UsernameString, WsMsg, }; +use crate::handlers::{LoadInvitedUsers, RemoveInvitedUser}; use crate::server::InnerMsg; use crate::{ - db_or_debug_and_return, mail_or_debug_and_return, WebSocketActor, WsHandler, WsMessageSender, - WsResult, + db_or_debug_and_return, mail_or_debug_and_return, AsyncHandler, WebSocketActor, WsHandler, + WsMessageSender, WsResult, }; +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgInvitation) -> WsResult { + match msg { + WsMsgInvitation::InvitationSendRequest { name, email, role } => { + self.exec(CreateInvitation { email, name, role }).await + } + WsMsgInvitation::InvitationListLoad => self.exec(ListInvitation).await, + + WsMsgInvitation::InvitationRevokeRequest(id) => { + self.exec(RevokeInvitation { id }).await + } + WsMsgInvitation::InvitedUsersLoad => self.exec(LoadInvitedUsers).await, + + WsMsgInvitation::InvitedUserRemoveRequest(user_id) => { + self.exec(RemoveInvitedUser { user_id }).await + } + WsMsgInvitation::InvitationListLoaded(_) => Ok(None), + WsMsgInvitation::InvitedUsersLoaded(_) => Ok(None), + WsMsgInvitation::InvitationSendSuccess => Ok(None), + WsMsgInvitation::InvitationSendFailure => Ok(None), + WsMsgInvitation::InvitationRevokeSuccess(_) => Ok(None), + WsMsgInvitation::InvitationAcceptRequest(_) => Ok(None), + WsMsgInvitation::InvitationAcceptSuccess(_) => Ok(None), + WsMsgInvitation::InvitationAcceptFailure(_) => Ok(None), + WsMsgInvitation::InvitationRejectRequest(_) => Ok(None), + WsMsgInvitation::InvitationRejectSuccess => Ok(None), + WsMsgInvitation::InvitationRejectFailure(_) => Ok(None), + WsMsgInvitation::InvitedUserRemoveSuccess(_) => Ok(None), + } + } +} + pub struct ListInvitation; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: ListInvitation, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: ListInvitation) -> WsResult { let user_id = match self.current_user.as_ref().map(|u| u.id) { Some(id) => id, _ => return Ok(None), }; - let v = db_or_debug_and_return!(self, invitations::ListInvitation { user_id }); - Ok(Some(WsMsg::InvitationListLoaded(v))) + let v = db_or_debug_and_return!(self, invitations::ListInvitation { user_id }; async); + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationListLoaded(v), + ))) } } @@ -30,8 +68,9 @@ pub struct CreateInvitation { pub role: UserRole, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: CreateInvitation, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: CreateInvitation) -> WsResult { let project_id = match self.current_user_project.as_ref() { Some(up) => up.project_id, _ => return Ok(None), @@ -48,8 +87,8 @@ impl WsHandler for WebSocketActor { name: name.clone(), role, }, - Ok(Some(WsMsg::InvitationSendFailure)), - Ok(Some(WsMsg::InvitationSendFailure)) + Ok(Some(WsMsg::Invitation(WsMsgInvitation::InvitationSendFailure))), + Ok(Some(WsMsg::Invitation(WsMsgInvitation::InvitationSendFailure))); async ); let _ = mail_or_debug_and_return!( self, @@ -58,8 +97,8 @@ impl WsHandler for WebSocketActor { email: invitation.email, inviter_name, }, - Ok(Some(WsMsg::InvitationSendFailure)), - Ok(Some(WsMsg::InvitationSendFailure)) + Ok(Some(WsMsg::Invitation(WsMsgInvitation::InvitationSendFailure))), + Ok(Some(WsMsg::Invitation(WsMsgInvitation::InvitationSendFailure))); async ); // If user exists then send message to him @@ -77,7 +116,9 @@ impl WsHandler for WebSocketActor { )); } - Ok(Some(WsMsg::InvitationSendSuccess)) + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationSendSuccess, + ))) } } @@ -85,11 +126,12 @@ pub struct DeleteInvitation { pub id: InvitationId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: DeleteInvitation, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: DeleteInvitation) -> WsResult { self.require_user()?; let DeleteInvitation { id } = msg; - let _ = db_or_debug_and_return!(self, invitations::DeleteInvitation { id }); + let _ = db_or_debug_and_return!(self, invitations::DeleteInvitation { id }; async); Ok(None) } } @@ -98,12 +140,15 @@ pub struct RevokeInvitation { pub id: InvitationId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: RevokeInvitation, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: RevokeInvitation) -> WsResult { self.require_user()?; let RevokeInvitation { id } = msg; - let _ = db_or_debug_and_return!(self, invitations::RevokeInvitation { id }); - Ok(Some(WsMsg::InvitationRevokeSuccess(id))) + let _ = db_or_debug_and_return!(self, invitations::RevokeInvitation { id }; async); + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationRevokeSuccess(id), + ))) } } @@ -117,8 +162,12 @@ impl WsHandler for WebSocketActor { let token = db_or_debug_and_return!( self, invitations::AcceptInvitation { invitation_token }, - Ok(Some(WsMsg::InvitationAcceptFailure(invitation_token))), - Ok(Some(WsMsg::InvitationAcceptFailure(invitation_token))) + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationAcceptFailure(invitation_token) + ))), + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationAcceptFailure(invitation_token) + ))) ); for message in crate::actor_or_debug_and_fallback!( @@ -144,6 +193,8 @@ impl WsHandler for WebSocketActor { ); } - Ok(Some(WsMsg::InvitationAcceptSuccess(token.access_token))) + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitationAcceptSuccess(token.access_token), + ))) } } diff --git a/actors/websocket-actor/src/handlers/issue_statuses.rs b/actors/websocket-actor/src/handlers/issue_statuses.rs index ebcfa132..8dfd7549 100644 --- a/actors/websocket-actor/src/handlers/issue_statuses.rs +++ b/actors/websocket-actor/src/handlers/issue_statuses.rs @@ -1,17 +1,48 @@ use database_actor::issue_statuses; -use futures::executor::block_on; +use jirs_data::msg::WsMsgIssueStatus; use jirs_data::{IssueStatusId, Position, TitleString, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; + +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgIssueStatus) -> WsResult { + match msg { + WsMsgIssueStatus::IssueStatusesLoad => self.exec(LoadIssueStatuses).await, + WsMsgIssueStatus::IssueStatusDelete(issue_status_id) => { + self.exec(DeleteIssueStatus { issue_status_id }).await + } + WsMsgIssueStatus::IssueStatusUpdate(issue_status_id, name, position) => { + self.exec(UpdateIssueStatus { + issue_status_id, + position, + name, + }) + .await + } + WsMsgIssueStatus::IssueStatusCreate(name, position) => { + self.exec(CreateIssueStatus { position, name }).await + } + WsMsgIssueStatus::IssueStatusesLoaded(_) => Ok(None), + WsMsgIssueStatus::IssueStatusUpdated(_) => Ok(None), + WsMsgIssueStatus::IssueStatusCreated(_) => Ok(None), + WsMsgIssueStatus::IssueStatusDeleted(_, _) => Ok(None), + } + } +} pub struct LoadIssueStatuses; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadIssueStatuses, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadIssueStatuses) -> WsResult { let project_id = self.require_user_project()?.project_id; - let v = db_or_debug_and_return!(self, issue_statuses::LoadIssueStatuses { project_id }); - Ok(Some(WsMsg::IssueStatusesLoaded(v))) + let v = + db_or_debug_and_return!(self, issue_statuses::LoadIssueStatuses { project_id }; async); + Ok(Some(WsMsg::IssueStatus( + WsMsgIssueStatus::IssueStatusesLoaded(v), + ))) } } @@ -20,8 +51,9 @@ pub struct CreateIssueStatus { pub name: TitleString, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: CreateIssueStatus, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: CreateIssueStatus) -> WsResult { let project_id = self.require_user_project()?.project_id; let CreateIssueStatus { position, name } = msg; @@ -31,9 +63,11 @@ impl WsHandler for WebSocketActor { project_id, position, name, - } + }; async ); - Ok(Some(WsMsg::IssueStatusCreated(issue_status))) + Ok(Some(WsMsg::IssueStatus( + WsMsgIssueStatus::IssueStatusCreated(issue_status), + ))) } } @@ -41,8 +75,9 @@ pub struct DeleteIssueStatus { pub issue_status_id: IssueStatusId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: DeleteIssueStatus, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: DeleteIssueStatus) -> WsResult { let project_id = self.require_user_project()?.project_id; let DeleteIssueStatus { issue_status_id } = msg; @@ -51,9 +86,11 @@ impl WsHandler for WebSocketActor { issue_statuses::DeleteIssueStatus { project_id, issue_status_id - } + }; async ); - Ok(Some(WsMsg::IssueStatusDeleted(msg.issue_status_id, n))) + Ok(Some(WsMsg::IssueStatus( + WsMsgIssueStatus::IssueStatusDeleted(msg.issue_status_id, n), + ))) } } @@ -63,8 +100,9 @@ pub struct UpdateIssueStatus { pub name: TitleString, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateIssueStatus, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateIssueStatus) -> WsResult { let project_id = self.require_user_project()?.project_id; let UpdateIssueStatus { @@ -79,9 +117,11 @@ impl WsHandler for WebSocketActor { project_id, position, name - } + }; async ); - let msg = Some(WsMsg::IssueStatusUpdated(issue_status)); + let msg = Some(WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusUpdated( + issue_status, + ))); if let Some(ws_msg) = msg.as_ref() { self.broadcast(ws_msg) } diff --git a/actors/websocket-actor/src/handlers/issues.rs b/actors/websocket-actor/src/handlers/issues.rs index c7baa685..cc680590 100644 --- a/actors/websocket-actor/src/handlers/issues.rs +++ b/actors/websocket-actor/src/handlers/issues.rs @@ -2,13 +2,36 @@ use std::collections::HashMap; use database_actor::issue_assignees::LoadAssignees; use database_actor::issues::{LoadProjectIssues, UpdateIssue}; -use futures::executor::block_on; +use jirs_data::msg::{WsMsgIssue, WsMsgProject}; use jirs_data::{ CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, IssueStatusId, ListPosition, PayloadVariant, WsMsg, }; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; + +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgIssue) -> WsResult { + match msg { + WsMsgIssue::IssueUpdate(id, field_id, payload) => { + self.exec(UpdateIssueHandler { + id, + field_id, + payload, + }) + .await + } + WsMsgIssue::IssueCreate(payload) => self.exec(payload).await, + WsMsgIssue::IssueDelete(id) => self.exec(DeleteIssue { id }).await, + WsMsgIssue::IssueSyncListPosition(sync) => self.exec(SyncIssueListPosition(sync)).await, + + WsMsgIssue::IssueUpdated(_) => Ok(None), + WsMsgIssue::IssueDeleted(_, _) => Ok(None), + WsMsgIssue::IssueCreated(_) => Ok(None), + } + } +} pub struct UpdateIssueHandler { pub id: i32, @@ -16,8 +39,9 @@ pub struct UpdateIssueHandler { pub payload: PayloadVariant, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateIssueHandler, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateIssueHandler) -> WsResult { self.require_user()?; let UpdateIssueHandler { @@ -123,23 +147,24 @@ impl WsHandler for WebSocketActor { _ => (), }; - let issue = db_or_debug_and_return!(self, msg); + let issue = db_or_debug_and_return!(self, msg; async); let mut issue: jirs_data::Issue = issue.into(); let assignees: Vec = - db_or_debug_and_return!(self, LoadAssignees { issue_id: issue.id }); + db_or_debug_and_return!(self, LoadAssignees { issue_id: issue.id }; async); for assignee in assignees { issue.user_ids.push(assignee.user_id); } - self.broadcast(&WsMsg::IssueUpdated(issue)); + self.broadcast(&WsMsg::Issue(WsMsgIssue::IssueUpdated(issue))); Ok(None) } } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: CreateIssuePayload, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: CreateIssuePayload) -> WsResult { self.require_user()?; let msg = database_actor::issues::CreateIssue { title: msg.title, @@ -156,8 +181,8 @@ impl WsHandler for WebSocketActor { user_ids: msg.user_ids, epic_id: msg.epic_id, }; - let issue = db_or_debug_and_return!(self, msg); - Ok(Some(WsMsg::IssueCreated(issue.into()))) + let issue = db_or_debug_and_return!(self, msg; async); + Ok(Some(WsMsg::Issue(WsMsgIssue::IssueCreated(issue.into())))) } } @@ -165,24 +190,26 @@ pub struct DeleteIssue { pub id: IssueId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: DeleteIssue, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: DeleteIssue) -> WsResult { self.require_user()?; let n = db_or_debug_and_return!( self, - database_actor::issues::DeleteIssue { issue_id: msg.id } + database_actor::issues::DeleteIssue { issue_id: msg.id }; async ); - Ok(Some(WsMsg::IssueDeleted(msg.id, n))) + Ok(Some(WsMsg::Issue(WsMsgIssue::IssueDeleted(msg.id, n)))) } } pub struct LoadIssues; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadIssues, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadIssues) -> WsResult { let project_id = self.require_user_project()?.project_id; - let v = db_or_debug_and_return!(self, LoadProjectIssues { project_id }); + let v = db_or_debug_and_return!(self, LoadProjectIssues { project_id }; async); let issues: Vec = v.into_iter().map(|i| i.into()).collect(); let mut issue_map = HashMap::new(); let mut queue = vec![]; @@ -192,7 +219,7 @@ impl WsHandler for WebSocketActor { issue_map.insert(issue.id, issue); } for f in queue { - if let Ok(Ok(assignees)) = block_on(f) { + if let Ok(Ok(assignees)) = f.await { for assignee in assignees { if let Some(issue) = issue_map.get_mut(&assignee.issue_id) { issue.user_ids.push(assignee.user_id); @@ -206,14 +233,17 @@ impl WsHandler for WebSocketActor { } issues.sort_by(|a, b| a.list_position.cmp(&b.list_position)); - Ok(Some(WsMsg::ProjectIssuesLoaded(issues))) + Ok(Some(WsMsg::Project(WsMsgProject::ProjectIssuesLoaded( + issues, + )))) } } pub struct SyncIssueListPosition(pub Vec<(IssueId, ListPosition, IssueStatusId, Option)>); -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: SyncIssueListPosition, ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: SyncIssueListPosition) -> WsResult { let _project_id = self.require_user_project()?.project_id; for (issue_id, list_position, status_id, epic_id) in msg.0 { crate::actor_or_debug_and_ignore!( @@ -226,10 +256,10 @@ impl WsHandler for WebSocketActor { epic_id: Some(epic_id), ..Default::default() }, - |_| {} + |_| {}; async ); } - self.handle_msg(LoadIssues, ctx) + self.exec(LoadIssues).await } } diff --git a/actors/websocket-actor/src/handlers/messages.rs b/actors/websocket-actor/src/handlers/messages.rs index c8e8fb4a..1d316754 100644 --- a/actors/websocket-actor/src/handlers/messages.rs +++ b/actors/websocket-actor/src/handlers/messages.rs @@ -1,15 +1,15 @@ use database_actor::messages; -use futures::executor::block_on; use jirs_data::{MessageId, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; pub struct LoadMessages; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadMessages, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadMessages) -> WsResult { let user_id = self.require_user()?.id; - let v = db_or_debug_and_return!(self, messages::LoadMessages { user_id }); + let v = db_or_debug_and_return!(self, messages::LoadMessages { user_id }; async); Ok(Some(WsMsg::MessagesLoaded(v))) } } @@ -18,15 +18,16 @@ pub struct MarkMessageSeen { pub id: MessageId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: MarkMessageSeen, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: MarkMessageSeen) -> WsResult { let user_id = self.require_user()?.id; let count = db_or_debug_and_return!( self, messages::MarkMessageSeen { message_id: msg.id, user_id, - } + }; async ); Ok(Some(WsMsg::MessageMarkedSeen(msg.id, count))) } diff --git a/actors/websocket-actor/src/handlers/projects.rs b/actors/websocket-actor/src/handlers/projects.rs index b0c778f7..346f950e 100644 --- a/actors/websocket-actor/src/handlers/projects.rs +++ b/actors/websocket-actor/src/handlers/projects.rs @@ -1,11 +1,28 @@ use database_actor as db; -use futures::executor::block_on; +use jirs_data::msg::WsMsgProject; use jirs_data::{UpdateProjectPayload, UserProject, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::handlers::{LoadIssues, LoadProjectUsers}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: UpdateProjectPayload, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: WsMsgProject) -> WsResult { + match msg { + WsMsgProject::ProjectIssuesLoad => self.exec(LoadIssues).await, + WsMsgProject::ProjectsLoad => self.exec(LoadProjects).await, + WsMsgProject::ProjectUpdateLoad(payload) => self.exec(payload).await, + WsMsgProject::ProjectUsersLoad => self.exec(LoadProjectUsers).await, + WsMsgProject::ProjectsLoaded(_) => Ok(None), + WsMsgProject::ProjectIssuesLoaded(_) => Ok(None), + WsMsgProject::ProjectUsersLoaded(_) => Ok(None), + } + } +} + +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: UpdateProjectPayload) -> WsResult { let UserProject { user_id, project_id, @@ -20,22 +37,23 @@ impl WsHandler for WebSocketActor { description: msg.description, category: msg.category, time_tracking: msg.time_tracking, - } + }; async ); let projects = db_or_debug_and_return!( self, - database_actor::projects::LoadProjects { user_id: *user_id } + database_actor::projects::LoadProjects { user_id: *user_id }; async ); - Ok(Some(WsMsg::ProjectsLoaded(projects))) + Ok(Some(WsMsg::Project(WsMsgProject::ProjectsLoaded(projects)))) } } pub struct LoadProjects; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadProjects, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadProjects) -> WsResult { let user_id = self.require_user()?.id; - let v = db_or_debug_and_return!(self, db::projects::LoadProjects { user_id }); - Ok(Some(WsMsg::ProjectsLoaded(v))) + let v = db_or_debug_and_return!(self, db::projects::LoadProjects { user_id }; async); + Ok(Some(WsMsg::Project(WsMsgProject::ProjectsLoaded(v)))) } } diff --git a/actors/websocket-actor/src/handlers/user_projects.rs b/actors/websocket-actor/src/handlers/user_projects.rs index 3edda485..1557d172 100644 --- a/actors/websocket-actor/src/handlers/user_projects.rs +++ b/actors/websocket-actor/src/handlers/user_projects.rs @@ -1,15 +1,16 @@ use database_actor as db; -use futures::executor::block_on; use jirs_data::{UserProjectId, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; pub struct LoadUserProjects; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadUserProjects, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadUserProjects) -> WsResult { let user_id = self.require_user()?.id; - let v = db_or_debug_and_return!(self, db::user_projects::LoadUserProjects { user_id }); + let v = + db_or_debug_and_return!(self, db::user_projects::LoadUserProjects { user_id }; async); Ok(Some(WsMsg::UserProjectsLoaded(v))) } } @@ -18,15 +19,16 @@ pub struct SetCurrentUserProject { pub id: UserProjectId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: SetCurrentUserProject, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: SetCurrentUserProject) -> WsResult { let user_id = self.require_user()?.id; let user_project = db_or_debug_and_return!( self, db::user_projects::ChangeCurrentUserProject { user_id, id: msg.id, - } + }; async ); self.current_user_project = Some(user_project.clone()); Ok(Some(WsMsg::UserProjectCurrentChanged(user_project))) diff --git a/actors/websocket-actor/src/handlers/user_settings.rs b/actors/websocket-actor/src/handlers/user_settings.rs index 20b2fe3d..80a56aa9 100644 --- a/actors/websocket-actor/src/handlers/user_settings.rs +++ b/actors/websocket-actor/src/handlers/user_settings.rs @@ -1,7 +1,6 @@ -use futures::executor::block_on; use jirs_data::{TextEditorMode, UserId, UserSetting, WsMsg}; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; pub fn default_user_setting(user_id: UserId) -> UserSetting { UserSetting { @@ -15,15 +14,16 @@ pub struct SetTextEditorMode { pub mode: TextEditorMode, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: SetTextEditorMode, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: SetTextEditorMode) -> WsResult { let user_id = self.require_user()?.id; let setting = db_or_debug_and_return!( self, database_actor::user_settings::UpdateUserSetting { user_id, mode: msg.mode - } + }; async ); Ok(Some(WsMsg::UserSettingUpdated(setting))) } diff --git a/actors/websocket-actor/src/handlers/users.rs b/actors/websocket-actor/src/handlers/users.rs index 54467797..c098defd 100644 --- a/actors/websocket-actor/src/handlers/users.rs +++ b/actors/websocket-actor/src/handlers/users.rs @@ -1,20 +1,21 @@ use database_actor::users::Register as DbRegister; use database_actor::{self}; -use futures::executor::block_on; +use jirs_data::msg::{WsMsgInvitation, WsMsgProject}; use jirs_data::{UserId, UserProject, UserRole, WsMsg}; use crate::handlers::auth::Authenticate; -use crate::{db_or_debug_and_return, WebSocketActor, WsHandler, WsResult}; +use crate::{db_or_debug_and_return, AsyncHandler, WebSocketActor, WsResult}; pub struct LoadProjectUsers; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadProjectUsers, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadProjectUsers) -> WsResult { use database_actor::users::LoadProjectUsers as Msg; let project_id = self.require_user_project()?.project_id; - let v = db_or_debug_and_return!(self, Msg { project_id }); - Ok(Some(WsMsg::ProjectUsersLoaded(v))) + let v = db_or_debug_and_return!(self, Msg { project_id }; async); + Ok(Some(WsMsg::Project(WsMsgProject::ProjectUsersLoaded(v)))) } } @@ -23,8 +24,9 @@ pub struct Register { pub email: String, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: Register, ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: Register) -> WsResult { let Register { name, email } = msg; let _ = db_or_debug_and_return!( self, @@ -35,10 +37,10 @@ impl WsHandler for WebSocketActor { role: UserRole::Owner, }, Ok(Some(WsMsg::SignUpPairTaken)), - Ok(None) + Ok(None); async ); - match self.handle_msg(Authenticate { name, email }, ctx) { + match self.exec(Authenticate { name, email }).await { Ok(_) => (), Err(e) => return Ok(Some(e)), }; @@ -49,14 +51,16 @@ impl WsHandler for WebSocketActor { pub struct LoadInvitedUsers; -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, _msg: LoadInvitedUsers, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, _msg: LoadInvitedUsers) -> WsResult { let user_id = self.require_user()?.id; - let users = - db_or_debug_and_return!(self, database_actor::users::LoadInvitedUsers { user_id }); + let users = db_or_debug_and_return!(self, database_actor::users::LoadInvitedUsers { user_id }; async); - Ok(Some(WsMsg::InvitedUsersLoaded(users))) + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitedUsersLoaded(users), + ))) } } @@ -65,8 +69,9 @@ pub struct ProfileUpdate { pub email: String, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: ProfileUpdate, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: ProfileUpdate) -> WsResult { let user_id = self.require_user()?.id; let ProfileUpdate { name, email } = msg; @@ -76,7 +81,7 @@ impl WsHandler for WebSocketActor { user_id, name, email, - } + }; async ); Ok(Some(WsMsg::ProfileUpdated)) @@ -87,8 +92,9 @@ pub struct RemoveInvitedUser { pub user_id: UserId, } -impl WsHandler for WebSocketActor { - fn handle_msg(&mut self, msg: RemoveInvitedUser, _ctx: &mut Self::Context) -> WsResult { +#[async_trait::async_trait] +impl AsyncHandler for WebSocketActor { + async fn exec(&mut self, msg: RemoveInvitedUser) -> WsResult { let RemoveInvitedUser { user_id: invited_id, } = msg; @@ -103,8 +109,10 @@ impl WsHandler for WebSocketActor { invited_id, inviter_id, project_id, - } + }; async ); - Ok(Some(WsMsg::InvitedUserRemoveSuccess(invited_id))) + Ok(Some(WsMsg::Invitation( + WsMsgInvitation::InvitedUserRemoveSuccess(invited_id), + ))) } } diff --git a/actors/websocket-actor/src/lib.rs b/actors/websocket-actor/src/lib.rs index a09a14dd..0452efbd 100644 --- a/actors/websocket-actor/src/lib.rs +++ b/actors/websocket-actor/src/lib.rs @@ -7,7 +7,8 @@ use common::{actix_web, actix_web_actors}; use database_actor::projects::LoadCurrentProject; use database_actor::user_projects::CurrentUserProject; use database_actor::DbExecutor; -use futures::executor::block_on; +use futures::executor::block_on as wait; +use jirs_data::msg::WsMsgInvitation; use jirs_data::{Project, User, UserProject, WsMsg}; use mail_actor::MailExecutor; @@ -80,154 +81,65 @@ impl WebSocketActor { debug!("incoming message: {:?}", msg); } - let msg = match msg { - WsMsg::Ping => Some(WsMsg::Pong), - WsMsg::Pong => Some(WsMsg::Ping), - - // issues - WsMsg::IssueUpdate(id, field_id, payload) => self.handle_msg( - UpdateIssueHandler { - id, - field_id, - payload, - }, - ctx, - )?, - WsMsg::IssueCreate(payload) => self.handle_msg(payload, ctx)?, - WsMsg::IssueDelete(id) => self.handle_msg(DeleteIssue { id }, ctx)?, - WsMsg::IssueSyncListPosition(sync) => { - self.handle_msg(SyncIssueListPosition(sync), ctx)? + match msg { + WsMsg::Ping => return Ok(Some(WsMsg::Pong)), + WsMsg::Pong => return Ok(Some(WsMsg::Ping)), + WsMsg::AuthorizeLoad(uuid) => { + return Ok(self.handle_msg(CheckAuthToken { token: uuid }, ctx)?) } - WsMsg::ProjectIssuesLoad => self.handle_msg(LoadIssues, ctx)?, - - // issue statuses - WsMsg::IssueStatusesLoad => self.handle_msg(LoadIssueStatuses, ctx)?, - WsMsg::IssueStatusDelete(issue_status_id) => { - self.handle_msg(DeleteIssueStatus { issue_status_id }, ctx)? - } - WsMsg::IssueStatusUpdate(issue_status_id, name, position) => self.handle_msg( - UpdateIssueStatus { - issue_status_id, - position, - name, - }, - ctx, - )?, - WsMsg::IssueStatusCreate(name, position) => { - self.handle_msg(CreateIssueStatus { position, name }, ctx)? + WsMsg::Invitation(WsMsgInvitation::InvitationAcceptRequest(invitation_token)) => { + return Ok(self.handle_msg(AcceptInvitation { invitation_token }, ctx)?) } + _ => {} + }; - // projects - WsMsg::ProjectsLoad => self.handle_msg(LoadProjects, ctx)?, - WsMsg::ProjectUpdateLoad(payload) => self.handle_msg(payload, ctx)?, + let fut = match msg { + WsMsg::Project(m) => self.exec(m), + WsMsg::Issue(m) => self.exec(m), + WsMsg::IssueStatus(m) => self.exec(m), + WsMsg::Comment(m) => self.exec(m), + WsMsg::Invitation(m) => self.exec(m), + WsMsg::Epic(m) => self.exec(m), // user projects - WsMsg::UserProjectsLoad => self.handle_msg(LoadUserProjects, ctx)?, - WsMsg::UserProjectSetCurrent(user_project_id) => self.handle_msg( - SetCurrentUserProject { - id: user_project_id, - }, - ctx, - )?, + WsMsg::UserProjectsLoad => self.exec(LoadUserProjects), + WsMsg::UserProjectSetCurrent(user_project_id) => self.exec(SetCurrentUserProject { + id: user_project_id, + }), // auth - WsMsg::AuthorizeLoad(uuid) => self.handle_msg(CheckAuthToken { token: uuid }, ctx)?, - WsMsg::BindTokenCheck(uuid) => { - self.handle_msg(CheckBindToken { bind_token: uuid }, ctx)? - } - WsMsg::AuthenticateRequest(email, name) => { - self.handle_msg(Authenticate { name, email }, ctx)? - } + WsMsg::BindTokenCheck(uuid) => self.exec(CheckBindToken { bind_token: uuid }), + WsMsg::AuthenticateRequest(email, name) => self.exec(Authenticate { name, email }), // register - WsMsg::SignUpRequest(email, username) => self.handle_msg( - Register { - name: username, - email, - }, - ctx, - )?, - - // users - WsMsg::ProjectUsersLoad => self.handle_msg(LoadProjectUsers, ctx)?, - WsMsg::InvitedUserRemoveRequest(user_id) => { - self.handle_msg(RemoveInvitedUser { user_id }, ctx)? - } + WsMsg::SignUpRequest(email, username) => self.exec(Register { + name: username, + email, + }), // user settings WsMsg::UserSettingSetEditorMode(mode) => { - self.handle_msg(user_settings::SetTextEditorMode { mode }, ctx)? + self.exec(user_settings::SetTextEditorMode { mode }) } - // comments - WsMsg::IssueCommentsLoad(issue_id) => { - self.handle_msg(LoadIssueComments { issue_id }, ctx)? - } - WsMsg::CommentCreate(payload) => self.handle_msg(payload, ctx)?, - WsMsg::CommentUpdate(payload) => self.handle_msg(payload, ctx)?, - WsMsg::CommentDelete(comment_id) => { - self.handle_msg(DeleteComment { comment_id }, ctx)? - } - - // invitations - WsMsg::InvitationSendRequest { name, email, role } => { - self.handle_msg(CreateInvitation { email, name, role }, ctx)? - } - WsMsg::InvitationListLoad => self.handle_msg(ListInvitation, ctx)?, - WsMsg::InvitationAcceptRequest(invitation_token) => { - self.handle_msg(AcceptInvitation { invitation_token }, ctx)? - } - WsMsg::InvitationRevokeRequest(id) => self.handle_msg(RevokeInvitation { id }, ctx)?, - WsMsg::InvitedUsersLoad => self.handle_msg(LoadInvitedUsers, ctx)?, - // users - WsMsg::ProfileUpdate(email, name) => { - self.handle_msg(ProfileUpdate { name, email }, ctx)? - } + WsMsg::ProfileUpdate(email, name) => self.exec(ProfileUpdate { name, email }), // messages - WsMsg::MessagesLoad => self.handle_msg(LoadMessages, ctx)?, - WsMsg::MessageMarkSeen(id) => self.handle_msg(MarkMessageSeen { id }, ctx)?, - - // epics - WsMsg::EpicsLoad => self.handle_msg(epics::LoadEpics, ctx)?, - WsMsg::EpicCreate(name, description, description_html) => self.handle_msg( - epics::CreateEpic { - name, - description, - description_html, - }, - ctx, - )?, - WsMsg::EpicUpdateName(epic_id, name) => { - self.handle_msg(epics::UpdateEpicName { epic_id, name }, ctx)? - } - WsMsg::EpicUpdateStartsAt(epic_id, starts_at) => { - self.handle_msg(epics::UpdateEpicStartsAt { epic_id, starts_at }, ctx)? - } - WsMsg::EpicUpdateEndsAt(epic_id, ends_at) => { - self.handle_msg(epics::UpdateEpicEndsAt { epic_id, ends_at }, ctx)? - } - WsMsg::EpicDelete(epic_id) => self.handle_msg(epics::DeleteEpic { epic_id }, ctx)?, - WsMsg::EpicTransform(epic_id, issue_type) => self.handle_msg( - epics::TransformEpic { - epic_id, - issue_type, - }, - ctx, - )?, + WsMsg::MessagesLoad => self.exec(LoadMessages), + WsMsg::MessageMarkSeen(id) => self.exec(MarkMessageSeen { id }), // hi - WsMsg::HighlightCode(lang, code) => { - self.handle_msg(hi::HighlightCode(lang, code), ctx)? - } + WsMsg::HighlightCode(lang, code) => self.exec(hi::HighlightCode(lang, code)), // else fail _ => { error!("No handle for {:?} specified", msg); - None + return Ok(None); } }; + let msg = wait(fut)?; + if msg.is_some() && msg != Some(WsMsg::Pong) { info!("sending message {:?}", msg); } @@ -251,8 +163,8 @@ impl WebSocketActor { .send(InnerMsg::Join(project_id, user.id, addr)) .await { - Err(e) => error!("{}", e), - _ => info!(" joined channel"), + Err(e) => common::log::error!("{:?}", e), + _ => common::log::info!(" joined channel"), }; } @@ -268,7 +180,7 @@ impl WebSocketActor { fn load_user_project(&self) -> Result { let user_id = self.require_user()?.id; - match block_on(self.db.send(CurrentUserProject { user_id })) { + match wait(self.db.send(CurrentUserProject { user_id })) { Ok(Ok(user_project)) => Ok(user_project), Ok(Err(e)) => { error!("load_user_project encounter service error {:?}", e); @@ -283,14 +195,14 @@ impl WebSocketActor { fn load_project(&self) -> Result { let project_id = self.require_user_project()?.project_id; - match block_on(self.db.send(LoadCurrentProject { project_id })) { + match wait(self.db.send(LoadCurrentProject { project_id })) { Ok(Ok(project)) => Ok(project), Ok(Err(e)) => { error!("{:?}", e); Err(WsMsg::AuthorizeExpired) } Err(e) => { - error!("{}", e); + error!("{:?}", e); Err(WsMsg::AuthorizeExpired) } } @@ -347,6 +259,14 @@ where fn handle_msg(&mut self, msg: Message, _ctx: &mut ::Context) -> WsResult; } +#[async_trait::async_trait] +pub trait AsyncHandler +where + Self: actix::Actor, +{ + async fn exec(&mut self, msg: Message) -> WsResult; +} + #[get("/ws/")] pub async fn index( req: HttpRequest, diff --git a/actors/websocket-actor/src/prelude.rs b/actors/websocket-actor/src/prelude.rs index 3eeea0b8..88e18569 100644 --- a/actors/websocket-actor/src/prelude.rs +++ b/actors/websocket-actor/src/prelude.rs @@ -6,6 +6,12 @@ macro_rules! db_or_debug_and_return { ($s: ident, $msg: expr) => { $crate::actor_or_debug_and_return!($s, db, $msg) }; + ($s: ident, $msg: expr, $actor_err: expr, $mailbox_err: expr; async) => { + $crate::actor_or_debug_and_return!($s, db, $msg, $actor_err, $mailbox_err; async) + }; + ($s: ident, $msg: expr; async) => { + $crate::actor_or_debug_and_return!($s, db, $msg; async) + }; } #[macro_export] @@ -16,6 +22,12 @@ macro_rules! db_or_debug_or_fallback { ($s: ident, $msg: expr) => { $crate::actor_or_debug_and_fallback!($s, db, $msg) }; + ($s: ident, $msg: expr, $actor_err: expr, $mailbox_err: expr;async) => { + $crate::actor_or_debug_and_fallback!($s, db, $msg, $actor_err, $mailbox_err;async) + }; + ($s: ident, $msg: expr;async) => { + $crate::actor_or_debug_and_fallback!($s, db, $msg;async) + }; } #[macro_export] @@ -26,6 +38,12 @@ macro_rules! mail_or_debug_and_return { ($s: ident, $msg: expr) => { $crate::actor_or_debug_and_return!($s, mail, $msg) }; + ($s: ident, $msg: expr, $actor_err: expr, $mailbox_err: expr; async) => { + $crate::actor_or_debug_and_return!($s, mail, $msg, $actor_err, $mailbox_err; async) + }; + ($s: ident, $msg: expr; async) => { + $crate::actor_or_debug_and_return!($s, mail, $msg; async) + }; } #[macro_export] @@ -46,6 +64,22 @@ macro_rules! actor_or_debug_and_return { ($s: ident, $actor: ident, $msg: expr) => { crate::actor_or_debug_and_return!($s, $actor, $msg, Ok(None), Ok(None)) }; + ($s: ident, $actor: ident, $msg: expr, $actor_err: expr, $mailbox_err: expr; async) => { + match $s.$actor.send($msg).await { + Ok(Ok(r)) => r, + Ok(Err(e)) => { + common::log::error!("{:?}", e); + return $actor_err; + } + Err(e) => { + common::log::error!("{:?}", e); + return $mailbox_err; + } + } + }; + ($s: ident, $actor: ident, $msg: expr;async) => { + crate::actor_or_debug_and_return!($s, $actor, $msg, Ok(None), Ok(None); async) + }; } #[macro_export] @@ -63,6 +97,19 @@ macro_rules! actor_or_debug_and_ignore { } } }; + ($s: ident, $actor: ident, $msg: expr, $on_success: expr;async) => { + match $s.$actor.send($msg).await { + Ok(Ok(r)) => { + $on_success(r); + } + Ok(Err(e)) => { + common::log::error!("{:?}", e); + } + Err(e) => { + common::log::error!("{:?}", e); + } + } + }; } #[macro_export] @@ -80,4 +127,17 @@ macro_rules! actor_or_debug_and_fallback { } } }; + ($s: ident, $actor: ident, $msg: expr, $actor_err: expr, $mailbox_err: expr; async) => { + match $s.$actor.send($msg).await { + Ok(Ok(r)) => r, + Ok(Err(e)) => { + common::log::error!("{:?}", e); + $actor_err + } + Err(e) => { + common::log::error!("{:?}", e); + $mailbox_err + } + } + }; } diff --git a/jirs-client/src/modals/epics_delete/update.rs b/jirs-client/src/modals/epics_delete/update.rs index e16289b6..ddfba3c3 100644 --- a/jirs-client/src/modals/epics_delete/update.rs +++ b/jirs-client/src/modals/epics_delete/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgEpic; use jirs_data::WsMsg; use seed::prelude::*; @@ -12,7 +13,11 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde match msg { Msg::DeleteEpic => { - send_ws_msg(WsMsg::EpicDelete(modal.epic_id), model.ws.as_ref(), orders); + send_ws_msg( + WsMsg::Epic(WsMsgEpic::EpicDelete(modal.epic_id)), + model.ws.as_ref(), + orders, + ); } Msg::ResourceChanged(ResourceKind::Epic, OperationKind::SingleRemoved, Some(_)) => { orders.skip().send_msg(Msg::ModalDropped); diff --git a/jirs-client/src/modals/epics_edit/update.rs b/jirs-client/src/modals/epics_edit/update.rs index b663cd81..c36283c8 100644 --- a/jirs-client/src/modals/epics_edit/update.rs +++ b/jirs-client/src/modals/epics_edit/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgEpic; use jirs_data::{EpicFieldId, IssueType, WsMsg}; use seed::prelude::*; @@ -35,7 +36,7 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde Msg::StrInputChanged(FieldId::EditEpic(EpicFieldId::Name), s) => { let epic_id = modal.epic_id; send_ws_msg( - WsMsg::EpicUpdateName(epic_id, s.to_string()), + WsMsg::Epic(WsMsgEpic::EpicUpdateName(epic_id, s.to_string())), model.ws.as_ref(), orders, ); @@ -46,7 +47,7 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde ) => { let epic_id = modal.epic_id; send_ws_msg( - WsMsg::EpicUpdateStartsAt(epic_id, Some(*date)), + WsMsg::Epic(WsMsgEpic::EpicUpdateStartsAt(epic_id, Some(*date))), model.ws.as_ref(), orders, ); @@ -57,7 +58,7 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde ) => { let epic_id = modal.epic_id; send_ws_msg( - WsMsg::EpicUpdateEndsAt(epic_id, Some(*date)), + WsMsg::Epic(WsMsgEpic::EpicUpdateEndsAt(epic_id, Some(*date))), model.ws.as_ref(), orders, ); @@ -66,7 +67,7 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde let epic_id = modal.epic_id; let issue_type: IssueType = modal.transform_into.value.into(); send_ws_msg( - WsMsg::EpicTransform(epic_id, issue_type), + WsMsg::Epic(WsMsgEpic::EpicTransform(epic_id, issue_type)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/modals/issue_statuses_delete/update.rs b/jirs-client/src/modals/issue_statuses_delete/update.rs index 167850ec..31429237 100644 --- a/jirs-client/src/modals/issue_statuses_delete/update.rs +++ b/jirs-client/src/modals/issue_statuses_delete/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgIssueStatus; use jirs_data::WsMsg; use seed::prelude::*; @@ -13,7 +14,7 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { match msg { Msg::DeleteIssueStatus(issue_status_id) => { crate::ws::send_ws_msg( - WsMsg::IssueStatusDelete(*issue_status_id), + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusDelete(*issue_status_id)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/modals/issues_create/update.rs b/jirs-client/src/modals/issues_create/update.rs index 91662752..0017ecae 100644 --- a/jirs-client/src/modals/issues_create/update.rs +++ b/jirs-client/src/modals/issues_create/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::{WsMsgEpic, WsMsgIssue}; use jirs_data::{IssueFieldId, UserId, WsMsg}; use seed::prelude::*; @@ -24,7 +25,11 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde } Msg::AddEpic => { send_ws_msg( - WsMsg::EpicCreate(modal.title_state.value.clone(), None, None), + WsMsg::Epic(WsMsgEpic::EpicCreate( + modal.title_state.value.clone(), + None, + None, + )), model.ws.as_ref(), orders, ); @@ -51,7 +56,7 @@ pub fn update(msg: &Msg, model: &mut crate::model::Model, orders: &mut impl Orde }; send_ws_msg( - jirs_data::WsMsg::IssueCreate(payload), + jirs_data::WsMsg::Issue(WsMsgIssue::IssueCreate(payload)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/modals/issues_edit/update.rs b/jirs-client/src/modals/issues_edit/update.rs index d0845023..38c7535d 100644 --- a/jirs-client/src/modals/issues_edit/update.rs +++ b/jirs-client/src/modals/issues_edit/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::{WsMsgComment, WsMsgIssue}; use jirs_data::*; use seed::prelude::*; @@ -32,11 +33,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.issue_type = (*value).into(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsg::Issue(WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Type, PayloadVariant::IssueType(modal.payload.issue_type), - ), + )), model.ws.as_ref(), orders, ); @@ -49,11 +50,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.issue_status_id = *value as IssueStatusId; send_ws_msg( - WsMsg::IssueUpdate( + WsMsg::Issue(WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::IssueStatusId, PayloadVariant::I32(modal.payload.issue_status_id), - ), + )), model.ws.as_ref(), orders, ); @@ -66,11 +67,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.reporter_id = *value as i32; send_ws_msg( - WsMsg::IssueUpdate( + WsMsg::Issue(WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Reporter, PayloadVariant::I32(modal.payload.reporter_id), - ), + )), model.ws.as_ref(), orders, ); @@ -83,11 +84,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.user_ids.push(*value as i32); send_ws_msg( - WsMsg::IssueUpdate( + WsMsg::Issue(WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Assignees, PayloadVariant::VecI32(modal.payload.user_ids.clone()), - ), + )), model.ws.as_ref(), orders, ); @@ -104,11 +105,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { } } send_ws_msg( - WsMsg::IssueUpdate( + WsMsg::Issue(WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Assignees, PayloadVariant::VecI32(modal.payload.user_ids.clone()), - ), + )), model.ws.as_ref(), orders, ); @@ -121,11 +122,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.priority = (*value).into(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Priority, PayloadVariant::IssuePriority(modal.payload.priority), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -138,11 +140,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.title = value.clone(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Title, PayloadVariant::String(modal.payload.title.clone()), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -156,7 +159,7 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.description_text = Some(value.clone()); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Description, PayloadVariant::String( @@ -167,7 +170,8 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { .cloned() .unwrap_or_default(), ), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -180,11 +184,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.time_spent = modal.time_spent.represent_f64_as_i32(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::TimeSpent, PayloadVariant::OptionI32(modal.payload.time_spent), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -195,11 +200,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.time_spent = modal.time_spent_select.values.get(0).map(|n| *n as i32); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::TimeSpent, PayloadVariant::OptionI32(modal.payload.time_spent), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -211,11 +217,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.time_remaining = modal.time_remaining.represent_f64_as_i32(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::TimeRemaining, PayloadVariant::OptionI32(modal.payload.time_remaining), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -227,11 +234,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { modal.payload.time_remaining = modal.time_remaining_select.values.get(0).map(|n| *n as i32); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::TimeRemaining, PayloadVariant::OptionI32(modal.payload.time_remaining), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -243,11 +251,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.estimate = modal.estimate.represent_f64_as_i32(); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Estimate, PayloadVariant::OptionI32(modal.payload.estimate), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -258,11 +267,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { ) => { modal.payload.estimate = modal.estimate_select.values.get(0).map(|n| *n as i32); send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::Estimate, PayloadVariant::OptionI32(modal.payload.estimate), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -272,11 +282,12 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { StyledSelectChanged::Changed(v), ) => { send_ws_msg( - WsMsg::IssueUpdate( + WsMsgIssue::IssueUpdate( modal.id, IssueFieldId::EpicName, PayloadVariant::OptionI32(v.map(|n| n as EpicId)), - ), + ) + .into(), model.ws.as_ref(), orders, ); @@ -301,17 +312,17 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { } Msg::SaveComment => { let msg = match modal.comment_form.id { - Some(id) => WsMsg::CommentUpdate(UpdateCommentPayload { + Some(id) => WsMsgComment::CommentUpdate(UpdateCommentPayload { id, body: modal.comment_form.body.clone(), }), - _ => WsMsg::CommentCreate(CreateCommentPayload { + _ => WsMsgComment::CommentCreate(CreateCommentPayload { user_id: None, body: modal.comment_form.body.clone(), issue_id: modal.id, }), }; - send_ws_msg(msg, model.ws.as_ref(), orders); + send_ws_msg(msg.into(), model.ws.as_ref(), orders); orders .skip() .send_msg(Msg::ModalChanged(FieldChange::ToggleCommentForm( @@ -335,7 +346,11 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { modal.comment_form.creating = true; } Msg::DeleteComment(comment_id) => { - send_ws_msg(WsMsg::CommentDelete(*comment_id), model.ws.as_ref(), orders); + send_ws_msg( + WsMsgComment::CommentDelete(*comment_id).into(), + model.ws.as_ref(), + orders, + ); orders.skip().send_msg(Msg::ModalDropped); } diff --git a/jirs-client/src/modals/update.rs b/jirs-client/src/modals/update.rs index 88dc500a..881f877d 100644 --- a/jirs-client/src/modals/update.rs +++ b/jirs-client/src/modals/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgComment; use jirs_data::{CommentId, EpicId, IssueId, IssueStatusId, TimeTracking, WsMsg}; use seed::prelude::*; @@ -193,7 +194,7 @@ fn push_edit_issue_modal(issue_id: EpicId, model: &mut Model, orders: &mut impl crate::modals::issues_edit::Model::new(user_mode, issue, time_tracking_type) }; send_ws_msg( - WsMsg::IssueCommentsLoad(issue_id), + WsMsg::Comment(WsMsgComment::IssueCommentsLoad(issue_id)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/pages/epics_page/update.rs b/jirs-client/src/pages/epics_page/update.rs index 588e2cec..5ee1d9ee 100644 --- a/jirs-client/src/pages/epics_page/update.rs +++ b/jirs-client/src/pages/epics_page/update.rs @@ -1,4 +1,4 @@ -use jirs_data::WsMsg; +use jirs_data::msg::WsMsgIssueStatus; use seed::app::Orders; use crate::model::{Model, Page, PageContent}; @@ -39,5 +39,9 @@ fn build_page_content(model: &mut Model, orders: &mut impl Orders) { return; } model.page_content = PageContent::Epics(Box::new(super::EpicsPage::new(model))); - send_ws_msg(WsMsg::IssueStatusesLoad, model.ws.as_ref(), orders); + send_ws_msg( + WsMsgIssueStatus::IssueStatusesLoad.into(), + model.ws.as_ref(), + orders, + ); } diff --git a/jirs-client/src/pages/invite_page/update.rs b/jirs-client/src/pages/invite_page/update.rs index 98991df7..ac6047da 100644 --- a/jirs-client/src/pages/invite_page/update.rs +++ b/jirs-client/src/pages/invite_page/update.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use jirs_data::fields::*; +use jirs_data::msg::WsMsgInvitation; use jirs_data::WsMsg; use seed::prelude::*; @@ -26,10 +27,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { match msg { Msg::WebSocketChange(WebSocketChanged::WsMsg(ws_msg)) => match ws_msg { - WsMsg::InvitationAcceptFailure(_) => { + WsMsg::Invitation(WsMsgInvitation::InvitationAcceptFailure(_)) => { page.error = Some("Invalid token".to_string()); } - WsMsg::InvitationAcceptSuccess(token) => { + WsMsg::Invitation(WsMsgInvitation::InvitationAcceptSuccess(token)) => { if let Ok(Msg::AuthTokenStored) = write_auth_token(Some(token)) { authorize_or_redirect(model, orders); } @@ -44,7 +45,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { Msg::PageChanged(PageChanged::Invitation(InvitationPageChange::SubmitForm)) => { if let Ok(token) = uuid::Uuid::from_str(page.token.as_str()) { send_ws_msg( - WsMsg::InvitationAcceptRequest(token), + WsMsgInvitation::InvitationAcceptRequest(token).into(), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/pages/project_page/update.rs b/jirs-client/src/pages/project_page/update.rs index 776edf2a..aaeabe8b 100644 --- a/jirs-client/src/pages/project_page/update.rs +++ b/jirs-client/src/pages/project_page/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgIssue; use jirs_data::*; use seed::prelude::Orders; @@ -106,7 +107,7 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order } Msg::DeleteIssue(issue_id) => { send_ws_msg( - jirs_data::WsMsg::IssueDelete(issue_id), + jirs_data::WsMsg::Issue(WsMsgIssue::IssueDelete(issue_id)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/pages/project_settings_page/update.rs b/jirs-client/src/pages/project_settings_page/update.rs index e6b9f5db..7838f0f8 100644 --- a/jirs-client/src/pages/project_settings_page/update.rs +++ b/jirs-client/src/pages/project_settings_page/update.rs @@ -1,5 +1,6 @@ use std::collections::HashSet; +use jirs_data::msg::{WsMsgIssueStatus, WsMsgProject}; use jirs_data::{IssueStatus, IssueStatusId, ProjectFieldId, UpdateProjectPayload, WsMsg}; use seed::prelude::Orders; @@ -22,7 +23,9 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { WebSocketChanged::WsMsg(WsMsg::AuthorizeLoaded(..)) => { board_load(model, orders); } - WebSocketChanged::WsMsg(WsMsg::IssueStatusCreated(_)) => { + WebSocketChanged::WsMsg(WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusCreated( + _, + ))) => { match &mut model.page_content { PageContent::ProjectSettings(page) if Some(0) == page.edit_column_id => { page.reset(); @@ -83,14 +86,15 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { ProjectPageChange::SubmitProjectSettingsForm, )) => { send_ws_msg( - WsMsg::ProjectUpdateLoad(UpdateProjectPayload { + WsMsgProject::ProjectUpdateLoad(UpdateProjectPayload { id: page.payload.id, name: page.payload.name.clone(), url: page.payload.url.clone(), description: page.payload.description.clone(), category: page.payload.category, time_tracking: Some(page.time_tracking.value.into()), - }), + }) + .into(), model.ws.as_ref(), orders, ); @@ -129,7 +133,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { .map(|is| (is.id, is.position)) { send_ws_msg( - WsMsg::IssueStatusUpdate(id, name, pos), + WsMsgIssueStatus::IssueStatusUpdate(id, name, pos).into(), model.ws.as_ref(), orders, ); @@ -153,7 +157,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { )) => { let name = page.name.value.clone(); let position = model.issue_statuses.len(); - let ws_msg = WsMsg::IssueStatusCreate(name, position as i32); + let ws_msg = WsMsgIssueStatus::IssueStatusCreate(name, position as i32).into(); send_ws_msg(ws_msg, model.ws.as_ref(), orders); } _ => (), @@ -226,7 +230,7 @@ fn sync(model: &mut Model, orders: &mut impl Orders) { _ => continue, }; send_ws_msg( - WsMsg::IssueStatusUpdate(id, name.clone(), *position), + WsMsgIssueStatus::IssueStatusUpdate(id, name.clone(), *position).into(), model.ws.as_ref(), orders, ); @@ -247,5 +251,9 @@ fn build_page_content(model: &mut Model, orders: &mut impl Orders) { PageContent::ProjectSettings(Box::new(ProjectSettingsPage::new(mode, project))); } - send_ws_msg(WsMsg::IssueStatusesLoad, model.ws.as_ref(), orders); + send_ws_msg( + WsMsgIssueStatus::IssueStatusesLoad.into(), + model.ws.as_ref(), + orders, + ); } diff --git a/jirs-client/src/pages/users_page/update.rs b/jirs-client/src/pages/users_page/update.rs index abdad6cf..259110f6 100644 --- a/jirs-client/src/pages/users_page/update.rs +++ b/jirs-client/src/pages/users_page/update.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgInvitation; use jirs_data::{InvitationState, UserRole, UsersFieldId, WsMsg}; use seed::prelude::Orders; @@ -28,13 +29,19 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { WebSocketChanged::WsMsg(WsMsg::AuthorizeLoaded(Ok(_))) if model.user.is_some() => { invitation_load(model, orders); } - WebSocketChanged::WsMsg(WsMsg::InvitedUsersLoaded(users)) => { + WebSocketChanged::WsMsg(WsMsg::Invitation(WsMsgInvitation::InvitedUsersLoaded( + users, + ))) => { page.invited_users = users; } - WebSocketChanged::WsMsg(WsMsg::InvitationListLoaded(invitations)) => { + WebSocketChanged::WsMsg(WsMsg::Invitation(WsMsgInvitation::InvitationListLoaded( + invitations, + ))) => { page.invitations = invitations; } - WebSocketChanged::WsMsg(WsMsg::InvitationRevokeSuccess(id)) => { + WebSocketChanged::WsMsg(WsMsg::Invitation( + WsMsgInvitation::InvitationRevokeSuccess(id), + )) => { let mut old = vec![]; std::mem::swap(&mut page.invitations, &mut old); for mut invitation in old { @@ -43,9 +50,15 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { } page.invitations.push(invitation); } - send_ws_msg(WsMsg::InvitationListLoad, model.ws.as_ref(), orders); + send_ws_msg( + WsMsgInvitation::InvitationListLoad.into(), + model.ws.as_ref(), + orders, + ); } - WebSocketChanged::WsMsg(WsMsg::InvitedUserRemoveSuccess(removed_id)) => { + WebSocketChanged::WsMsg(WsMsg::Invitation( + WsMsgInvitation::InvitedUserRemoveSuccess(removed_id), + )) => { let mut old = vec![]; std::mem::swap(&mut page.invited_users, &mut old); for user in old { @@ -54,11 +67,15 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { } } } - WebSocketChanged::WsMsg(WsMsg::InvitationSendSuccess) => { - send_ws_msg(WsMsg::InvitationListLoad, model.ws.as_ref(), orders); + WebSocketChanged::WsMsg(WsMsg::Invitation(WsMsgInvitation::InvitationSendSuccess)) => { + send_ws_msg( + WsMsgInvitation::InvitationListLoad.into(), + model.ws.as_ref(), + orders, + ); page.form_state = InvitationFormState::Succeed; } - WebSocketChanged::WsMsg(WsMsg::InvitationSendFailure) => { + WebSocketChanged::WsMsg(WsMsg::Invitation(WsMsgInvitation::InvitationSendFailure)) => { page.form_state = InvitationFormState::Failed; } _ => (), @@ -94,25 +111,25 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { page.form_state = InvitationFormState::Sent; send_ws_msg( - WsMsg::InvitationSendRequest { + WsMsg::Invitation(WsMsgInvitation::InvitationSendRequest { name: page.name.clone(), email: page.email.clone(), role, - }, + }), model.ws.as_ref(), orders, ); } Msg::InviteRevokeRequest(invitation_id) => { send_ws_msg( - WsMsg::InvitationRevokeRequest(invitation_id), + WsMsg::Invitation(WsMsgInvitation::InvitationRevokeRequest(invitation_id)), model.ws.as_ref(), orders, ); } Msg::InvitedUserRemove(user_id) => { send_ws_msg( - WsMsg::InvitedUserRemoveRequest(user_id), + WsMsg::Invitation(WsMsgInvitation::InvitedUserRemoveRequest(user_id)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/shared/aside.rs b/jirs-client/src/shared/aside.rs index 10f9a4db..ba8f3c73 100644 --- a/jirs-client/src/shared/aside.rs +++ b/jirs-client/src/shared/aside.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgProject; use jirs_data::{UserRole, WsMsg}; use seed::prelude::*; use seed::*; @@ -13,8 +14,8 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { enqueue_ws_msg( vec![ WsMsg::UserProjectsLoad, - WsMsg::ProjectsLoad, - WsMsg::ProjectUsersLoad, + WsMsg::Project(WsMsgProject::ProjectsLoad), + WsMsg::Project(WsMsgProject::ProjectUsersLoad), WsMsg::MessagesLoad, ], model.ws.as_ref(), diff --git a/jirs-client/src/shared/navbar_left.rs b/jirs-client/src/shared/navbar_left.rs index 768267b9..00e8b26d 100644 --- a/jirs-client/src/shared/navbar_left.rs +++ b/jirs-client/src/shared/navbar_left.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgInvitation; use jirs_data::{InvitationToken, Message, MessageType, WsMsg}; use seed::prelude::*; use seed::*; @@ -35,8 +36,12 @@ impl IntoNavItemIcon for Icon { pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { let m = match msg { - Msg::MessageInvitationApproved(token) => WsMsg::InvitationAcceptRequest(*token), - Msg::MessageInvitationDismiss(token) => WsMsg::InvitationRejectRequest(*token), + Msg::MessageInvitationApproved(token) => { + WsMsgInvitation::InvitationAcceptRequest(*token).into() + } + Msg::MessageInvitationDismiss(token) => { + WsMsgInvitation::InvitationRejectRequest(*token).into() + } Msg::MessageSeen(id) => WsMsg::MessageMarkSeen(*id), _ => return, }; diff --git a/jirs-client/src/ws/init_load_sets.rs b/jirs-client/src/ws/init_load_sets.rs index 5910fffb..327b056b 100644 --- a/jirs-client/src/ws/init_load_sets.rs +++ b/jirs-client/src/ws/init_load_sets.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::{WsMsgEpic, WsMsgInvitation, WsMsgIssueStatus, WsMsgProject}; use jirs_data::WsMsg; use seed::app::Orders; @@ -8,10 +9,10 @@ use crate::Msg; pub fn board_load(model: &mut Model, orders: &mut impl Orders) { enqueue_ws_msg( vec![ - WsMsg::IssueStatusesLoad, - WsMsg::ProjectIssuesLoad, - WsMsg::ProjectUsersLoad, - WsMsg::EpicsLoad, + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusesLoad), + WsMsg::Project(WsMsgProject::ProjectIssuesLoad), + WsMsg::Project(WsMsgProject::ProjectUsersLoad), + WsMsg::Epic(WsMsgEpic::EpicsLoad), ], model.ws.as_ref(), orders, @@ -20,7 +21,10 @@ pub fn board_load(model: &mut Model, orders: &mut impl Orders) { pub fn invitation_load(model: &mut Model, orders: &mut impl Orders) { enqueue_ws_msg( - vec![WsMsg::InvitationListLoad, WsMsg::InvitedUsersLoad], + vec![ + WsMsg::Invitation(WsMsgInvitation::InvitationListLoad), + WsMsg::Invitation(WsMsgInvitation::InvitedUsersLoad), + ], model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/ws/issue.rs b/jirs-client/src/ws/issue.rs index e466b952..8ac5cb45 100644 --- a/jirs-client/src/ws/issue.rs +++ b/jirs-client/src/ws/issue.rs @@ -1,3 +1,4 @@ +use jirs_data::msg::WsMsgIssue; use jirs_data::*; use seed::prelude::Orders; use seed::*; @@ -104,7 +105,7 @@ pub fn sync(model: &mut Model, orders: &mut impl Orders) { .collect(); send_ws_msg( - WsMsg::IssueSyncListPosition(changes), + WsMsg::Issue(WsMsgIssue::IssueSyncListPosition(changes)), model.ws.as_ref(), orders, ); diff --git a/jirs-client/src/ws/mod.rs b/jirs-client/src/ws/mod.rs index a1e11494..8a12879d 100644 --- a/jirs-client/src/ws/mod.rs +++ b/jirs-client/src/ws/mod.rs @@ -1,4 +1,5 @@ pub use init_load_sets::*; +use jirs_data::msg::{WsMsgComment, WsMsgEpic, WsMsgIssue, WsMsgIssueStatus, WsMsgProject}; use jirs_data::*; use seed::prelude::*; @@ -129,7 +130,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { } } // project - WsMsg::ProjectsLoaded(v) => { + WsMsg::Project(WsMsgProject::ProjectsLoaded(v)) => { model.projects = v; init_current_project(model, orders); orders.send_msg(Msg::ResourceChanged( @@ -175,7 +176,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { } // issue statuses - WsMsg::IssueStatusesLoaded(v) => { + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusesLoaded(v)) => { model.issue_statuses = v; model .issue_statuses @@ -186,7 +187,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { None, )); } - WsMsg::IssueStatusCreated(is) => { + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusCreated(is)) => { let id = is.id; model.issue_statuses.push(is); model @@ -198,7 +199,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(id), )); } - WsMsg::IssueStatusUpdated(mut changed) => { + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusUpdated(mut changed)) => { let id = changed.id; if let Some(idx) = model.issue_statuses.iter().position(|c| c.id == changed.id) { std::mem::swap(&mut model.issue_statuses[idx], &mut changed); @@ -212,7 +213,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(id), )); } - WsMsg::IssueStatusDeleted(dropped_id, _count) => { + WsMsg::IssueStatus(WsMsgIssueStatus::IssueStatusDeleted(dropped_id, _count)) => { let mut old = vec![]; std::mem::swap(&mut model.issue_statuses, &mut old); for is in old { @@ -230,7 +231,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { )); } // issues - WsMsg::ProjectIssuesLoaded(mut v) => { + WsMsg::Project(WsMsgProject::ProjectIssuesLoaded(mut v)) => { v.sort_by(|a, b| (a.list_position as i64).cmp(&(b.list_position as i64))); { let _ = std::mem::replace(model.issues_mut(), v.clone()); @@ -246,7 +247,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { None, )); } - WsMsg::IssueUpdated(issue) => { + WsMsg::Issue(WsMsgIssue::IssueUpdated(issue)) => { let id = issue.id; model.issues_by_id.remove(&id); model.issues_by_id.insert(id, issue.clone()); @@ -259,7 +260,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(id), )); } - WsMsg::IssueDeleted(id, _count) => { + WsMsg::Issue(WsMsgIssue::IssueDeleted(id, _count)) => { let mut old = vec![]; std::mem::swap(model.issues_mut(), &mut old); for is in old { @@ -275,7 +276,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { )); } // users - WsMsg::ProjectUsersLoaded(v) => { + WsMsg::Project(WsMsgProject::ProjectUsersLoaded(v)) => { model.users = v.clone(); model.users_by_id.clear(); for user in v { @@ -288,7 +289,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { )); } // comments - WsMsg::IssueCommentsLoaded(mut comments) => { + WsMsg::Comment(WsMsgComment::IssueCommentsLoaded(mut comments)) => { let issue_id = match &model.modals().edit_issue { Some(modal) => modal.id, _ => return, @@ -307,7 +308,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { None, )); } - WsMsg::CommentUpdated(comment) => { + WsMsg::Comment(WsMsgComment::CommentUpdated(comment)) => { let comment_id = comment.id; if let Some(idx) = model.comments.iter().position(|c| c.id == comment.id) { let _ = std::mem::replace(&mut model.comments[idx], comment.clone()); @@ -319,7 +320,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(comment_id), )); } - WsMsg::CommentDeleted(comment_id, _count) => { + WsMsg::Comment(WsMsgComment::CommentDeleted(comment_id, _count)) => { if let Some(idx) = model.comments.iter().position(|c| c.id == comment_id) { model.comments.remove(idx); } @@ -381,7 +382,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { } // epics - WsMsg::EpicsLoaded(epics) => { + WsMsg::Epic(WsMsgEpic::EpicsLoaded(epics)) => { model.epics = epics.clone(); for epic in epics { model.epics_by_id.insert(epic.id, epic); @@ -392,7 +393,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { None, )); } - WsMsg::EpicCreated(epic) => { + WsMsg::Epic(WsMsgEpic::EpicCreated(epic)) => { let id = epic.id; model.epics.push(epic.clone()); model.epics.sort_by(|a, b| a.id.cmp(&b.id)); @@ -403,7 +404,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(id), )); } - WsMsg::EpicUpdated(epic) => { + WsMsg::Epic(WsMsgEpic::EpicUpdated(epic)) => { let epic_id = epic.id; if let Some(idx) = model.epics.iter().position(|e| e.id == epic.id) { let _ = std::mem::replace(&mut model.epics[idx], epic.clone()); @@ -416,7 +417,7 @@ pub fn update(msg: WsMsg, model: &mut Model, orders: &mut impl Orders) { Some(epic_id), )); } - WsMsg::EpicDeleted(id, _count) => { + WsMsg::Epic(WsMsgEpic::EpicDeleted(id, _count)) => { if let Some(idx) = model.epics.iter().position(|e| e.id == id) { model.epics.remove(idx); } diff --git a/jirs-server/Cargo.toml b/jirs-server/Cargo.toml index 42020b9b..ed06043c 100644 --- a/jirs-server/Cargo.toml +++ b/jirs-server/Cargo.toml @@ -23,29 +23,9 @@ actix = { version = "0.10.0" } dotenv = { version = "*" } -byteorder = "1.0" -chrono = { version = "0.4", features = ["serde"] } -time = { version = "0.1" } -url = { version = "2.1.0" } -percent-encoding = { version = "2.1.0" } -uuid = { version = "0.8.1", features = ["serde", "v4", "v5"] } -ipnetwork = { version = ">=0.12.2, <0.17.0" } -num-bigint = { version = ">=0.1.41, <0.3" } -num-traits = { version = "0.2" } -num-integer = { version = "0.1.32" } -bigdecimal = { version = ">= 0.0.10, <= 0.1.0" } -bitflags = { version = "1.0" } - serde = { version = "*", features = ["derive"] } serde_json = { version = ">=0.8.0, <2.0" } toml = { version = "0.5.6" } -bincode = { version = "1.2.1" } - -log = { version = "0.4" } -pretty_env_logger = { version = "0.4" } -env_logger = { version = "0.7" } - -async-trait = { version = "*" } futures = { version = "*" } openssl-sys = { version = "*", features = ["vendored"] } diff --git a/shared/jirs-data/src/msg.rs b/shared/jirs-data/src/msg.rs index a20fb256..441d614b 100644 --- a/shared/jirs-data/src/msg.rs +++ b/shared/jirs-data/src/msg.rs @@ -120,27 +120,60 @@ impl WsError { } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] -pub enum WsMsg { - Ping, - Pong, - Die, +pub enum WsMsgIssue { + IssueUpdate(IssueId, IssueFieldId, PayloadVariant), + IssueUpdated(Issue), + IssueDelete(IssueId), + IssueDeleted(IssueId, NumberOfDeleted), + IssueCreate(CreateIssuePayload), + IssueCreated(Issue), + IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option)>), +} - // auth - AuthorizeLoad(Uuid), - AuthorizeLoaded(Result<(User, UserSetting), String>), - AuthorizeExpired, - AuthenticateRequest(EmailString, UsernameString), - AuthenticateSuccess, - BindTokenCheck(Uuid), - BindTokenBad, - BindTokenOk(Uuid), +impl From for WsMsg { + fn from(msg: WsMsgIssue) -> Self { + WsMsg::Issue(msg) + } +} - // Sign up - SignUpRequest(EmailString, UsernameString), - SignUpSuccess, - SignUpPairTaken, +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsgIssueStatus { + IssueStatusesLoad, + IssueStatusesLoaded(Vec), + IssueStatusUpdate(IssueStatusId, TitleString, Position), + IssueStatusUpdated(IssueStatus), + IssueStatusCreate(TitleString, Position), + IssueStatusCreated(IssueStatus), + IssueStatusDelete(IssueStatusId), + IssueStatusDeleted(IssueStatusId, NumberOfDeleted), +} - // invitations +impl From for WsMsg { + fn from(msg: WsMsgIssueStatus) -> Self { + WsMsg::IssueStatus(msg) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsgComment { + IssueCommentsLoad(IssueId), + IssueCommentsLoaded(Vec), + CommentCreate(CreateCommentPayload), + CommentCreated(Comment), + CommentUpdate(UpdateCommentPayload), + CommentUpdated(Comment), + CommentDelete(CommentId), + CommentDeleted(CommentId, NumberOfDeleted), +} + +impl From for WsMsg { + fn from(msg: WsMsgComment) -> Self { + WsMsg::Comment(msg) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsgInvitation { InvitationListLoad, InvitationListLoaded(Vec), // @@ -168,8 +201,35 @@ pub enum WsMsg { // InvitedUserRemoveRequest(UserId), InvitedUserRemoveSuccess(UserId), +} - // project page +impl From for WsMsg { + fn from(msg: WsMsgInvitation) -> Self { + WsMsg::Invitation(msg) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsgEpic { + EpicsLoad, + EpicsLoaded(Vec), + EpicCreate( + NameString, + Option, + Option, + ), + EpicCreated(Epic), + EpicUpdateName(EpicId, NameString), + EpicUpdateStartsAt(EpicId, Option), + EpicUpdateEndsAt(EpicId, Option), + EpicUpdated(Epic), + EpicDelete(EpicId), + EpicDeleted(EpicId, NumberOfDeleted), + EpicTransform(EpicId, IssueType), +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsgProject { ProjectsLoad, ProjectsLoaded(Vec), @@ -178,35 +238,49 @@ pub enum WsMsg { ProjectUsersLoad, ProjectUsersLoaded(Vec), ProjectUpdateLoad(UpdateProjectPayload), +} + +impl From for WsMsg { + fn from(msg: WsMsgProject) -> Self { + WsMsg::Project(msg) + } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum WsMsg { + Ping, + Pong, + Die, + + // auth + AuthorizeLoad(Uuid), + AuthorizeLoaded(Result<(User, UserSetting), String>), + AuthorizeExpired, + AuthenticateRequest(EmailString, UsernameString), + AuthenticateSuccess, + BindTokenCheck(Uuid), + BindTokenBad, + BindTokenOk(Uuid), + + // Sign up + SignUpRequest(EmailString, UsernameString), + SignUpSuccess, + SignUpPairTaken, + + // invitations + Invitation(WsMsgInvitation), + + // project page + Project(WsMsgProject), // issue - IssueUpdate(IssueId, IssueFieldId, PayloadVariant), - IssueUpdated(Issue), - IssueDelete(IssueId), - IssueDeleted(IssueId, NumberOfDeleted), - IssueCreate(CreateIssuePayload), - IssueCreated(Issue), - IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option)>), + Issue(WsMsgIssue), // issue status - IssueStatusesLoad, - IssueStatusesLoaded(Vec), - IssueStatusUpdate(IssueStatusId, TitleString, Position), - IssueStatusUpdated(IssueStatus), - IssueStatusCreate(TitleString, Position), - IssueStatusCreated(IssueStatus), - IssueStatusDelete(IssueStatusId), - IssueStatusDeleted(IssueStatusId, NumberOfDeleted), + IssueStatus(WsMsgIssueStatus), // comments - IssueCommentsLoad(IssueId), - IssueCommentsLoaded(Vec), - CommentCreate(CreateCommentPayload), - CommentCreated(Comment), - CommentUpdate(UpdateCommentPayload), - CommentUpdated(Comment), - CommentDelete(CommentId), - CommentDeleted(CommentId, NumberOfDeleted), + Comment(WsMsgComment), // users AvatarUrlChanged(UserId, AvatarUrl), @@ -231,21 +305,7 @@ pub enum WsMsg { MessageMarkedSeen(MessageId, NumberOfDeleted), // epics - EpicsLoad, - EpicsLoaded(Vec), - EpicCreate( - NameString, - Option, - Option, - ), - EpicCreated(Epic), - EpicUpdateName(EpicId, NameString), - EpicUpdateStartsAt(EpicId, Option), - EpicUpdateEndsAt(EpicId, Option), - EpicUpdated(Epic), - EpicDelete(EpicId), - EpicDeleted(EpicId, NumberOfDeleted), - EpicTransform(EpicId, IssueType), + Epic(WsMsgEpic), // highlight HighlightCode(Lang, Code),