Remove last in-use builder
This commit is contained in:
parent
2b40f9fd91
commit
041078b7c9
@ -27,7 +27,7 @@ impl StyledCheckboxState {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChildBuilder<'l> {
|
||||
pub field_id: Option<FieldId>,
|
||||
pub field_id: FieldId,
|
||||
pub name: &'l str,
|
||||
pub label: &'l str,
|
||||
pub value: u32,
|
||||
@ -38,7 +38,7 @@ pub struct ChildBuilder<'l> {
|
||||
impl<'l> Default for ChildBuilder<'l> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
field_id: None,
|
||||
field_id: FieldId::TextFilterBoard,
|
||||
name: "",
|
||||
label: "",
|
||||
value: 0,
|
||||
@ -48,38 +48,6 @@ impl<'l> Default for ChildBuilder<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ChildBuilder<'l> {
|
||||
pub fn value(mut self, value: u32) -> Self {
|
||||
self.value = value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(mut self, name: &'l str) -> Self {
|
||||
self.name = name;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn label(mut self, label: &'l str) -> Self {
|
||||
self.label = label;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_id(mut self, id: FieldId) -> Self {
|
||||
self.field_id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn try_select(mut self, value: u32) -> Self {
|
||||
self.selected = self.value == value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn class_list(mut self, name: &'l str) -> Self {
|
||||
self.class_list = name;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for ChildBuilder<'l> {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
let ChildBuilder {
|
||||
@ -91,18 +59,12 @@ impl<'l> ToNode for ChildBuilder<'l> {
|
||||
class_list,
|
||||
} = self;
|
||||
|
||||
let id = field_id.as_ref().map(|f| f.to_string()).unwrap_or_default();
|
||||
let field_id_clone = field_id.as_ref().cloned();
|
||||
let id = field_id.to_string();
|
||||
let field_id_clone = field_id.clone();
|
||||
let handler: EventHandler<Msg> = mouse_ev(Ev::Click, move |_| {
|
||||
field_id_clone.map(|field_id| Msg::U32InputChanged(field_id, value))
|
||||
Msg::U32InputChanged(field_id_clone, value)
|
||||
});
|
||||
|
||||
let input_attrs = if selected {
|
||||
attrs![At::Type => "radio", At::Name => name, At::Checked => selected, At::Id => format!("{}-{}", id, name)]
|
||||
} else {
|
||||
attrs![At::Type => "radio", At::Name => name, At::Id => format!("{}-{}", id, name)]
|
||||
};
|
||||
|
||||
div![
|
||||
C![
|
||||
"styledCheckboxChild",
|
||||
@ -111,7 +73,10 @@ impl<'l> ToNode for ChildBuilder<'l> {
|
||||
],
|
||||
handler,
|
||||
label![attrs![At::For => format!("{}-{}", id, name)], label],
|
||||
input![input_attrs],
|
||||
input![
|
||||
attrs![At::Type => "radio", At::Name => name, At::Id => format!("{}-{}", id, name)],
|
||||
IF![selected => attrs!(At::Checked => selected)]
|
||||
],
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -121,10 +86,20 @@ pub struct StyledCheckbox<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
id: FieldId,
|
||||
options: Option<Options>,
|
||||
selected: u32,
|
||||
class_list: Vec<&'l str>,
|
||||
pub options: Option<Options>,
|
||||
pub class_list: &'l str,
|
||||
}
|
||||
|
||||
impl<'l, Options> Default for StyledCheckbox<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
options: None,
|
||||
class_list: "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l, Options> ToNode for StyledCheckbox<'l, Options>
|
||||
@ -136,78 +111,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l, Options> StyledCheckbox<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
pub fn build() -> StyledCheckboxBuilder<'l, Options> {
|
||||
StyledCheckboxBuilder {
|
||||
options: None,
|
||||
selected: 0,
|
||||
class_list: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledCheckboxBuilder<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
options: Option<Options>,
|
||||
selected: u32,
|
||||
class_list: Vec<&'l str>,
|
||||
}
|
||||
|
||||
impl<'l, Options> StyledCheckboxBuilder<'l, Options>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
pub fn state(mut self, state: &StyledCheckboxState) -> Self {
|
||||
self.selected = state.value;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_class(mut self, name: &'l str) -> Self {
|
||||
self.class_list.push(name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn options(mut self, options: Options) -> Self {
|
||||
self.options = Some(options);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, field_id: FieldId) -> StyledCheckbox<'l, Options> {
|
||||
StyledCheckbox {
|
||||
id: field_id,
|
||||
options: self.options,
|
||||
selected: self.selected,
|
||||
class_list: self.class_list,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render<'l, Options>(values: StyledCheckbox<'l, Options>) -> Node<Msg>
|
||||
where
|
||||
Options: Iterator<Item = ChildBuilder<'l>>,
|
||||
{
|
||||
let StyledCheckbox {
|
||||
id,
|
||||
options,
|
||||
selected,
|
||||
class_list,
|
||||
} = values;
|
||||
|
||||
let opt: Vec<Node<Msg>> = match options {
|
||||
Some(options) => options
|
||||
.map(|child| child.with_id(id.clone()).try_select(selected).into_node())
|
||||
.collect(),
|
||||
Some(options) => options.map(|child| child.into_node()).collect(),
|
||||
_ => vec![Node::Empty],
|
||||
};
|
||||
|
||||
div![
|
||||
C!["styledCheckbox"],
|
||||
attrs![At::Class => class_list.join(" ")],
|
||||
opt,
|
||||
]
|
||||
div![C!["styledCheckbox", class_list], opt,]
|
||||
}
|
||||
|
@ -32,64 +32,12 @@ impl<'l> Default for StyledConfirmModal<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> StyledConfirmModal<'l> {
|
||||
pub fn build() -> StyledConfirmModalBuilder<'l> {
|
||||
StyledConfirmModalBuilder::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for StyledConfirmModal<'l> {
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
render(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct StyledConfirmModalBuilder<'l> {
|
||||
title: Option<&'l str>,
|
||||
message: Option<&'l str>,
|
||||
confirm_text: Option<&'l str>,
|
||||
cancel_text: Option<&'l str>,
|
||||
on_confirm: Option<EventHandler<Msg>>,
|
||||
}
|
||||
|
||||
impl<'l> StyledConfirmModalBuilder<'l> {
|
||||
pub fn title(mut self, title: &'l str) -> Self {
|
||||
self.title = Some(title);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn message(mut self, message: &'l str) -> Self {
|
||||
self.message = Some(message);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn confirm_text(mut self, confirm_text: &'l str) -> Self {
|
||||
self.confirm_text = Some(confirm_text);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cancel_text(mut self, cancel_text: &'l str) -> Self {
|
||||
self.cancel_text = Some(cancel_text);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_confirm(mut self, on_confirm: EventHandler<Msg>) -> Self {
|
||||
self.on_confirm = Some(on_confirm);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> StyledConfirmModal<'l> {
|
||||
StyledConfirmModal {
|
||||
title: self.title.unwrap_or(TITLE),
|
||||
message: self.message.unwrap_or(MESSAGE),
|
||||
confirm_text: self.confirm_text.unwrap_or(CONFIRM_TEXT),
|
||||
cancel_text: self.cancel_text.unwrap_or(CANCEL_TEXT),
|
||||
on_confirm: self.on_confirm,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(values: StyledConfirmModal) -> Node<Msg> {
|
||||
let StyledConfirmModal {
|
||||
title,
|
||||
@ -114,7 +62,7 @@ pub fn render(values: StyledConfirmModal) -> Node<Msg> {
|
||||
|
||||
let message_node = match message {
|
||||
_ if message.is_empty() => empty![],
|
||||
_ => p![attrs![At::Class => "message"], message],
|
||||
_ => p![C!["message"], message],
|
||||
};
|
||||
|
||||
let confirm_button = StyledButton {
|
||||
|
@ -21,8 +21,8 @@ pub enum StyledDateTimeChanged {
|
||||
#[derive(Clone, Debug, PartialOrd, PartialEq)]
|
||||
pub struct StyledDateTimeInputState {
|
||||
field_id: FieldId,
|
||||
timestamp: Option<chrono::NaiveDateTime>,
|
||||
popup_visible: bool,
|
||||
pub timestamp: Option<chrono::NaiveDateTime>,
|
||||
pub popup_visible: bool,
|
||||
}
|
||||
|
||||
impl StyledDateTimeInputState {
|
||||
@ -70,18 +70,9 @@ impl StyledDateTimeInputState {
|
||||
}
|
||||
|
||||
pub struct StyledDateTimeInput {
|
||||
field_id: FieldId,
|
||||
timestamp: Option<chrono::NaiveDateTime>,
|
||||
popup_visible: bool,
|
||||
}
|
||||
|
||||
impl StyledDateTimeInput {
|
||||
pub fn build() -> StyledDateTimeInputBuilder {
|
||||
StyledDateTimeInputBuilder {
|
||||
timestamp: None,
|
||||
popup_visible: false,
|
||||
}
|
||||
}
|
||||
pub field_id: FieldId,
|
||||
pub timestamp: Option<chrono::NaiveDateTime>,
|
||||
pub popup_visible: bool,
|
||||
}
|
||||
|
||||
impl ToNode for StyledDateTimeInput {
|
||||
@ -90,27 +81,6 @@ impl ToNode for StyledDateTimeInput {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StyledDateTimeInputBuilder {
|
||||
timestamp: Option<chrono::NaiveDateTime>,
|
||||
popup_visible: bool,
|
||||
}
|
||||
|
||||
impl StyledDateTimeInputBuilder {
|
||||
pub fn state(mut self, state: &StyledDateTimeInputState) -> Self {
|
||||
self.timestamp = state.timestamp;
|
||||
self.popup_visible = state.popup_visible;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, field_id: FieldId) -> StyledDateTimeInput {
|
||||
StyledDateTimeInput {
|
||||
field_id,
|
||||
timestamp: self.timestamp,
|
||||
popup_visible: self.popup_visible,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(values: StyledDateTimeInput) -> Node<Msg> {
|
||||
let timestamp = values
|
||||
.timestamp
|
||||
|
@ -4,20 +4,13 @@ use seed::*;
|
||||
use crate::shared::ToNode;
|
||||
use crate::Msg;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct StyledForm<'l> {
|
||||
pub heading: &'l str,
|
||||
pub fields: Vec<Node<Msg>>,
|
||||
pub on_submit: Option<EventHandler<Msg>>,
|
||||
}
|
||||
|
||||
impl<'l> StyledForm<'l> {
|
||||
#[inline]
|
||||
pub fn build() -> StyledFormBuilder<'l> {
|
||||
StyledFormBuilder::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'l> ToNode for StyledForm<'l> {
|
||||
#[inline]
|
||||
fn into_node(self) -> Node<Msg> {
|
||||
@ -25,50 +18,6 @@ impl<'l> ToNode for StyledForm<'l> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct StyledFormBuilder<'l> {
|
||||
fields: Vec<Node<Msg>>,
|
||||
heading: &'l str,
|
||||
on_submit: Option<EventHandler<Msg>>,
|
||||
}
|
||||
|
||||
impl<'l> StyledFormBuilder<'l> {
|
||||
#[inline]
|
||||
pub fn add_field(mut self, node: Node<Msg>) -> Self {
|
||||
self.fields.push(node);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_field(mut self, node: Option<Node<Msg>>) -> Self {
|
||||
if let Some(n) = node {
|
||||
self.fields.push(n);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn heading(mut self, heading: &'l str) -> Self {
|
||||
self.heading = heading;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn on_submit(mut self, on_submit: EventHandler<Msg>) -> Self {
|
||||
self.on_submit = Some(on_submit);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn build(self) -> StyledForm<'l> {
|
||||
StyledForm {
|
||||
heading: self.heading,
|
||||
fields: self.fields,
|
||||
on_submit: self.on_submit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn render(values: StyledForm) -> Node<Msg> {
|
||||
let StyledForm {
|
||||
|
@ -69,7 +69,7 @@ impl StyledSelectState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, msg: &Msg, orders: &mut impl Orders<Msg>) {
|
||||
pub fn update(&mut self, msg: &Msg, _orders: &mut impl Orders<Msg>) {
|
||||
let field_id = match msg {
|
||||
Msg::StyledSelectChanged(field_id, ..) => field_id,
|
||||
_ => return,
|
||||
@ -85,7 +85,6 @@ impl StyledSelectState {
|
||||
}
|
||||
}
|
||||
Msg::StyledSelectChanged(_, StyledSelectChanged::Text(text)) => {
|
||||
orders.skip();
|
||||
self.text_filter = text.clone();
|
||||
}
|
||||
Msg::StyledSelectChanged(_, StyledSelectChanged::Changed(Some(v))) => {
|
||||
|
@ -8,23 +8,9 @@ use crate::components::styled_icon::Icon;
|
||||
use crate::components::styled_input::*;
|
||||
use crate::components::styled_modal::*;
|
||||
use crate::modals::epics_edit::Model;
|
||||
use crate::shared::{IntoChild, ToNode};
|
||||
use crate::shared::ToNode;
|
||||
use crate::{model, FieldId, Msg};
|
||||
|
||||
pub struct IssueTypeWrapper(IssueType);
|
||||
|
||||
impl<'l> IntoChild<'l> for IssueTypeWrapper {
|
||||
type Builder = ChildBuilder<'l>;
|
||||
|
||||
fn into_child(self) -> Self::Builder {
|
||||
Self::Builder::default()
|
||||
.label(self.0.to_label())
|
||||
.name(self.0.to_str())
|
||||
.value(self.0.into())
|
||||
.class_list(self.0.to_str())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view(_model: &model::Model, modal: &Model) -> Node<Msg> {
|
||||
let transform = if modal.related_issues.is_empty() {
|
||||
transform_into_available(modal)
|
||||
@ -62,15 +48,15 @@ pub fn view(_model: &model::Model, modal: &Model) -> Node<Msg> {
|
||||
}
|
||||
|
||||
fn transform_into_available(modal: &super::Model) -> Node<Msg> {
|
||||
let types = StyledCheckbox::build()
|
||||
.options(
|
||||
let types = StyledCheckbox {
|
||||
options: Some(
|
||||
IssueType::default()
|
||||
.into_iter()
|
||||
.map(issue_type_select_option),
|
||||
)
|
||||
.state(&modal.transform_into)
|
||||
.build(FieldId::EditEpic(EpicFieldId::TransformInto))
|
||||
.into_node();
|
||||
.map(|it| issue_type_select_option(it, &modal.transform_into)),
|
||||
),
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
let execute = StyledButton {
|
||||
on_click: Some(mouse_ev("click", |ev| {
|
||||
ev.stop_propagation();
|
||||
@ -85,13 +71,15 @@ fn transform_into_available(modal: &super::Model) -> Node<Msg> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn issue_type_select_option<'l>(ty: IssueType) -> ChildBuilder<'l> {
|
||||
fn issue_type_select_option<'l>(ty: IssueType, state: &StyledCheckboxState) -> ChildBuilder<'l> {
|
||||
let value: u32 = ty.into();
|
||||
ChildBuilder {
|
||||
field_id: state.field_id.clone(),
|
||||
name: ty.to_str(),
|
||||
label: ty.to_label(),
|
||||
value: ty.into(),
|
||||
class_list: ty.to_str(),
|
||||
..Default::default()
|
||||
selected: value == state.value,
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,6 +88,7 @@ fn transform_into_unavailable(modal: &super::Model) -> Node<Msg> {
|
||||
1 => (1.to_string(), "issue"),
|
||||
n => (n.to_string(), "issues"),
|
||||
};
|
||||
|
||||
div![
|
||||
C!["transform unavailable"],
|
||||
span![
|
||||
|
@ -29,36 +29,43 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
.unwrap_or_else(|| Type::Task);
|
||||
|
||||
let issue_type_field = issue_type_field(modal);
|
||||
let form = StyledForm::build()
|
||||
.heading(issue_type.form_label())
|
||||
.add_field(issue_type_field)
|
||||
.add_field(crate::shared::divider());
|
||||
let mut form = StyledForm {
|
||||
heading: issue_type.form_label(),
|
||||
fields: vec![issue_type_field, crate::shared::divider()],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let form = match issue_type {
|
||||
match issue_type {
|
||||
Type::Epic => {
|
||||
let name_field = name_field(modal);
|
||||
|
||||
let starts = StyledField {
|
||||
input: StyledDateTimeInput::build()
|
||||
.state(&modal.epic_starts_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicStartsAt))
|
||||
.into_node(),
|
||||
input: StyledDateTimeInput {
|
||||
field_id: FieldId::AddIssueModal(IssueFieldId::EpicStartsAt),
|
||||
popup_visible: modal.epic_starts_at_state.popup_visible,
|
||||
timestamp: modal.epic_starts_at_state.timestamp.clone(),
|
||||
}
|
||||
.into_node(),
|
||||
label: "Starts at",
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let end = StyledField {
|
||||
input: StyledDateTimeInput::build()
|
||||
.state(&modal.epic_ends_at_state)
|
||||
.build(FieldId::AddIssueModal(IssueFieldId::EpicEndsAt))
|
||||
.into_node(),
|
||||
input: StyledDateTimeInput {
|
||||
field_id: FieldId::AddIssueModal(IssueFieldId::EpicEndsAt),
|
||||
popup_visible: modal.epic_ends_at_state.popup_visible,
|
||||
timestamp: modal.epic_ends_at_state.timestamp.clone(),
|
||||
}
|
||||
.into_node(),
|
||||
label: "Ends at",
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
form.add_field(name_field).add_field(starts).add_field(end)
|
||||
form.fields.push(name_field);
|
||||
form.fields.push(starts);
|
||||
form.fields.push(end)
|
||||
}
|
||||
Type::Task | Type::Story | Type::Bug => {
|
||||
let short_summary_field = short_summary_field(modal);
|
||||
@ -69,12 +76,14 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
let epic_field =
|
||||
epic_field(model, modal, FieldId::AddIssueModal(IssueFieldId::EpicName));
|
||||
|
||||
form.add_field(short_summary_field)
|
||||
.add_field(description_field)
|
||||
.add_field(reporter_field)
|
||||
.add_field(assignees_field)
|
||||
.add_field(issue_priority_field)
|
||||
.try_field(epic_field)
|
||||
form.fields.push(short_summary_field);
|
||||
form.fields.push(description_field);
|
||||
form.fields.push(reporter_field);
|
||||
form.fields.push(assignees_field);
|
||||
form.fields.push(issue_priority_field);
|
||||
if let Some(field) = epic_field {
|
||||
form.fields.push(field);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,12 +115,12 @@ pub fn view(model: &Model, modal: &AddIssueModal) -> Node<Msg> {
|
||||
.into_node();
|
||||
let actions = div![attrs![At::Class => "actions"], submit, cancel];
|
||||
|
||||
let form = form.add_field(actions).build().into_node();
|
||||
form.fields.push(actions);
|
||||
|
||||
StyledModal {
|
||||
class_list: "addIssue",
|
||||
width: Some(0),
|
||||
children: vec![form],
|
||||
children: vec![form.into_node()],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node()
|
||||
|
@ -22,17 +22,15 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
_ => empty![],
|
||||
};
|
||||
|
||||
let form = StyledForm::build()
|
||||
.heading("Welcome in JIRS")
|
||||
.on_submit(ev(Ev::Submit, move |ev| {
|
||||
let form = StyledForm {
|
||||
heading: "Welcome in JIRS",
|
||||
on_submit: Some(ev(Ev::Submit, move |ev| {
|
||||
ev.prevent_default();
|
||||
Msg::PageChanged(PageChanged::Invitation(InvitationPageChange::SubmitForm))
|
||||
}))
|
||||
.add_field(token_field)
|
||||
.add_field(submit_field)
|
||||
.add_field(error)
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
fields: vec![token_field, submit_field, error],
|
||||
}
|
||||
.into_node();
|
||||
|
||||
outer_layout(model, "invite", vec![form])
|
||||
}
|
||||
|
@ -77,19 +77,21 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let content = StyledForm::build()
|
||||
.heading("Profile")
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
let content = StyledForm {
|
||||
heading: "Profile",
|
||||
on_submit: Some(ev(Ev::Submit, |ev| {
|
||||
ev.prevent_default();
|
||||
Msg::PageChanged(PageChanged::Profile(ProfilePageChange::SubmitForm))
|
||||
}))
|
||||
.add_field(avatar)
|
||||
.add_field(username_field)
|
||||
.add_field(email_field)
|
||||
.add_field(current_project)
|
||||
.add_field(submit_field)
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
fields: vec![
|
||||
avatar,
|
||||
username_field,
|
||||
email_field,
|
||||
current_project,
|
||||
submit_field,
|
||||
],
|
||||
}
|
||||
.into_node();
|
||||
inner_layout(model, "profile", &[content])
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use seed::prelude::*;
|
||||
use seed::*;
|
||||
|
||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||
use crate::components::styled_checkbox::{ChildBuilder, StyledCheckbox};
|
||||
use crate::components::styled_checkbox::{ChildBuilder, StyledCheckbox, StyledCheckboxState};
|
||||
use crate::components::styled_editor::StyledEditor;
|
||||
use crate::components::styled_field::StyledField;
|
||||
use crate::components::styled_form::StyledForm;
|
||||
@ -64,24 +64,26 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let form = StyledForm::build()
|
||||
.heading("Project Details")
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
let form = StyledForm {
|
||||
heading: "Project Details",
|
||||
fields: vec![
|
||||
name_field,
|
||||
url_field,
|
||||
description_field,
|
||||
category_field,
|
||||
time_tracking_field,
|
||||
save_button,
|
||||
columns_field,
|
||||
],
|
||||
on_submit: Some(ev(Ev::Submit, |ev| {
|
||||
ev.prevent_default();
|
||||
ev.stop_propagation();
|
||||
Msg::PageChanged(PageChanged::ProjectSettings(
|
||||
ProjectPageChange::SubmitProjectSettingsForm,
|
||||
))
|
||||
}))
|
||||
.add_field(name_field)
|
||||
.add_field(url_field)
|
||||
// .add_field(desc_rte)
|
||||
.add_field(description_field)
|
||||
.add_field(category_field)
|
||||
.add_field(time_tracking_field)
|
||||
.add_field(save_button)
|
||||
.add_field(columns_field)
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let project_section = [div![C!["formContainer"], form]];
|
||||
|
||||
@ -90,16 +92,15 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
|
||||
#[inline(always)]
|
||||
fn time_tracking_select(page: &ProjectSettingsPage) -> Node<Msg> {
|
||||
let time_tracking = StyledCheckbox::build()
|
||||
.options(
|
||||
let time_tracking = StyledCheckbox {
|
||||
options: Some(
|
||||
TimeTracking::default()
|
||||
.into_iter()
|
||||
.map(time_tracking_select_option),
|
||||
)
|
||||
.state(&page.time_tracking)
|
||||
.add_class("timeTracking")
|
||||
.build(FieldId::ProjectSettings(ProjectFieldId::TimeTracking))
|
||||
.into_node();
|
||||
.map(|tt| time_tracking_checkbox_option(tt, &page.time_tracking)),
|
||||
),
|
||||
class_list: "timeTracking",
|
||||
}
|
||||
.into_node();
|
||||
let time_tracking_type: TimeTracking = page.time_tracking.value.into();
|
||||
StyledField {
|
||||
input: time_tracking,
|
||||
@ -113,8 +114,14 @@ fn time_tracking_select(page: &ProjectSettingsPage) -> Node<Msg> {
|
||||
.into_node()
|
||||
}
|
||||
|
||||
fn time_tracking_select_option<'l>(t: TimeTracking) -> ChildBuilder<'l> {
|
||||
fn time_tracking_checkbox_option<'l>(
|
||||
t: TimeTracking,
|
||||
state: &StyledCheckboxState,
|
||||
) -> ChildBuilder<'l> {
|
||||
let value: u32 = t.into();
|
||||
ChildBuilder {
|
||||
field_id: state.field_id.clone(),
|
||||
selected: state.value == value,
|
||||
label: match t {
|
||||
TimeTracking::Untracked => "No tracking",
|
||||
TimeTracking::Fibonacci => "Fibonacci (Bad mode)",
|
||||
@ -130,8 +137,7 @@ fn time_tracking_select_option<'l>(t: TimeTracking) -> ChildBuilder<'l> {
|
||||
TimeTracking::Fibonacci => "fibonacci",
|
||||
TimeTracking::Hourly => "hourly",
|
||||
},
|
||||
value: t.into(),
|
||||
..Default::default()
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,12 +242,10 @@ fn category_select_option<'l>(pc: ProjectCategory) -> StyledSelectChild<'l> {
|
||||
fn columns_section(model: &Model, page: &ProjectSettingsPage) -> 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 per_column_issue_count = model.issues().iter().fold(HashMap::new(), |mut h, issue| {
|
||||
*h.entry(issue.issue_status_id).or_insert(0) += 1;
|
||||
h
|
||||
});
|
||||
let columns: Vec<Node<Msg>> = model
|
||||
.issue_statuses
|
||||
.iter()
|
||||
@ -281,6 +285,7 @@ fn add_column(page: &ProjectSettingsPage, column_style: &str) -> Node<Msg> {
|
||||
});
|
||||
let on_submit = ev(Ev::Submit, move |ev| {
|
||||
ev.prevent_default();
|
||||
ev.stop_propagation();
|
||||
Some(Msg::PageChanged(PageChanged::ProjectSettings(
|
||||
ProjectPageChange::SubmitIssueStatusForm,
|
||||
)))
|
||||
|
@ -124,16 +124,16 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let bind_token_form = StyledForm::build()
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
let bind_token_form = StyledForm {
|
||||
on_submit: Some(ev(Ev::Submit, |ev| {
|
||||
ev.stop_propagation();
|
||||
ev.prevent_default();
|
||||
Msg::BindClientRequest
|
||||
}))
|
||||
.add_field(token_field)
|
||||
.add_field(submit_token_field)
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
fields: vec![token_field, submit_token_field],
|
||||
..Default::default()
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let children = vec![sign_in_form, bind_token_form];
|
||||
outer_layout(model, "login", children)
|
||||
|
@ -94,20 +94,22 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
||||
div![C!["error"], p![page.error.as_str()]]
|
||||
};
|
||||
|
||||
let sign_up_form = StyledForm::build()
|
||||
.heading("Sign In to your account")
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
let sign_up_form = StyledForm {
|
||||
heading: "Sign In to your account",
|
||||
on_submit: Some(ev(Ev::Submit, |ev| {
|
||||
ev.stop_propagation();
|
||||
ev.prevent_default();
|
||||
Msg::SignUpRequest
|
||||
}))
|
||||
.add_field(username_field)
|
||||
.add_field(email_field)
|
||||
.add_field(submit_field)
|
||||
.add_field(no_pass_section)
|
||||
.add_field(error_row)
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
fields: vec![
|
||||
username_field,
|
||||
email_field,
|
||||
submit_field,
|
||||
no_pass_section,
|
||||
error_row,
|
||||
],
|
||||
}
|
||||
.into_node();
|
||||
let children = vec![sign_up_form];
|
||||
outer_layout(model, "register", children)
|
||||
}
|
||||
|
@ -82,18 +82,15 @@ pub fn view(model: &Model) -> Node<Msg> {
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let form = StyledForm::build()
|
||||
.heading("Invite new user")
|
||||
.add_field(name_field)
|
||||
.add_field(email_field)
|
||||
.add_field(user_role_field)
|
||||
.add_field(submit_field)
|
||||
.on_submit(ev(Ev::Submit, |ev| {
|
||||
let form = StyledForm {
|
||||
heading: "Invite new user",
|
||||
on_submit: Some(ev(Ev::Submit, |ev| {
|
||||
ev.prevent_default();
|
||||
Msg::InviteRequest
|
||||
}))
|
||||
.build()
|
||||
.into_node();
|
||||
})),
|
||||
fields: vec![name_field, email_field, user_role_field, submit_field],
|
||||
}
|
||||
.into_node();
|
||||
|
||||
let users: Vec<Node<Msg>> = page
|
||||
.invited_users
|
||||
|
Loading…
Reference in New Issue
Block a user