Delete issue status full logic

This commit is contained in:
Adrian Wozniak 2020-05-10 13:10:31 +02:00
parent b2cbb251d1
commit 4d07639e90
10 changed files with 148 additions and 21 deletions

View File

@ -0,0 +1,3 @@
.deleteIssueStatus {
min-width: 800px;
}

View File

@ -55,3 +55,21 @@
text-align: center;
cursor: pointer;
}
#projectSettings > .formContainer .styledForm > .formElement > .styledField > .columnsSection > .columns > .columnPreview > .columnName > .removeColumn {
text-align: center;
display: flex;
justify-content: space-around;
padding-top: 15px;
}
#projectSettings > .formContainer .styledForm > .formElement > .styledField > .columnsSection > .columns > .columnPreview:hover > .columnName > .removeColumn,
#projectSettings > .formContainer .styledForm > .formElement > .styledField > .columnsSection > .columns > .columnPreview:focus > .columnName > .removeColumn,
#projectSettings > .formContainer .styledForm > .formElement > .styledField > .columnsSection > .columns > .columnPreview:active > .columnName > .removeColumn {
}
#projectSettings > .formContainer .styledForm > .formElement > .styledField > .columnsSection > .columns > .columnPreview > .columnName > .issueCount {
text-transform: none;
padding-top: 15px;
}

View File

@ -67,7 +67,7 @@
--font-black: "CircularStdBlack";
}
:root {
:root { /* user without avatar */
--avatar-color-1: rgb(218, 118, 87);
--avatar-color-2: rgb(106, 218, 87);
--avatar-color-3: rgb(87, 132, 218);

View File

@ -240,6 +240,9 @@ pub enum Msg {
AddIssue,
DeleteIssue(IssueId),
// issue statuses
DeleteIssueStatus(IssueStatusId),
// comments
SaveComment,
DeleteComment(CommentId),

View File

@ -0,0 +1,43 @@
use seed::prelude::*;
use jirs_data::{IssueStatusId, WsMsg};
use crate::api::send_ws_msg;
use crate::model::{DeleteIssueStatusModal, ModalType, Model};
use crate::shared::styled_confirm_modal::StyledConfirmModal;
use crate::shared::ToNode;
use crate::{model, Msg};
pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
let _modal: &mut Box<DeleteIssueStatusModal> =
match model.modals.iter_mut().find_map(|modal| match modal {
ModalType::DeleteIssueStatusModal(modal) => Some(modal),
_ => None,
}) {
Some(m) => m,
_ => return,
};
match msg {
Msg::DeleteIssueStatus(issue_status_id) => {
send_ws_msg(WsMsg::IssueStatusDelete(*issue_status_id));
}
Msg::WsMsg(WsMsg::IssueStatusDelete(_)) => {
orders.skip().perform_cmd(Msg::ModalDropped);
}
_ => (),
};
}
pub fn view(_model: &model::Model, issue_status_id: IssueStatusId) -> Node<Msg> {
StyledConfirmModal::build()
.title("Delete column")
.cancel_text("No")
.confirm_text("Yes")
.on_confirm(mouse_ev(Ev::Click, move |_| {
Msg::DeleteIssueStatus(issue_status_id)
}))
.message("Are you sure you want to delete column?")
.build()
.into_node()
}

View File

@ -292,10 +292,10 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
pub fn view(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
div![
attrs![At::Class => "issueDetails"],
class!["issueDetails"],
top_modal_row(model, modal),
div![
attrs![At::Class => "content"],
class!["content"],
left_modal_column(model, modal),
right_modal_column(model, modal),
],

View File

@ -11,6 +11,7 @@ use crate::{model, FieldChange, FieldId, Msg};
mod add_issue;
mod confirm_delete_issue;
mod delete_issue_status;
mod issue_details;
pub mod time_tracking;
@ -57,6 +58,7 @@ pub fn update(msg: &Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>
}
add_issue::update(msg, model, orders);
issue_details::update(msg, model, orders);
delete_issue_status::update(msg, model, orders);
}
pub fn view(model: &model::Model) -> Node<Msg> {
@ -90,6 +92,9 @@ pub fn view(model: &model::Model) -> Node<Msg> {
.into_node()
}
ModalType::TimeTracking(issue_id) => time_tracking::view(model, *issue_id),
ModalType::DeleteIssueStatusModal(delete_issue_modal) => {
delete_issue_status::view(model, delete_issue_modal.delete_id)
}
})
.collect();
section![id!["modals"], modals]

View File

@ -21,6 +21,7 @@ pub enum ModalType {
DeleteIssueConfirm(IssueId),
DeleteCommentConfirm(CommentId),
TimeTracking(IssueId),
DeleteIssueStatusModal(Box<DeleteIssueStatusModal>),
}
#[derive(Clone, Debug, PartialOrd, PartialEq)]
@ -30,9 +31,24 @@ pub struct CommentForm {
pub creating: bool,
}
#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct DeleteIssueStatusModal {
pub delete_id: IssueStatusId,
pub receiver_id: Option<IssueStatusId>,
}
impl DeleteIssueStatusModal {
pub fn new(delete_id: IssueStatusId) -> Self {
Self {
delete_id,
receiver_id: None,
}
}
}
#[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct EditIssueModal {
pub id: i32,
pub id: IssueId,
pub link_copied: bool,
pub payload: UpdateIssuePayload,
pub top_type_state: StyledSelectState,

View File

@ -1,11 +1,14 @@
use seed::{prelude::*, *};
use wasm_bindgen::__rt::std::collections::HashMap;
use jirs_data::{
IssueStatus, IssueStatusId, ProjectCategory, TimeTracking, ToVec, UpdateProjectPayload, WsMsg,
};
use crate::api::send_ws_msg;
use crate::model::{Model, Page, PageContent, ProjectSettingsPage};
use crate::model::{
DeleteIssueStatusModal, ModalType, Model, Page, PageContent, ProjectSettingsPage,
};
use crate::shared::styled_button::StyledButton;
use crate::shared::styled_checkbox::StyledCheckbox;
use crate::shared::styled_editor::StyledEditor;
@ -31,12 +34,14 @@ pub fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>)
Msg::WsMsg(WsMsg::AuthorizeLoaded(..)) => {
send_ws_msg(WsMsg::ProjectRequest);
send_ws_msg(WsMsg::IssueStatusesRequest);
send_ws_msg(WsMsg::ProjectIssuesRequest);
}
Msg::ChangePage(Page::ProjectSettings) => {
build_page_content(model);
if model.user.is_some() {
send_ws_msg(WsMsg::ProjectRequest);
send_ws_msg(WsMsg::IssueStatusesRequest);
send_ws_msg(WsMsg::ProjectIssuesRequest);
}
}
Msg::WsMsg(WsMsg::ProjectLoaded(..)) => {
@ -245,6 +250,12 @@ pub fn view(model: &model::Model) -> Node<Msg> {
let width = 100f64 / (model.issue_statuses.len() + 1) as f64;
let column_style = format!("width: calc({width}% - 10px)", width = width);
let mut per_column_issue_count = HashMap::new();
for issue in model.issues.iter() {
*per_column_issue_count
.entry(issue.issue_status_id)
.or_insert(0) += 1;
}
let columns: Vec<Node<Msg>> = model
.issue_statuses
.iter()
@ -284,21 +295,40 @@ pub fn view(model: &model::Model) -> Node<Msg> {
.into_node();
div![
class!["columnPreview"],
div![class!["columnName"], input]
class!["columnPreview"],
div![class!["columnName"], input]
]
} else {
let edit = mouse_ev(Ev::Click, move |_| {
let on_edit = mouse_ev(Ev::Click, move |_| {
Msg::PageChanged(PageChanged::ProjectSettings(ProjectPageChange::EditIssueStatusName(Some(id))))
});
let issue_count_in_column = per_column_issue_count.get(&id).cloned().unwrap_or_default();
let delete_row = if issue_count_in_column == 0 {
let on_delete = mouse_ev(Ev::Click, move |ev| {
ev.prevent_default();
ev.stop_propagation();
Msg::ModalOpened(Box::new(ModalType::DeleteIssueStatusModal(Box::new(DeleteIssueStatusModal::new(id)))))
});
let delete = StyledButton::build()
.primary()
.add_class("removeColumn")
.icon(Icon::Trash)
.on_click(on_delete)
.build()
.into_node();
div![class!["removeColumn"], delete]
} else {
div![class!["issueCount"], format!("Issues in column: {}", issue_count_in_column)]
};
div![
class!["columnPreview"],
attrs![At::Style => column_style.as_str(), At::Draggable => "true", At::DropZone => "true"],
div![class!["columnName"], span![is.name], edit],
drag_started,
drag_stopped,
drag_over_handler,
drag_out,
class!["columnPreview"],
attrs![At::Style => column_style.as_str(), At::Draggable => "true", At::DropZone => "true"],
div![class!["columnName"], span![is.name], on_edit, delete_row],
drag_started,
drag_stopped,
drag_over_handler,
drag_out,
]
}
})
@ -352,7 +382,12 @@ pub fn view(model: &model::Model) -> Node<Msg> {
let project_section = vec![div![class!["formContainer"], form]];
inner_layout(model, "projectSettings", project_section, empty![])
inner_layout(
model,
"projectSettings",
project_section,
crate::modal::view(model),
)
}
fn exchange_position(bellow_id: IssueStatusId, model: &mut Model) {

View File

@ -29,11 +29,11 @@ impl Variant {
#[derive(Debug)]
pub struct StyledModal {
pub variant: Variant,
pub width: usize,
pub with_icon: bool,
pub children: Vec<Node<Msg>>,
pub class_list: Vec<String>,
variant: Variant,
width: usize,
with_icon: bool,
children: Vec<Node<Msg>>,
class_list: Vec<String>,
}
impl ToNode for StyledModal {
@ -63,6 +63,10 @@ impl StyledModalBuilder {
self
}
// pub fn center(mut self) -> Self {
// self.variant(Variant::Center)
// }
pub fn width(mut self, width: usize) -> Self {
self.width = Some(width);
self