use seed::{prelude::*, *}; use jirs_data::{Issue, IssueType}; use crate::model::{EditIssueModal, ModalType, Model}; use crate::shared::styled_button::StyledButton; use crate::shared::styled_icon::{Icon, StyledIcon}; use crate::shared::styled_select::StyledSelect; use crate::shared::ToNode; use crate::{FieldChange, FieldId, IssueId, Msg}; pub fn view(_model: &Model, issue: &Issue, modal: &EditIssueModal) -> Node { let issue_id = issue.id; let issue_type_select = StyledSelect::build(FieldId::IssueTypeEditModalTop) .dropdown_width(150) .name("type") .text_filter(modal.top_select_filter.as_str()) .opened(modal.top_select_opened) .valid(true) .options(vec![ IssueTypeOption(issue_id, IssueType::Story), IssueTypeOption(issue_id, IssueType::Task), IssueTypeOption(issue_id, IssueType::Bug), ]) .selected(vec![IssueTypeOption(issue_id, modal.value.clone())]) .build() .into_node(); let click_handler = mouse_ev(Ev::Click, move |_| { use wasm_bindgen::JsCast; let link = format!("http://localhost:7000/issues/{id}", id = issue_id); let el = match seed::html_document().create_element("textarea") { Ok(el) => el .dyn_ref::() .unwrap() .clone(), _ => return Msg::NoOp, }; seed::body().append_child(&el).unwrap(); el.set_text_content(Some(link.as_str())); el.select(); el.set_selection_range(0, 9999).unwrap(); seed::html_document().exec_command("copy").unwrap(); seed::body().remove_child(&el).unwrap(); Msg::ModalChanged(FieldChange::LinkCopied(FieldId::CopyButtonLabel, true)) }); let close_handler = mouse_ev(Ev::Click, |_| Msg::ModalDropped); let delete_confirmation_handler = mouse_ev(Ev::Click, move |_| { Msg::ModalOpened(ModalType::DeleteIssueConfirm(issue_id)) }); let copy_button = StyledButton::build() .empty() .icon(Icon::Link) .on_click(click_handler) .children(vec![span![if modal.link_copied { "Link Copied" } else { "Copy link" }]]) .build() .into_node(); let delete_button = StyledButton::build() .empty() .icon(Icon::Trash.into_styled_builder().size(19).build()) .on_click(delete_confirmation_handler) .build() .into_node(); let close_button = StyledButton::build() .empty() .icon(Icon::Close.into_styled_builder().size(24).build()) .on_click(close_handler) .build() .into_node(); div![ attrs![At::Class => "issueDetails"], div![ attrs![At::Class => "topActions"], issue_type_select, div![ attrs![At::Class => "topActionsRight"], copy_button, delete_button, close_button ], ], div![ attrs![At::Class => "content"], div![ attrs![At::Class => "left"], div![attrs![At::Class => "title"]], div![attrs![At::Class => "description"]], div![attrs![At::Class => "comments"]], ], div![attrs![At::Class => "right"]], ], ] } #[derive(PartialOrd, PartialEq, Debug)] pub struct IssueTypeOption(pub IssueId, pub IssueType); impl crate::shared::styled_select::SelectOption for IssueTypeOption { fn into_option(self) -> Node { let name = self.1.to_label().to_owned(); let icon = StyledIcon::build(self.1.into()) .add_class("issueTypeIcon".to_string()) .build() .into_node(); div![ attrs![At::Class => "type"], icon, div![attrs![At::Class => "typeLabel"], name] ] } fn into_value(self) -> Node { let issue_id = self.0; let name = self.1.to_label().to_owned(); StyledButton::build() .empty() .children(vec![span![format!("{}-{}", name, issue_id)]]) .icon(StyledIcon::build(self.1.into()).build()) .build() .into_node() } fn match_text_filter(&self, text_filter: &str) -> bool { self.1 .to_string() .to_lowercase() .contains(&text_filter.to_lowercase()) } fn to_value(&self) -> u32 { self.1.clone().into() } }