diff --git a/jirs-client/src/modal/add_issue.rs b/jirs-client/src/modal/add_issue.rs index 6b2cecff..8585ecad 100644 --- a/jirs-client/src/modal/add_issue.rs +++ b/jirs-client/src/modal/add_issue.rs @@ -7,6 +7,7 @@ use crate::shared::styled_button::StyledButton; use crate::shared::styled_field::StyledField; use crate::shared::styled_form::StyledForm; use crate::shared::styled_icon::{Icon, StyledIcon}; +use crate::shared::styled_input::StyledInput; use crate::shared::styled_modal::{StyledModal, Variant as ModalVariant}; use crate::shared::styled_select::StyledSelect; use crate::shared::ToNode; @@ -34,6 +35,18 @@ pub fn view(_model: &Model, modal: &AddIssueModal) -> Node { .build() .into_node(); + let short_summary = StyledInput::build() + .id("issue-short-summary") + .valid(true) + .build() + .into_node(); + let short_summary_field = StyledField::build() + .label("Short Summary") + .tip("Concisely summarize the issue in one or two sentences.") + .input(short_summary) + .build() + .into_node(); + let submit = StyledButton::build() .primary() .text("Create Issue") @@ -52,6 +65,7 @@ pub fn view(_model: &Model, modal: &AddIssueModal) -> Node { .heading("Create issue") .add_field(issue_type_field) .add_field(crate::shared::divider()) + .add_field(short_summary_field) .add_field(actions) .build() .into_node(); diff --git a/jirs-client/src/project.rs b/jirs-client/src/project.rs index 3edfead5..12726fda 100644 --- a/jirs-client/src/project.rs +++ b/jirs-client/src/project.rs @@ -172,13 +172,15 @@ fn header() -> Node { } fn project_board_filters(model: &Model) -> Node { - let search_input = StyledInput { - icon: Some(Icon::Search), - id: Some("searchInput".to_string()), - valid: true, - on_change: input_ev(Ev::Change, |value| Msg::ProjectTextFilterChanged(value)), - } - .into_node(); + let search_input = StyledInput::build() + .icon(Icon::Search) + .id("searchInput") + .valid(true) + .on_change(input_ev(Ev::Change, |value| { + Msg::ProjectTextFilterChanged(value) + })) + .build() + .into_node(); let project_page = &model.project_page; diff --git a/jirs-client/src/shared/styled_input.rs b/jirs-client/src/shared/styled_input.rs index 4928b9d2..478226a3 100644 --- a/jirs-client/src/shared/styled_input.rs +++ b/jirs-client/src/shared/styled_input.rs @@ -4,11 +4,60 @@ use crate::shared::styled_icon::{Icon, StyledIcon}; use crate::shared::ToNode; use crate::Msg; +#[derive(Debug)] pub struct StyledInput { - pub id: Option, - pub icon: Option, - pub valid: bool, - pub on_change: EventHandler, + id: Option, + icon: Option, + valid: bool, + on_change: Option>, +} + +impl StyledInput { + pub fn build() -> StyledInputBuilder { + StyledInputBuilder::default() + } +} + +#[derive(Default, Debug)] +pub struct StyledInputBuilder { + id: Option, + icon: Option, + valid: Option, + on_change: Option>, +} + +impl StyledInputBuilder { + pub fn id(mut self, id: S) -> Self + where + S: Into, + { + self.id = Some(id.into()); + self + } + + pub fn icon(mut self, icon: Icon) -> Self { + self.icon = Some(icon); + self + } + + pub fn valid(mut self, valid: bool) -> Self { + self.valid = Some(valid); + self + } + + pub fn on_change(mut self, on_change: EventHandler) -> Self { + self.on_change = Some(on_change); + self + } + + pub fn build(self) -> StyledInput { + StyledInput { + id: self.id, + icon: self.icon, + valid: self.valid.unwrap_or_default(), + on_change: self.on_change, + } + } } impl ToNode for StyledInput { @@ -40,10 +89,15 @@ pub fn render(values: StyledInput) -> Node { _ => empty![], }; + let input_node = match on_change { + Some(on_change) => seed::input![attrs![At::Class => input_class_list.join(" ")], on_change], + _ => seed::input![attrs![At::Class => input_class_list.join(" ")]], + }; + div![ id![id.unwrap_or_default()], attrs!(At::Class => wrapper_class_list.join(" ")), icon, - input![attrs![At::Class => input_class_list.join(" ")], on_change] + input_node, ] }