2020-04-02 23:51:29 +02:00
|
|
|
use seed::{prelude::*, *};
|
|
|
|
|
2020-04-10 22:33:07 +02:00
|
|
|
use jirs_data::*;
|
2020-04-02 23:51:29 +02:00
|
|
|
|
2020-04-10 22:33:07 +02:00
|
|
|
use crate::api::send_ws_msg;
|
2020-04-03 16:15:56 +02:00
|
|
|
use crate::model::{EditIssueModal, ModalType, Model};
|
2020-04-09 16:03:11 +02:00
|
|
|
use crate::shared::styled_avatar::StyledAvatar;
|
2020-04-02 23:51:29 +02:00
|
|
|
use crate::shared::styled_button::StyledButton;
|
2020-04-10 08:09:40 +02:00
|
|
|
use crate::shared::styled_editor::StyledEditor;
|
2020-04-09 16:03:11 +02:00
|
|
|
use crate::shared::styled_field::StyledField;
|
2020-04-12 13:21:47 +02:00
|
|
|
use crate::shared::styled_icon::Icon;
|
2020-04-10 22:33:07 +02:00
|
|
|
use crate::shared::styled_input::StyledInput;
|
2020-04-12 13:21:47 +02:00
|
|
|
use crate::shared::styled_select::{StyledSelect, StyledSelectChange};
|
|
|
|
use crate::shared::styled_select_child::ToStyledSelectChild;
|
2020-04-09 16:03:11 +02:00
|
|
|
use crate::shared::styled_textarea::StyledTextarea;
|
2020-04-02 23:51:29 +02:00
|
|
|
use crate::shared::ToNode;
|
2020-04-12 13:21:47 +02:00
|
|
|
use crate::{EditIssueModalFieldId, FieldChange, FieldId, Msg};
|
2020-04-02 23:51:29 +02:00
|
|
|
|
2020-04-09 16:03:11 +02:00
|
|
|
pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
|
|
|
let modal: &mut EditIssueModal = match model.modals.get_mut(0) {
|
|
|
|
Some(ModalType::EditIssue(_issue_id, modal)) => modal,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
modal.top_type_state.update(msg, orders);
|
|
|
|
modal.status_state.update(msg, orders);
|
|
|
|
modal.reporter_state.update(msg, orders);
|
|
|
|
modal.assignees_state.update(msg, orders);
|
|
|
|
modal.priority_state.update(msg, orders);
|
2020-04-10 08:09:40 +02:00
|
|
|
|
|
|
|
match msg {
|
2020-04-10 22:33:07 +02:00
|
|
|
Msg::WsMsg(WsMsg::IssueUpdated(issue)) => {
|
|
|
|
modal.payload = issue.clone().into();
|
|
|
|
}
|
2020-04-10 08:09:40 +02:00
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::IssueType),
|
2020-04-10 08:09:40 +02:00
|
|
|
StyledSelectChange::Changed(value),
|
|
|
|
) => {
|
|
|
|
modal.payload.issue_type = (*value).into();
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Status),
|
2020-04-10 08:09:40 +02:00
|
|
|
StyledSelectChange::Changed(value),
|
|
|
|
) => {
|
|
|
|
modal.payload.status = (*value).into();
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Reporter),
|
2020-04-10 08:09:40 +02:00
|
|
|
StyledSelectChange::Changed(value),
|
|
|
|
) => {
|
|
|
|
modal.payload.reporter_id = *value as i32;
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Assignees),
|
2020-04-10 08:09:40 +02:00
|
|
|
StyledSelectChange::Changed(value),
|
|
|
|
) => {
|
|
|
|
modal.payload.user_ids.push(*value as i32);
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
|
|
|
}
|
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Assignees),
|
2020-04-10 22:33:07 +02:00
|
|
|
StyledSelectChange::RemoveMulti(value),
|
|
|
|
) => {
|
|
|
|
let mut old = vec![];
|
|
|
|
std::mem::swap(&mut old, &mut modal.payload.user_ids);
|
|
|
|
let dropped = *value as i32;
|
|
|
|
for id in old.into_iter() {
|
|
|
|
if id != dropped {
|
|
|
|
modal.payload.user_ids.push(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
|
|
|
Msg::StyledSelectChanged(
|
2020-04-12 13:21:47 +02:00
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Priority),
|
2020-04-10 08:09:40 +02:00
|
|
|
StyledSelectChange::Changed(value),
|
|
|
|
) => {
|
|
|
|
modal.payload.priority = (*value).into();
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
2020-04-12 13:21:47 +02:00
|
|
|
Msg::InputChanged(FieldId::EditIssueModal(EditIssueModalFieldId::Title), value) => {
|
2020-04-10 08:09:40 +02:00
|
|
|
modal.payload.title = value.clone();
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
2020-04-12 13:21:47 +02:00
|
|
|
Msg::InputChanged(FieldId::EditIssueModal(EditIssueModalFieldId::Description), value) => {
|
2020-04-10 08:09:40 +02:00
|
|
|
modal.payload.description = Some(value.clone());
|
|
|
|
modal.payload.description_text = Some(value.clone());
|
2020-04-10 22:33:07 +02:00
|
|
|
send_ws_msg(WsMsg::IssueUpdateRequest(modal.id, modal.payload.clone()));
|
2020-04-10 08:09:40 +02:00
|
|
|
}
|
2020-04-12 13:21:47 +02:00
|
|
|
Msg::ModalChanged(FieldChange::TabChanged(
|
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::Description),
|
|
|
|
mode,
|
|
|
|
)) => {
|
2020-04-10 08:09:40 +02:00
|
|
|
modal.description_editor_mode = mode.clone();
|
|
|
|
}
|
2020-04-12 13:21:47 +02:00
|
|
|
Msg::ModalChanged(FieldChange::ToggleCreateComment(
|
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::CommentBody),
|
|
|
|
flag,
|
|
|
|
)) => {
|
|
|
|
modal.creating_comment = *flag;
|
|
|
|
}
|
|
|
|
Msg::GlobalKeyDown { key, .. } if key.as_str() == "m" && !modal.creating_comment => {
|
|
|
|
orders
|
|
|
|
.skip()
|
|
|
|
.send_msg(Msg::ModalChanged(FieldChange::ToggleCreateComment(
|
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::CommentBody),
|
|
|
|
true,
|
|
|
|
)));
|
|
|
|
}
|
2020-04-10 08:09:40 +02:00
|
|
|
|
|
|
|
_ => (),
|
|
|
|
}
|
2020-04-09 16:03:11 +02:00
|
|
|
}
|
|
|
|
|
2020-04-10 08:09:40 +02:00
|
|
|
pub fn view(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
2020-04-12 13:21:47 +02:00
|
|
|
div![
|
|
|
|
attrs![At::Class => "issueDetails"],
|
|
|
|
top_modal_row(model, modal),
|
|
|
|
div![
|
|
|
|
attrs![At::Class => "content"],
|
|
|
|
left_modal_column(model, modal),
|
|
|
|
right_modal_column(model, modal),
|
|
|
|
],
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn top_modal_row(_model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
2020-04-10 08:09:40 +02:00
|
|
|
let EditIssueModal {
|
|
|
|
id,
|
|
|
|
payload,
|
|
|
|
top_type_state,
|
2020-04-12 13:21:47 +02:00
|
|
|
link_copied,
|
|
|
|
..
|
2020-04-10 08:09:40 +02:00
|
|
|
} = modal;
|
2020-04-02 23:51:29 +02:00
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let issue_id = id.clone();
|
2020-04-02 23:51:29 +02:00
|
|
|
|
|
|
|
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::<web_sys::HtmlTextAreaElement>()
|
|
|
|
.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();
|
2020-04-03 16:15:56 +02:00
|
|
|
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))
|
2020-04-02 23:51:29 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
let copy_button = StyledButton::build()
|
|
|
|
.empty()
|
|
|
|
.icon(Icon::Link)
|
|
|
|
.on_click(click_handler)
|
2020-04-10 08:09:40 +02:00
|
|
|
.children(vec![span![if *link_copied {
|
2020-04-02 23:51:29 +02:00
|
|
|
"Link Copied"
|
|
|
|
} else {
|
|
|
|
"Copy link"
|
|
|
|
}]])
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-03 08:51:25 +02:00
|
|
|
let delete_button = StyledButton::build()
|
|
|
|
.empty()
|
|
|
|
.icon(Icon::Trash.into_styled_builder().size(19).build())
|
2020-04-03 16:15:56 +02:00
|
|
|
.on_click(delete_confirmation_handler)
|
2020-04-03 08:51:25 +02:00
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-02 23:51:29 +02:00
|
|
|
let close_button = StyledButton::build()
|
|
|
|
.empty()
|
2020-04-03 08:51:25 +02:00
|
|
|
.icon(Icon::Close.into_styled_builder().size(24).build())
|
2020-04-03 14:40:21 +02:00
|
|
|
.on_click(close_handler)
|
2020-04-02 23:51:29 +02:00
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let issue_type_select =
|
|
|
|
StyledSelect::build(FieldId::EditIssueModal(EditIssueModalFieldId::IssueType))
|
|
|
|
.dropdown_width(150)
|
|
|
|
.name("type")
|
|
|
|
.text_filter(top_type_state.text_filter.as_str())
|
|
|
|
.opened(top_type_state.opened)
|
|
|
|
.valid(true)
|
|
|
|
.options(
|
|
|
|
IssueType::ordered()
|
|
|
|
.into_iter()
|
|
|
|
.map(|t| t.to_select_child().name("type"))
|
|
|
|
.collect(),
|
|
|
|
)
|
|
|
|
.selected(vec![{
|
|
|
|
let id = modal.id.clone();
|
|
|
|
let issue_type = &payload.issue_type;
|
|
|
|
issue_type
|
|
|
|
.to_select_child()
|
|
|
|
.name("type")
|
|
|
|
.text(format!("{} - {}", issue_type, id))
|
|
|
|
}])
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
|
|
|
div![
|
|
|
|
attrs![At::Class => "topActions"],
|
|
|
|
issue_type_select,
|
|
|
|
div![
|
|
|
|
attrs![At::Class => "topActionsRight"],
|
|
|
|
copy_button,
|
|
|
|
delete_button,
|
|
|
|
close_button
|
|
|
|
],
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn left_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
|
|
|
let EditIssueModal {
|
|
|
|
payload,
|
|
|
|
description_editor_mode,
|
|
|
|
creating_comment,
|
|
|
|
..
|
|
|
|
} = modal;
|
|
|
|
|
2020-04-09 16:03:11 +02:00
|
|
|
let title = StyledTextarea::build()
|
2020-04-10 08:09:40 +02:00
|
|
|
.value(payload.title.as_str())
|
2020-04-09 16:03:11 +02:00
|
|
|
.add_class("textarea")
|
|
|
|
.max_height(48)
|
|
|
|
.height(0)
|
2020-04-12 13:21:47 +02:00
|
|
|
.build(FieldId::EditIssueModal(EditIssueModalFieldId::Title))
|
2020-04-09 16:03:11 +02:00
|
|
|
.into_node();
|
|
|
|
|
2020-04-10 08:09:40 +02:00
|
|
|
let description_text = payload.description.as_ref().cloned().unwrap_or_default();
|
2020-04-12 13:21:47 +02:00
|
|
|
let description =
|
|
|
|
StyledEditor::build(FieldId::EditIssueModal(EditIssueModalFieldId::Description))
|
|
|
|
.text(description_text)
|
|
|
|
.mode(description_editor_mode.clone())
|
|
|
|
.update_on(Ev::Change)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let description_field = StyledField::build().input(description).build().into_node();
|
|
|
|
|
|
|
|
let user_avatar = StyledAvatar::build()
|
|
|
|
.add_class("userAvatar")
|
|
|
|
.size(32)
|
|
|
|
.avatar_url(
|
|
|
|
model
|
|
|
|
.user
|
|
|
|
.as_ref()
|
|
|
|
.and_then(|u| u.avatar_url.clone())
|
|
|
|
.unwrap_or_default(),
|
|
|
|
)
|
2020-04-10 08:09:40 +02:00
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let create_comment = if *creating_comment {
|
|
|
|
let text_area = StyledTextarea::build()
|
|
|
|
.build(FieldId::EditIssueModal(EditIssueModalFieldId::CommentBody))
|
|
|
|
.into_node();
|
|
|
|
div![text_area]
|
|
|
|
} else {
|
|
|
|
let creating_comment = *creating_comment;
|
|
|
|
let handler = mouse_ev(Ev::Click, move |ev| {
|
|
|
|
ev.stop_propagation();
|
|
|
|
Msg::ModalChanged(FieldChange::ToggleCreateComment(
|
|
|
|
FieldId::EditIssueModal(EditIssueModalFieldId::CommentBody),
|
|
|
|
!creating_comment,
|
|
|
|
))
|
|
|
|
});
|
|
|
|
div![class!["fakeTextArea"], handler]
|
|
|
|
};
|
|
|
|
|
|
|
|
div![
|
|
|
|
class!["left"],
|
|
|
|
title,
|
|
|
|
description_field,
|
|
|
|
div![
|
|
|
|
class!["comments"],
|
|
|
|
div![class!["title"], "Comments"],
|
|
|
|
div![
|
|
|
|
class!["create"],
|
|
|
|
user_avatar,
|
|
|
|
div![
|
|
|
|
class!["right"],
|
|
|
|
create_comment,
|
|
|
|
div![
|
|
|
|
class!["proTip"],
|
|
|
|
strong![class!["strong"], "Pro tip: "],
|
|
|
|
"press ",
|
|
|
|
span![class!["tipLetter"], "M"],
|
|
|
|
" to comment"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
|
|
],
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
fn right_modal_column(model: &Model, modal: &EditIssueModal) -> Node<Msg> {
|
|
|
|
let EditIssueModal {
|
|
|
|
payload,
|
|
|
|
status_state,
|
|
|
|
reporter_state,
|
|
|
|
assignees_state,
|
|
|
|
priority_state,
|
|
|
|
..
|
|
|
|
} = modal;
|
|
|
|
|
|
|
|
let status = StyledSelect::build(FieldId::EditIssueModal(EditIssueModalFieldId::Status))
|
2020-04-09 16:03:11 +02:00
|
|
|
.name("status")
|
2020-04-10 08:09:40 +02:00
|
|
|
.opened(status_state.opened)
|
|
|
|
.normal()
|
|
|
|
.text_filter(status_state.text_filter.as_str())
|
2020-04-09 16:03:11 +02:00
|
|
|
.options(
|
|
|
|
IssueStatus::ordered()
|
|
|
|
.into_iter()
|
2020-04-12 13:21:47 +02:00
|
|
|
.map(|opt| opt.to_select_child().name("status"))
|
2020-04-09 16:03:11 +02:00
|
|
|
.collect(),
|
|
|
|
)
|
2020-04-12 13:21:47 +02:00
|
|
|
.selected(vec![payload.status.to_select_child().name("status")])
|
2020-04-09 16:03:11 +02:00
|
|
|
.valid(true)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-10 08:09:40 +02:00
|
|
|
let status_field = StyledField::build()
|
|
|
|
.input(status)
|
|
|
|
.label("Status")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let assignees = StyledSelect::build(FieldId::EditIssueModal(EditIssueModalFieldId::Assignees))
|
2020-04-10 08:09:40 +02:00
|
|
|
.name("assignees")
|
2020-04-12 13:21:47 +02:00
|
|
|
.opened(assignees_state.opened)
|
|
|
|
.empty()
|
2020-04-10 08:09:40 +02:00
|
|
|
.multi()
|
2020-04-12 13:21:47 +02:00
|
|
|
.text_filter(assignees_state.text_filter.as_str())
|
|
|
|
.options(
|
|
|
|
model
|
|
|
|
.users
|
|
|
|
.iter()
|
|
|
|
.map(|user| user.to_select_child().name("assignees"))
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-04-10 08:09:40 +02:00
|
|
|
.selected(
|
|
|
|
model
|
|
|
|
.users
|
|
|
|
.iter()
|
|
|
|
.filter(|user| payload.user_ids.contains(&user.id))
|
2020-04-12 13:21:47 +02:00
|
|
|
.map(|user| user.to_select_child().name("assignees"))
|
2020-04-10 08:09:40 +02:00
|
|
|
.collect(),
|
|
|
|
)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let assignees_field = StyledField::build()
|
|
|
|
.input(assignees)
|
|
|
|
.label("Assignees")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
2020-04-09 16:03:11 +02:00
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let reporter = StyledSelect::build(FieldId::EditIssueModal(EditIssueModalFieldId::Reporter))
|
2020-04-10 22:33:07 +02:00
|
|
|
.name("reporter")
|
2020-04-12 13:21:47 +02:00
|
|
|
.opened(reporter_state.opened)
|
|
|
|
.empty()
|
|
|
|
.text_filter(reporter_state.text_filter.as_str())
|
|
|
|
.options(
|
|
|
|
model
|
|
|
|
.users
|
|
|
|
.iter()
|
|
|
|
.map(|user| user.to_select_child().name("reporter"))
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-04-10 22:33:07 +02:00
|
|
|
.selected(
|
|
|
|
model
|
|
|
|
.users
|
|
|
|
.iter()
|
|
|
|
.filter(|user| payload.reporter_id == user.id)
|
2020-04-12 13:21:47 +02:00
|
|
|
.map(|user| user.to_select_child().name("reporter"))
|
2020-04-10 22:33:07 +02:00
|
|
|
.collect(),
|
|
|
|
)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let reporter_field = StyledField::build()
|
|
|
|
.input(reporter)
|
|
|
|
.label("Reporter")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let priority = StyledSelect::build(FieldId::EditIssueModal(EditIssueModalFieldId::Priority))
|
|
|
|
.name("priority")
|
|
|
|
.opened(priority_state.opened)
|
|
|
|
.empty()
|
|
|
|
.text_filter(priority_state.text_filter.as_str())
|
2020-04-10 22:33:07 +02:00
|
|
|
.options(
|
|
|
|
IssuePriority::ordered()
|
|
|
|
.into_iter()
|
2020-04-12 13:21:47 +02:00
|
|
|
.map(|p| p.to_select_child().name("priority"))
|
2020-04-10 22:33:07 +02:00
|
|
|
.collect(),
|
|
|
|
)
|
2020-04-12 13:21:47 +02:00
|
|
|
.selected(vec![payload.priority.to_select_child().name("priority")])
|
2020-04-10 22:33:07 +02:00
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let priority_field = StyledField::build()
|
|
|
|
.input(priority)
|
|
|
|
.label("Priority")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-12 13:21:47 +02:00
|
|
|
let estimate = StyledInput::build(FieldId::EditIssueModal(EditIssueModalFieldId::Estimate))
|
2020-04-10 22:33:07 +02:00
|
|
|
.valid(true)
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
let estimate_field = StyledField::build()
|
|
|
|
.input(estimate)
|
|
|
|
.label("Original Estimate (hours)")
|
|
|
|
.build()
|
|
|
|
.into_node();
|
|
|
|
|
2020-04-02 23:51:29 +02:00
|
|
|
div![
|
2020-04-12 13:21:47 +02:00
|
|
|
attrs![At::Class => "right"],
|
|
|
|
status_field,
|
|
|
|
assignees_field,
|
|
|
|
reporter_field,
|
|
|
|
priority_field,
|
|
|
|
estimate_field
|
2020-04-02 23:51:29 +02:00
|
|
|
]
|
|
|
|
}
|