From 87d2ea48a3c456f545ba9a47d60c6e7b36ca68d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Wo=C5=BAniak?= Date: Sat, 16 Jan 2021 14:31:31 +0100 Subject: [PATCH] Add delete epic modal --- actors/database-actor/src/issues.rs | 14 ++--- actors/websocket-actor/src/handlers/issues.rs | 8 ++- jirs-client/js/css/styledModal.scss | 56 +++++++++++++++++++ jirs-client/src/changes.rs | 10 ++-- jirs-client/src/lib.rs | 13 +++-- jirs-client/src/modals/debug/view.rs | 2 +- jirs-client/src/modals/epic_delete/mod.rs | 5 ++ jirs-client/src/modals/epic_delete/model.rs | 30 ++++++++++ jirs-client/src/modals/epic_delete/update.rs | 10 ++++ jirs-client/src/modals/epic_delete/view.rs | 55 ++++++++++++++++++ jirs-client/src/modals/issues_create/view.rs | 2 +- jirs-client/src/modals/issues_edit/model.rs | 4 +- jirs-client/src/modals/mod.rs | 1 + jirs-client/src/modals/time_tracking/view.rs | 11 +--- jirs-client/src/modals/update.rs | 22 ++++++-- jirs-client/src/modals/view.rs | 3 +- jirs-client/src/model.rs | 13 +++-- jirs-client/src/pages/project_page/model.rs | 6 +- .../src/pages/project_page/view/board.rs | 17 +++++- .../src/shared/styled_confirm_modal.rs | 12 +--- jirs-client/src/shared/styled_modal.rs | 27 ++++++--- jirs-client/src/ws/issue.rs | 6 +- shared/jirs-data/src/lib.rs | 11 ++-- shared/jirs-data/src/msg.rs | 7 +-- 24 files changed, 267 insertions(+), 78 deletions(-) create mode 100644 jirs-client/src/modals/epic_delete/mod.rs create mode 100644 jirs-client/src/modals/epic_delete/model.rs create mode 100644 jirs-client/src/modals/epic_delete/update.rs create mode 100644 jirs-client/src/modals/epic_delete/view.rs diff --git a/actors/database-actor/src/issues.rs b/actors/database-actor/src/issues.rs index 3bc0bdd4..b042e377 100644 --- a/actors/database-actor/src/issues.rs +++ b/actors/database-actor/src/issues.rs @@ -28,21 +28,21 @@ pub struct LoadProjectIssues { #[derive(Default, Execute)] #[db_exec(result = "Issue", schema = "issues")] pub struct UpdateIssue { - pub issue_id: i32, + pub issue_id: jirs_data::IssueId, pub title: Option, pub issue_type: Option, pub priority: Option, - pub list_position: Option, + pub list_position: Option, pub description: Option, pub description_text: Option, pub estimate: Option, pub time_spent: Option, pub time_remaining: Option, - pub project_id: Option, - pub user_ids: Option>, - pub reporter_id: Option, - pub issue_status_id: Option, - pub epic_id: Option>, + pub project_id: Option, + pub user_ids: Option>, + pub reporter_id: Option, + pub issue_status_id: Option, + pub epic_id: Option>, } impl UpdateIssue { diff --git a/actors/websocket-actor/src/handlers/issues.rs b/actors/websocket-actor/src/handlers/issues.rs index 96fac117..a67e51e4 100644 --- a/actors/websocket-actor/src/handlers/issues.rs +++ b/actors/websocket-actor/src/handlers/issues.rs @@ -1,4 +1,3 @@ -use jirs_data::{EpicId, IssueStatusId, ListPosition}; use { crate::{WebSocketActor, WsHandler, WsResult}, database_actor::{ @@ -6,7 +5,10 @@ use { issues::{LoadProjectIssues, UpdateIssue}, }, futures::executor::block_on, - jirs_data::{CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, PayloadVariant, WsMsg}, + jirs_data::{ + CreateIssuePayload, IssueAssignee, IssueFieldId, IssueId, IssueStatusId, ListPosition, + PayloadVariant, WsMsg, + }, std::collections::HashMap, }; @@ -257,7 +259,7 @@ impl WsHandler for WebSocketActor { } } -pub struct SyncIssueListPosition(pub Vec<(IssueId, ListPosition, IssueStatusId, Option)>); +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 { diff --git a/jirs-client/js/css/styledModal.scss b/jirs-client/js/css/styledModal.scss index 86267984..500ab2c1 100644 --- a/jirs-client/js/css/styledModal.scss +++ b/jirs-client/js/css/styledModal.scss @@ -108,6 +108,62 @@ &.debugModal { padding-left: 15px; } + + &.deleteEpic { + > section { + > .header { + background: var(--danger); + color: var(--secondary); + + padding: { + top: 15px; + right: 40px; + left: 40px; + bottom: 15px; + }; + } + + > .warning { + margin: { + bottom: 10px; + top: 10px; + } + + padding: { + right: 40px; + left: 40px; + }; + } + + > .relatedList { + list-style: none; + padding: { + right: 40px; + left: 40px; + bottom: 20px; + }; + + > li { + > .relatedIssue { + list-style: none; + line-height: 22px; + font-size: 14px; + + > a { + color: var(--textLink); + + .styledIcon.link { + font-size: 14px; + margin: { + right: 5px; + } + } + } + } + } + } + } + } } } } diff --git a/jirs-client/src/changes.rs b/jirs-client/src/changes.rs index 126327d9..5145bdb7 100644 --- a/jirs-client/src/changes.rs +++ b/jirs-client/src/changes.rs @@ -1,6 +1,6 @@ use seed::prelude::WebSocketMessage; -use jirs_data::{IssueId, IssueStatusId, WsMsg}; +use jirs_data::{EpicId, IssueStatusId, WsMsg}; use crate::shared::styled_editor::Mode as TabMode; use crate::FieldId; @@ -16,10 +16,10 @@ pub enum FieldChange { #[derive(Clone, Debug, PartialEq)] pub enum BoardPageChange { // dragging - IssueDragStarted(IssueId), - IssueDragStopped(IssueId), - DragLeave(IssueId), - ExchangePosition(IssueId), + IssueDragStarted(EpicId), + IssueDragStopped(EpicId), + DragLeave(EpicId), + ExchangePosition(EpicId), IssueDragOverStatus(IssueStatusId), IssueDropZone(IssueStatusId), } diff --git a/jirs-client/src/lib.rs b/jirs-client/src/lib.rs index 53eb7fbc..8992eb5a 100644 --- a/jirs-client/src/lib.rs +++ b/jirs-client/src/lib.rs @@ -104,7 +104,7 @@ pub enum Msg { // issues AddIssue, - DeleteIssue(IssueId), + DeleteIssue(EpicId), // epics AddEpic, @@ -237,7 +237,7 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders) { crate::modals::update(&msg, model, orders); match model.page { - Page::Project | Page::AddIssue | Page::EditIssue(..) => { + Page::Project | Page::AddIssue | Page::EditIssue(..) | Page::DeleteEpic(..) => { pages::project_page::update(msg, model, orders) } Page::ProjectSettings => pages::project_settings_page::update(msg, model, orders), @@ -255,8 +255,9 @@ fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders) { fn view(model: &model::Model) -> Node { match model.page { - Page::Project | Page::AddIssue => pages::project_page::view(model), - Page::EditIssue(_id) => pages::project_page::view(model), + Page::Project | Page::AddIssue | Page::DeleteEpic(..) | Page::EditIssue(..) => { + pages::project_page::view(model) + } Page::ProjectSettings => pages::project_settings_page::view(model), Page::SignIn => pages::sign_in_page::view(model), Page::SignUp => pages::sign_up_page::view(model), @@ -278,6 +279,10 @@ fn resolve_page(url: Url) -> Option { Some(Ok(id)) => Page::EditIssue(id), _ => return None, }, + "delete-epic" => match url.path().get(1).as_ref().map(|s| s.parse::()) { + Some(Ok(id)) => Page::DeleteEpic(id), + _ => return None, + }, "profile" => Page::Profile, "add-issue" => Page::AddIssue, "project-settings" => Page::ProjectSettings, diff --git a/jirs-client/src/modals/debug/view.rs b/jirs-client/src/modals/debug/view.rs index 5bf480df..d3242c09 100644 --- a/jirs-client/src/modals/debug/view.rs +++ b/jirs-client/src/modals/debug/view.rs @@ -14,7 +14,7 @@ pub fn view(model: &Model) -> Node { .width(1200) .add_class("debugModal") .center() - .children(vec![code]) + .children(vec![code].into_iter()) .build() .into_node() } diff --git a/jirs-client/src/modals/epic_delete/mod.rs b/jirs-client/src/modals/epic_delete/mod.rs new file mode 100644 index 00000000..aecce944 --- /dev/null +++ b/jirs-client/src/modals/epic_delete/mod.rs @@ -0,0 +1,5 @@ +pub use {model::*, update::*, view::*}; + +mod model; +mod update; +mod view; diff --git a/jirs-client/src/modals/epic_delete/model.rs b/jirs-client/src/modals/epic_delete/model.rs new file mode 100644 index 00000000..81792b09 --- /dev/null +++ b/jirs-client/src/modals/epic_delete/model.rs @@ -0,0 +1,30 @@ +use { + crate::model, + jirs_data::{EpicId, IssueId}, +}; + +#[derive(Clone, Debug, PartialOrd, PartialEq)] +pub struct Model { + pub epic_id: EpicId, + pub related_issues: Vec, +} + +impl Model { + pub fn new(issue_id: i32, model: &mut model::Model) -> Self { + let related_issues = model + .issues + .iter() + .filter_map(|issue| { + if issue.epic_id == Some(issue_id) { + Some(issue.id) + } else { + None + } + }) + .collect(); + Self { + epic_id: issue_id, + related_issues, + } + } +} diff --git a/jirs-client/src/modals/epic_delete/update.rs b/jirs-client/src/modals/epic_delete/update.rs new file mode 100644 index 00000000..7a5b8781 --- /dev/null +++ b/jirs-client/src/modals/epic_delete/update.rs @@ -0,0 +1,10 @@ +use { + crate::{shared::go_to_board, Msg}, + seed::prelude::*, +}; + +pub fn update(msg: &Msg, _model: &mut crate::model::Model, orders: &mut impl Orders) { + if let Msg::ModalDropped = msg { + go_to_board(orders); + }; +} diff --git a/jirs-client/src/modals/epic_delete/view.rs b/jirs-client/src/modals/epic_delete/view.rs new file mode 100644 index 00000000..007d12c9 --- /dev/null +++ b/jirs-client/src/modals/epic_delete/view.rs @@ -0,0 +1,55 @@ +use { + crate::{ + modals::epic_delete::Model, + model, + shared::{styled_confirm_modal::*, styled_icon::*, styled_modal::*, ToNode}, + Msg, + }, + seed::{prelude::*, *}, +}; + +pub fn view(model: &model::Model, modal: &Model) -> Node { + if modal.related_issues.is_empty() { + StyledConfirmModal::build() + .title("Delete empty epic") + .cancel_text("Cancel") + .confirm_text("Delete epic") + .build() + .into_node() + } else { + StyledModal::build() + .add_class("deleteEpic") + .center() + .width(600) + .child(warning(model, modal)) + .build() + .into_node() + } +} + +fn warning(model: &model::Model, modal: &Model) -> Node { + let issues: Vec> = modal + .related_issues + .iter() + .flat_map(|id| model.issues_by_id.get(id)) + .map(|issue| { + let link = StyledIcon::build(Icon::Link).build().into_node(); + li![div![ + C!["relatedIssue"], + a![ + attrs! {"href" => format!("/issues/{}", issue.id)}, + link, + issue.title.as_str() + ] + ]] + }) + .collect(); + section![ + h3![C!["header"], "Cannot delete epic"], + div![ + C!["warning"], + "This epic have related issues. Please move or delete them first." + ], + ol![C!["relatedList"], issues] + ] +} diff --git a/jirs-client/src/modals/issues_create/view.rs b/jirs-client/src/modals/issues_create/view.rs index 07fbe608..c07ef9ff 100644 --- a/jirs-client/src/modals/issues_create/view.rs +++ b/jirs-client/src/modals/issues_create/view.rs @@ -114,7 +114,7 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node { .add_class("addIssue") .width(0) .variant(crate::shared::styled_modal::Variant::Center) - .children(vec![form]) + .child(form) .build() .into_node() } diff --git a/jirs-client/src/modals/issues_edit/model.rs b/jirs-client/src/modals/issues_edit/model.rs index b1a916d5..0d2ef9e2 100644 --- a/jirs-client/src/modals/issues_edit/model.rs +++ b/jirs-client/src/modals/issues_edit/model.rs @@ -9,13 +9,13 @@ use { }, EditIssueModalSection, FieldId, Msg, }, - jirs_data::{Issue, IssueFieldId, IssueId, TimeTracking, UpdateIssuePayload}, + jirs_data::{EpicId, Issue, IssueFieldId, TimeTracking, UpdateIssuePayload}, seed::prelude::*, }; #[derive(Clone, Debug, PartialOrd, PartialEq)] pub struct Model { - pub id: IssueId, + pub id: EpicId, pub link_copied: bool, pub payload: UpdateIssuePayload, pub top_type_state: StyledSelectState, diff --git a/jirs-client/src/modals/mod.rs b/jirs-client/src/modals/mod.rs index f92ccc5e..ad8787f7 100644 --- a/jirs-client/src/modals/mod.rs +++ b/jirs-client/src/modals/mod.rs @@ -2,6 +2,7 @@ pub use {epic_field::*, update::*, view::*}; #[cfg(debug_assertions)] pub mod debug; +pub mod epic_delete; pub mod issue_statuses_delete; pub mod issues_create; pub mod issues_delete; diff --git a/jirs-client/src/modals/time_tracking/view.rs b/jirs-client/src/modals/time_tracking/view.rs index adb5274d..8ad8d338 100644 --- a/jirs-client/src/modals/time_tracking/view.rs +++ b/jirs-client/src/modals/time_tracking/view.rs @@ -12,7 +12,7 @@ use { }, EditIssueModalSection, FieldId, Msg, }, - jirs_data::{IssueFieldId, IssueId, TimeTracking}, + jirs_data::{EpicId, IssueFieldId, TimeTracking}, seed::{prelude::*, *}, }; @@ -25,7 +25,7 @@ pub fn value_for_time_tracking(v: &Option, time_tracking_type: &TimeTrackin } } -pub fn view(model: &Model, issue_id: IssueId) -> Node { +pub fn view(model: &Model, issue_id: EpicId) -> Node { if model.issues_by_id.get(&issue_id).is_none() { return Node::Empty; } @@ -73,12 +73,7 @@ pub fn view(model: &Model, issue_id: IssueId) -> Node { StyledModal::build() .add_class("timeTrackingModal") - .children(vec![ - modal_title, - tracking, - inputs, - div![C!["actions"], close], - ]) + .children(vec![modal_title, tracking, inputs, div![C!["actions"], close]].into_iter()) .width(400) .build() .into_node() diff --git a/jirs-client/src/modals/update.rs b/jirs-client/src/modals/update.rs index a38d3af2..6ffc6f52 100644 --- a/jirs-client/src/modals/update.rs +++ b/jirs-client/src/modals/update.rs @@ -43,6 +43,9 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { Msg::ChangePage(Page::EditIssue(issue_id)) => push_edit_modal(*issue_id, model, orders), Msg::ChangePage(Page::AddIssue) => push_add_modal(model, orders), + Msg::ChangePage(Page::DeleteEpic(issue_id)) => { + push_delete_epic_modal(*issue_id, model, orders) + } #[cfg(debug_assertions)] Msg::GlobalKeyDown { key, .. } if key.eq("#") => { @@ -61,10 +64,13 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders) { _ => (), } - use crate::modals::{issue_statuses_delete, issues_create, issues_edit}; - issues_create::update(msg, model, orders); - issues_edit::update(msg, model, orders); - issue_statuses_delete::update(msg, model, orders); + { + use crate::modals::*; + issues_create::update(msg, model, orders); + issues_edit::update(msg, model, orders); + issue_statuses_delete::update(msg, model, orders); + epic_delete::update(msg, model, orders); + } } fn push_add_modal(model: &mut Model, _orders: &mut impl Orders) { @@ -75,12 +81,18 @@ fn push_add_modal(model: &mut Model, _orders: &mut impl Orders) { }))); } +fn push_delete_epic_modal(issue_id: i32, model: &mut Model, _orders: &mut impl Orders) { + use crate::modals::epic_delete::Model; + let modal = Model::new(issue_id, model); + model.modals.push(ModalType::DeleteEpic(Box::new(modal))); +} + fn push_edit_modal(issue_id: i32, model: &mut Model, orders: &mut impl Orders) { let time_tracking_type = model .project .as_ref() .map(|p| p.time_tracking) - .unwrap_or_else(|| TimeTracking::Untracked); + .unwrap_or(TimeTracking::Untracked); let modal = { let issue = match model.issues_by_id.get(&issue_id) { Some(issue) => issue, diff --git a/jirs-client/src/modals/view.rs b/jirs-client/src/modals/view.rs index d4acadf1..0f0f515c 100644 --- a/jirs-client/src/modals/view.rs +++ b/jirs-client/src/modals/view.rs @@ -18,7 +18,7 @@ pub fn view(model: &Model) -> Node { StyledModal::build() .variant(crate::shared::styled_modal::Variant::Center) .width(1040) - .children(vec![details]) + .child(details) .build() .into_node() } else { @@ -45,6 +45,7 @@ pub fn view(model: &Model) -> Node { } #[cfg(debug_assertions)] ModalType::DebugModal => crate::modals::debug::view(model), + ModalType::DeleteEpic(modal) => crate::modals::epic_delete::view(model, modal), }) .collect(); section![id!["modals"], modals] diff --git a/jirs-client/src/model.rs b/jirs-client/src/model.rs index 8eb2aec0..299961ce 100644 --- a/jirs-client/src/model.rs +++ b/jirs-client/src/model.rs @@ -27,10 +27,11 @@ pub trait IssueModal { #[derive(Clone, Debug, PartialOrd, PartialEq)] pub enum ModalType { AddIssue(Box), - EditIssue(IssueId, Box), - DeleteIssueConfirm(IssueId), + EditIssue(EpicId, Box), + DeleteEpic(Box), + DeleteIssueConfirm(EpicId), DeleteCommentConfirm(CommentId), - TimeTracking(IssueId), + TimeTracking(EpicId), DeleteIssueStatusModal(Box), #[cfg(debug_assertions)] DebugModal, @@ -46,7 +47,8 @@ pub struct CommentForm { #[derive(Copy, Clone, Debug, PartialOrd, PartialEq)] pub enum Page { Project, - EditIssue(IssueId), + EditIssue(EpicId), + DeleteEpic(EpicId), AddIssue, ProjectSettings, SignIn, @@ -62,6 +64,7 @@ impl Page { match self { Page::Project => "/board".to_string(), Page::EditIssue(id) => format!("/issues/{id}", id = id), + Page::DeleteEpic(id) => format!("/delete-epic/{id}", id = id), Page::AddIssue => "/add-issue".to_string(), Page::ProjectSettings => "/project-settings".to_string(), Page::SignIn => "/login".to_string(), @@ -147,7 +150,7 @@ pub struct Model { pub current_user_project: Option, pub issues: Vec, - pub issues_by_id: HashMap, + pub issues_by_id: HashMap, pub user: Option, pub users: Vec, diff --git a/jirs-client/src/pages/project_page/model.rs b/jirs-client/src/pages/project_page/model.rs index a13bb699..192b6410 100644 --- a/jirs-client/src/pages/project_page/model.rs +++ b/jirs-client/src/pages/project_page/model.rs @@ -4,12 +4,12 @@ use {crate::shared::drag::DragState, jirs_data::*, std::collections::HashMap}; pub struct StatusIssueIds { pub status_id: IssueStatusId, pub status_name: IssueStatusName, - pub issue_ids: Vec, + pub issue_ids: Vec, } #[derive(Default, Debug)] pub struct EpicIssuePerStatus { - pub epic_name: Option, + pub epic_ref: Option<(EpicId, EpicName)>, pub per_status_issues: Vec, } @@ -57,7 +57,7 @@ impl ProjectPage { for epic in epics { let mut per_epic_map = EpicIssuePerStatus { - epic_name: epic.map(|(_, name)| name.to_string()), + epic_ref: epic.map(|(id, name)| (id, name.to_string())), ..Default::default() }; diff --git a/jirs-client/src/pages/project_page/view/board.rs b/jirs-client/src/pages/project_page/view/board.rs index 3d8a71d5..a5c389b9 100644 --- a/jirs-client/src/pages/project_page/view/board.rs +++ b/jirs-client/src/pages/project_page/view/board.rs @@ -1,4 +1,3 @@ -use crate::shared::styled_button::StyledButton; use { crate::{ model::PageContent, @@ -9,6 +8,8 @@ use { seed::{prelude::*, *}, }; +use crate::shared::styled_button::StyledButton; + pub fn project_board_lists(model: &Model) -> Node { let project_page = match &model.page_content { PageContent::Project(project_page) => project_page, @@ -32,8 +33,9 @@ pub fn project_board_lists(model: &Model) -> Node { ) }) .collect(); - let epic_name = match per_epic.epic_name.as_deref() { - Some(name) => { + let epic_name = match per_epic.epic_ref.as_ref() { + Some((id, name)) => { + let id = *id; let edit_button = StyledButton::build() .empty() .icon(Icon::EditAlt) @@ -42,6 +44,15 @@ pub fn project_board_lists(model: &Model) -> Node { let delete_button = StyledButton::build() .empty() .icon(Icon::DeleteAlt) + .on_click(mouse_ev("click", move |ev| { + ev.stop_propagation(); + ev.prevent_default(); + seed::Url::new() + .add_path_part("delete-epic") + .add_path_part(id.to_string()) + .go_and_push(); + Msg::ChangePage(Page::DeleteEpic(id)) + })) .build() .into_node(); diff --git a/jirs-client/src/shared/styled_confirm_modal.rs b/jirs-client/src/shared/styled_confirm_modal.rs index b5ea5cb3..8ff537c4 100644 --- a/jirs-client/src/shared/styled_confirm_modal.rs +++ b/jirs-client/src/shared/styled_confirm_modal.rs @@ -109,15 +109,9 @@ pub fn render(values: StyledConfirmModal) -> Node { StyledModal::build() .width(600) - .children(vec![ - div![attrs![At::Class => "title"], title], - message_node, - div![ - attrs![At::Class => "actions"], - confirm_button, - cancel_button - ], - ]) + .child(div![C!["title"], title]) + .child(message_node) + .child(div![C!["actions"], confirm_button, cancel_button]) .add_class("confirmModal") .build() .into_node() diff --git a/jirs-client/src/shared/styled_modal.rs b/jirs-client/src/shared/styled_modal.rs index 765c5b0d..514f9395 100644 --- a/jirs-client/src/shared/styled_modal.rs +++ b/jirs-client/src/shared/styled_modal.rs @@ -58,38 +58,48 @@ pub struct StyledModalBuilder<'l> { } impl<'l> StyledModalBuilder<'l> { + #[inline] pub fn variant(mut self, variant: Variant) -> Self { self.variant = Some(variant); self } + #[inline] pub fn center(self) -> Self { self.variant(Variant::Center) } + #[inline] pub fn width(mut self, width: usize) -> Self { self.width = Some(width); self } - // pub fn with_icon(mut self, with_icon: bool) -> Self { - // self.with_icon = Some(with_icon); - // self - // } - - pub fn children(mut self, children: Vec>) -> Self { - self.children = Some(children); + #[inline] + pub fn child(mut self, child: Node) -> Self { + self.children.get_or_insert(vec![]).push(child); self } + #[inline] + pub fn children(mut self, children: ChildIter) -> Self + where + ChildIter: Iterator>, + { + self.children.get_or_insert(vec![]).extend(children); + self + } + + #[inline] pub fn add_class(mut self, name: &'l str) -> Self { self.class_list.push(name); self } + #[inline] pub fn build(self) -> StyledModal<'l> { StyledModal { - variant: self.variant.unwrap_or_else(|| Variant::Center), + variant: self.variant.unwrap_or(Variant::Center), width: self.width, with_icon: self.with_icon.unwrap_or_default(), children: self.children.unwrap_or_default(), @@ -98,6 +108,7 @@ impl<'l> StyledModalBuilder<'l> { } } +#[inline] pub fn render(values: StyledModal) -> Node { let StyledModal { variant, diff --git a/jirs-client/src/ws/issue.rs b/jirs-client/src/ws/issue.rs index fa9b0430..6f73ba1a 100644 --- a/jirs-client/src/ws/issue.rs +++ b/jirs-client/src/ws/issue.rs @@ -8,7 +8,7 @@ use { seed::{prelude::Orders, *}, }; -pub fn drag_started(issue_id: IssueId, model: &mut Model) { +pub fn drag_started(issue_id: EpicId, model: &mut Model) { let project_page = match &mut model.page_content { PageContent::Project(project_page) => project_page, _ => return, @@ -16,7 +16,7 @@ pub fn drag_started(issue_id: IssueId, model: &mut Model) { project_page.issue_drag.drag(issue_id); } -pub fn exchange_position(below_id: IssueId, model: &mut Model) { +pub fn exchange_position(below_id: EpicId, model: &mut Model) { let project_page = match &mut model.page_content { PageContent::Project(project_page) => project_page, _ => return, @@ -88,7 +88,7 @@ pub fn sync(model: &mut Model, orders: &mut impl Orders) { _ => return, }; - let changes: Vec<(IssueId, ListPosition, IssueStatusId, Option)> = dirty + let changes: Vec<(EpicId, ListPosition, IssueStatusId, Option)> = dirty .into_iter() .filter_map(|id| { model.issues_by_id.get(&id).map(|issue| { diff --git a/shared/jirs-data/src/lib.rs b/shared/jirs-data/src/lib.rs index 56651b9e..72ae02f2 100644 --- a/shared/jirs-data/src/lib.rs +++ b/shared/jirs-data/src/lib.rs @@ -1,6 +1,8 @@ #[cfg(feature = "backend")] use diesel::*; +#[cfg(feature = "backend")] +use derive_enum_sql::EnumSql; use { chrono::NaiveDateTime, derive_enum_iter::EnumIter, @@ -16,9 +18,6 @@ pub mod fields; pub mod msg; mod payloads; -#[cfg(feature = "backend")] -use derive_enum_sql::EnumSql; - pub type NumberOfDeleted = usize; pub type IssueId = i32; pub type ListPosition = i32; @@ -223,7 +222,7 @@ pub struct Project { #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct Issue { - pub id: IssueId, + pub id: EpicId, pub title: String, pub issue_type: IssueType, pub priority: IssuePriority, @@ -275,7 +274,7 @@ pub struct Comment { pub id: CommentId, pub body: String, pub user_id: UserId, - pub issue_id: IssueId, + pub issue_id: EpicId, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, } @@ -320,7 +319,7 @@ pub struct Token { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct IssueAssignee { pub id: i32, - pub issue_id: IssueId, + pub issue_id: EpicId, pub user_id: UserId, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, diff --git a/shared/jirs-data/src/msg.rs b/shared/jirs-data/src/msg.rs index a45bc43e..82b46a97 100644 --- a/shared/jirs-data/src/msg.rs +++ b/shared/jirs-data/src/msg.rs @@ -1,10 +1,9 @@ -use crate::ListPosition; use { crate::{ AvatarUrl, BindToken, Code, Comment, CommentId, CreateCommentPayload, CreateIssuePayload, EmailString, Epic, EpicId, HighlightedCode, Invitation, InvitationId, InvitationToken, - Issue, IssueFieldId, IssueId, IssueStatus, IssueStatusId, Lang, Message, MessageId, - NameString, NumberOfDeleted, PayloadVariant, Position, Project, TitleString, + Issue, IssueFieldId, IssueId, IssueStatus, IssueStatusId, Lang, ListPosition, Message, + MessageId, NameString, NumberOfDeleted, PayloadVariant, Position, Project, TitleString, UpdateCommentPayload, UpdateProjectPayload, User, UserId, UserProject, UserProjectId, UserRole, UsernameString, }, @@ -187,7 +186,7 @@ pub enum WsMsg { IssueDeleted(IssueId, NumberOfDeleted), IssueCreate(CreateIssuePayload), IssueCreated(Issue), - IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option)>), + IssueSyncListPosition(Vec<(IssueId, ListPosition, IssueStatusId, Option)>), // issue status IssueStatusesLoad,