Draw confirm delete issue, emit valid msg on confirm
This commit is contained in:
parent
f2b5753f83
commit
135907384e
@ -77,6 +77,29 @@
|
|||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.styledModal.confirmModal {
|
.modal > .clickableOverlay > .styledModal.confirmModal {
|
||||||
padding: 35px 40px 40px;
|
padding: 35px 40px 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal > .clickableOverlay > .styledModal.confirmModal > .title {
|
||||||
|
padding-bottom: 25px;
|
||||||
|
font-family: var(--font-medium);
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal > .clickableOverlay > .styledModal.confirmModal > .message {
|
||||||
|
padding-bottom: 25px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
font-size: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal > .clickableOverlay > .styledModal.confirmModal > .actions {
|
||||||
|
display: flex;
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal > .clickableOverlay > .styledModal.confirmModal > .actions > .styledButton {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
@ -56,6 +56,7 @@ pub enum Msg {
|
|||||||
|
|
||||||
// issues
|
// issues
|
||||||
IssueUpdateResult(FetchObject<String>),
|
IssueUpdateResult(FetchObject<String>),
|
||||||
|
DeleteIssue(IssueId),
|
||||||
|
|
||||||
// modals
|
// modals
|
||||||
ModalOpened(ModalType),
|
ModalOpened(ModalType),
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
use seed::{prelude::*, *};
|
use seed::{prelude::*, *};
|
||||||
|
|
||||||
use crate::shared::styled_modal::StyledModal;
|
use crate::model::ModalType;
|
||||||
|
use crate::shared::styled_confirm_modal::StyledConfirmModal;
|
||||||
use crate::shared::ToNode;
|
use crate::shared::ToNode;
|
||||||
use crate::{model, Msg};
|
use crate::{model, Msg};
|
||||||
|
|
||||||
pub fn view(model: &model::Model) -> Node<Msg> {
|
pub fn view(model: &model::Model) -> Node<Msg> {
|
||||||
let handle_issue_delete = mouse_ev(Ev::Click, |_| Msg::NoOp);
|
let opt_id = model
|
||||||
StyledModal::build()
|
.modals
|
||||||
|
.iter()
|
||||||
|
.filter_map(|modal| match modal {
|
||||||
|
ModalType::EditIssue(issue_id, _) => Some(issue_id),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.find(|id| id.eq(id));
|
||||||
|
|
||||||
|
let issue_id = match opt_id {
|
||||||
|
Some(id) => *id,
|
||||||
|
_ => return empty![],
|
||||||
|
};
|
||||||
|
|
||||||
|
let handle_issue_delete = mouse_ev(Ev::Click, move |_| Msg::DeleteIssue(issue_id));
|
||||||
|
|
||||||
|
StyledConfirmModal::build()
|
||||||
.title("Are you sure you want to delete this issue?")
|
.title("Are you sure you want to delete this issue?")
|
||||||
.message("Once you delete, it's gone for good.")
|
.message("Once you delete, it's gone for good.")
|
||||||
.confirm_text("Delete issue")
|
.confirm_text("Delete issue")
|
||||||
|
@ -4,7 +4,7 @@ use jirs_data::{Issue, IssueType, UpdateIssuePayload};
|
|||||||
|
|
||||||
use crate::api::update_issue;
|
use crate::api::update_issue;
|
||||||
use crate::model::{EditIssueModal, ModalType, Page};
|
use crate::model::{EditIssueModal, ModalType, Page};
|
||||||
use crate::shared::modal::{Modal, Variant as ModalVariant};
|
use crate::shared::styled_modal::{StyledModal, Variant as ModalVariant};
|
||||||
use crate::shared::styled_select::StyledSelectChange;
|
use crate::shared::styled_select::StyledSelectChange;
|
||||||
use crate::shared::{find_issue, ToNode};
|
use crate::shared::{find_issue, ToNode};
|
||||||
use crate::{model, FieldChange, FieldId, Msg};
|
use crate::{model, FieldChange, FieldId, Msg};
|
||||||
@ -114,14 +114,12 @@ pub fn view(model: &model::Model) -> Node<Msg> {
|
|||||||
ModalType::EditIssue(issue_id, modal) => {
|
ModalType::EditIssue(issue_id, modal) => {
|
||||||
if let Some(issue) = find_issue(model, *issue_id) {
|
if let Some(issue) = find_issue(model, *issue_id) {
|
||||||
let details = issue_details::view(model, issue, &modal);
|
let details = issue_details::view(model, issue, &modal);
|
||||||
let modal = Modal {
|
StyledModal::build()
|
||||||
variant: ModalVariant::Center,
|
.variant(ModalVariant::Center)
|
||||||
width: 1040,
|
.width(1040)
|
||||||
with_icon: false,
|
.children(vec![details])
|
||||||
children: vec![details],
|
.build()
|
||||||
}
|
.into_node()
|
||||||
.into_node();
|
|
||||||
modal
|
|
||||||
} else {
|
} else {
|
||||||
empty![]
|
empty![]
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@ use crate::model::Model;
|
|||||||
use crate::{IssueId, Msg};
|
use crate::{IssueId, Msg};
|
||||||
|
|
||||||
pub mod aside;
|
pub mod aside;
|
||||||
pub mod modal;
|
|
||||||
pub mod navbar_left;
|
pub mod navbar_left;
|
||||||
pub mod styled_avatar;
|
pub mod styled_avatar;
|
||||||
pub mod styled_button;
|
pub mod styled_button;
|
||||||
|
pub mod styled_confirm_modal;
|
||||||
pub mod styled_icon;
|
pub mod styled_icon;
|
||||||
pub mod styled_input;
|
pub mod styled_input;
|
||||||
pub mod styled_modal;
|
pub mod styled_modal;
|
||||||
|
@ -1,83 +0,0 @@
|
|||||||
use seed::{prelude::*, *};
|
|
||||||
|
|
||||||
use crate::shared::styled_icon::{Icon, StyledIcon};
|
|
||||||
use crate::shared::ToNode;
|
|
||||||
use crate::Msg;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
|
|
||||||
pub enum Variant {
|
|
||||||
Center,
|
|
||||||
Aside,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Variant {
|
|
||||||
pub fn to_class_name(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Variant::Center => "center",
|
|
||||||
Variant::Aside => "aside",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_icon_class_name(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Variant::Center => "modalVariantCenter",
|
|
||||||
Variant::Aside => "modalVariantAside",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Modal {
|
|
||||||
pub variant: Variant,
|
|
||||||
pub width: usize,
|
|
||||||
pub with_icon: bool,
|
|
||||||
pub children: Vec<Node<Msg>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToNode for Modal {
|
|
||||||
fn into_node(self) -> Node<Msg> {
|
|
||||||
render(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render(values: Modal) -> Node<Msg> {
|
|
||||||
let Modal {
|
|
||||||
variant,
|
|
||||||
width,
|
|
||||||
with_icon,
|
|
||||||
children,
|
|
||||||
} = values;
|
|
||||||
|
|
||||||
let icon = if with_icon {
|
|
||||||
StyledIcon::build(Icon::Close)
|
|
||||||
.add_class(variant.to_icon_class_name().to_string())
|
|
||||||
.build()
|
|
||||||
.into_node()
|
|
||||||
} else {
|
|
||||||
empty![]
|
|
||||||
};
|
|
||||||
|
|
||||||
let close_handler = mouse_ev(Ev::Click, |_| Msg::ModalDropped);
|
|
||||||
let body_handler = mouse_ev(Ev::Click, |ev| {
|
|
||||||
ev.stop_propagation();
|
|
||||||
Msg::NoOp
|
|
||||||
});
|
|
||||||
|
|
||||||
let clickable_class = format!("clickableOverlay {}", variant.to_class_name());
|
|
||||||
let styled_modal_class = format!("styledModal {}", variant.to_class_name());
|
|
||||||
let styled_modal_style = format!("max-width: {width}px", width = width);
|
|
||||||
div![
|
|
||||||
attrs![At::Class => "modal"],
|
|
||||||
div![
|
|
||||||
attrs![At::Class => clickable_class],
|
|
||||||
close_handler,
|
|
||||||
div![
|
|
||||||
attrs![At::Class => styled_modal_class, At::Style => styled_modal_style],
|
|
||||||
body_handler,
|
|
||||||
icon,
|
|
||||||
children
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
152
jirs-client/src/shared/styled_confirm_modal.rs
Normal file
152
jirs-client/src/shared/styled_confirm_modal.rs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
use seed::EventHandler;
|
||||||
|
use seed::{prelude::*, *};
|
||||||
|
|
||||||
|
use crate::shared::styled_button::{StyledButton, Variant as ButtonVariant};
|
||||||
|
use crate::shared::styled_modal::StyledModal;
|
||||||
|
use crate::shared::ToNode;
|
||||||
|
use crate::Msg;
|
||||||
|
|
||||||
|
const TITLE: &str = "Warning";
|
||||||
|
const MESSAGE: &str = "Are you sure you want to continue with this action?";
|
||||||
|
const CONFIRM_TEXT: &str = "Confirm";
|
||||||
|
const CANCEL_TEXT: &str = "Cancel";
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Variant {
|
||||||
|
Primary,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StyledConfirmModal {
|
||||||
|
pub variant: Variant,
|
||||||
|
pub title: String,
|
||||||
|
pub message: String,
|
||||||
|
pub confirm_text: String,
|
||||||
|
pub cancel_text: String,
|
||||||
|
pub on_confirm: Option<EventHandler<Msg>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StyledConfirmModal {
|
||||||
|
pub fn build() -> StyledConfirmModalBuilder {
|
||||||
|
StyledConfirmModalBuilder::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToNode for StyledConfirmModal {
|
||||||
|
fn into_node(self) -> Node<Msg> {
|
||||||
|
render(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StyledConfirmModalBuilder {
|
||||||
|
variant: Option<Variant>,
|
||||||
|
title: Option<String>,
|
||||||
|
message: Option<String>,
|
||||||
|
confirm_text: Option<String>,
|
||||||
|
cancel_text: Option<String>,
|
||||||
|
on_confirm: Option<Option<EventHandler<Msg>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StyledConfirmModalBuilder {
|
||||||
|
pub fn variant(mut self, variant: Variant) -> Self {
|
||||||
|
self.variant = Some(variant);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn title<S>(mut self, title: S) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.title = Some(title.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn message<S>(mut self, message: S) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.message = Some(message.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn confirm_text<S>(mut self, confirm_text: S) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.confirm_text = Some(confirm_text.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cancel_text<S>(mut self, cancel_text: S) -> Self
|
||||||
|
where
|
||||||
|
S: Into<String>,
|
||||||
|
{
|
||||||
|
self.cancel_text = Some(cancel_text.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_confirm(mut self, on_confirm: EventHandler<Msg>) -> Self {
|
||||||
|
self.on_confirm = Some(Some(on_confirm));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> StyledConfirmModal {
|
||||||
|
StyledConfirmModal {
|
||||||
|
variant: self.variant.unwrap_or_else(|| Variant::Primary),
|
||||||
|
title: self.title.unwrap_or_else(|| TITLE.to_string()),
|
||||||
|
message: self.message.unwrap_or_else(|| MESSAGE.to_string()),
|
||||||
|
confirm_text: self
|
||||||
|
.confirm_text
|
||||||
|
.unwrap_or_else(|| CONFIRM_TEXT.to_string()),
|
||||||
|
cancel_text: self.cancel_text.unwrap_or_else(|| CANCEL_TEXT.to_string()),
|
||||||
|
on_confirm: self.on_confirm.unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(values: StyledConfirmModal) -> Node<Msg> {
|
||||||
|
let StyledConfirmModal {
|
||||||
|
variant,
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
confirm_text,
|
||||||
|
cancel_text,
|
||||||
|
on_confirm,
|
||||||
|
} = values;
|
||||||
|
|
||||||
|
let message_node = match message {
|
||||||
|
_ if message.is_empty() => empty![],
|
||||||
|
_ => p![attrs![At::Class => "message"], message],
|
||||||
|
};
|
||||||
|
|
||||||
|
let confirm_button = match on_confirm {
|
||||||
|
Some(handler) => StyledButton::build()
|
||||||
|
.text(confirm_text)
|
||||||
|
.on_click(handler)
|
||||||
|
.build()
|
||||||
|
.into_node(),
|
||||||
|
_ => StyledButton::build().text(confirm_text).build().into_node(),
|
||||||
|
};
|
||||||
|
let cancel_button = StyledButton::build()
|
||||||
|
.text(cancel_text)
|
||||||
|
.variant(ButtonVariant::Secondary)
|
||||||
|
.on_click(mouse_ev(Ev::Click, |_| Msg::ModalDropped))
|
||||||
|
.build()
|
||||||
|
.into_node();
|
||||||
|
|
||||||
|
StyledModal::build()
|
||||||
|
.width(600)
|
||||||
|
.children(vec![
|
||||||
|
div![attrs![At::Class => "title"], title],
|
||||||
|
message_node,
|
||||||
|
div![
|
||||||
|
attrs![At::Class => "actions"],
|
||||||
|
confirm_button,
|
||||||
|
cancel_button
|
||||||
|
],
|
||||||
|
])
|
||||||
|
.add_class("confirmModal".to_string())
|
||||||
|
.build()
|
||||||
|
.into_node()
|
||||||
|
}
|
@ -1,33 +1,39 @@
|
|||||||
use seed::EventHandler;
|
|
||||||
use seed::{prelude::*, *};
|
use seed::{prelude::*, *};
|
||||||
|
|
||||||
|
use crate::shared::styled_icon::{Icon, StyledIcon};
|
||||||
use crate::shared::ToNode;
|
use crate::shared::ToNode;
|
||||||
use crate::Msg;
|
use crate::Msg;
|
||||||
|
|
||||||
const TITLE: &str = "Warning";
|
#[allow(dead_code)]
|
||||||
const MESSAGE: &str = "Are you sure you want to continue with this action?";
|
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
|
||||||
const CONFIRM_TEXT: &str = "Confirm";
|
|
||||||
const CANCEL_TEXT: &str = "Cancel";
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Variant {
|
pub enum Variant {
|
||||||
Primary,
|
Center,
|
||||||
|
Aside,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Variant {
|
||||||
|
pub fn to_class_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Variant::Center => "center",
|
||||||
|
Variant::Aside => "aside",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_icon_class_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Variant::Center => "modalVariantCenter",
|
||||||
|
Variant::Aside => "modalVariantAside",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StyledModal {
|
pub struct StyledModal {
|
||||||
pub variant: Variant,
|
pub variant: Variant,
|
||||||
pub title: String,
|
pub width: usize,
|
||||||
pub message: String,
|
pub with_icon: bool,
|
||||||
pub confirm_text: String,
|
pub children: Vec<Node<Msg>>,
|
||||||
pub cancel_text: String,
|
pub class_list: Vec<String>,
|
||||||
pub on_confirm: Option<EventHandler<Msg>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StyledModal {
|
|
||||||
pub fn build() -> StyledModalBuilder {
|
|
||||||
StyledModalBuilder::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNode for StyledModal {
|
impl ToNode for StyledModal {
|
||||||
@ -36,14 +42,19 @@ impl ToNode for StyledModal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl StyledModal {
|
||||||
|
pub fn build() -> StyledModalBuilder {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct StyledModalBuilder {
|
pub struct StyledModalBuilder {
|
||||||
variant: Option<Variant>,
|
variant: Option<Variant>,
|
||||||
title: Option<String>,
|
width: Option<usize>,
|
||||||
message: Option<String>,
|
with_icon: Option<bool>,
|
||||||
confirm_text: Option<String>,
|
children: Option<Vec<Node<Msg>>>,
|
||||||
cancel_text: Option<String>,
|
class_list: Vec<String>,
|
||||||
on_confirm: Option<Option<EventHandler<Msg>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StyledModalBuilder {
|
impl StyledModalBuilder {
|
||||||
@ -52,53 +63,33 @@ impl StyledModalBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title<S>(mut self, title: S) -> Self
|
pub fn width(mut self, width: usize) -> Self {
|
||||||
where
|
self.width = Some(width);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.title = Some(title.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message<S>(mut self, message: S) -> Self
|
pub fn with_icon(mut self, with_icon: bool) -> Self {
|
||||||
where
|
self.with_icon = Some(with_icon);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.message = Some(message.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn confirm_text<S>(mut self, confirm_text: S) -> Self
|
pub fn children(mut self, children: Vec<Node<Msg>>) -> Self {
|
||||||
where
|
self.children = Some(children);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.confirm_text = Some(confirm_text.into());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cancel_text<S>(mut self, cancel_text: S) -> Self
|
pub fn add_class(mut self, name: String) -> Self {
|
||||||
where
|
self.class_list.push(name);
|
||||||
S: Into<String>,
|
|
||||||
{
|
|
||||||
self.cancel_text = Some(cancel_text.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_confirm(mut self, on_confirm: EventHandler<Msg>) -> Self {
|
|
||||||
self.on_confirm = Some(Some(on_confirm));
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> StyledModal {
|
pub fn build(self) -> StyledModal {
|
||||||
StyledModal {
|
StyledModal {
|
||||||
variant: self.variant.unwrap_or_else(|| Variant::Primary),
|
variant: self.variant.unwrap_or_else(|| Variant::Center),
|
||||||
title: self.title.unwrap_or_else(|| TITLE.to_string()),
|
width: self.width.unwrap_or_else(|| 130),
|
||||||
message: self.message.unwrap_or_else(|| MESSAGE.to_string()),
|
with_icon: self.with_icon.unwrap_or_default(),
|
||||||
confirm_text: self
|
children: self.children.unwrap_or_default(),
|
||||||
.confirm_text
|
class_list: self.class_list,
|
||||||
.unwrap_or_else(|| CONFIRM_TEXT.to_string()),
|
|
||||||
cancel_text: self.cancel_text.unwrap_or_else(|| CANCEL_TEXT.to_string()),
|
|
||||||
on_confirm: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,14 +97,41 @@ impl StyledModalBuilder {
|
|||||||
pub fn render(values: StyledModal) -> Node<Msg> {
|
pub fn render(values: StyledModal) -> Node<Msg> {
|
||||||
let StyledModal {
|
let StyledModal {
|
||||||
variant,
|
variant,
|
||||||
title,
|
width,
|
||||||
message,
|
with_icon,
|
||||||
confirm_text,
|
children,
|
||||||
cancel_text,
|
mut class_list,
|
||||||
on_confirm,
|
|
||||||
} = values;
|
} = values;
|
||||||
|
|
||||||
|
let icon = if with_icon {
|
||||||
|
StyledIcon::build(Icon::Close)
|
||||||
|
.add_class(variant.to_icon_class_name().to_string())
|
||||||
|
.build()
|
||||||
|
.into_node()
|
||||||
|
} else {
|
||||||
|
empty![]
|
||||||
|
};
|
||||||
|
|
||||||
|
let close_handler = mouse_ev(Ev::Click, |_| Msg::ModalDropped);
|
||||||
|
let body_handler = mouse_ev(Ev::Click, |ev| {
|
||||||
|
ev.stop_propagation();
|
||||||
|
Msg::NoOp
|
||||||
|
});
|
||||||
|
|
||||||
|
let clickable_class = format!("clickableOverlay {}", variant.to_class_name());
|
||||||
|
class_list.push(format!("styledModal {}", variant.to_class_name()));
|
||||||
|
let styled_modal_style = format!("max-width: {width}px", width = width);
|
||||||
div![
|
div![
|
||||||
attrs![At::Class => "modal"],
|
attrs![At::Class => "modal"],
|
||||||
div![attrs![At::Class => "styledModal"]]
|
div![
|
||||||
|
attrs![At::Class => clickable_class],
|
||||||
|
close_handler,
|
||||||
|
div![
|
||||||
|
attrs![At::Class => class_list.join(" "), At::Style => styled_modal_style],
|
||||||
|
body_handler,
|
||||||
|
icon,
|
||||||
|
children
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
14
react-client/src/App/BaseStyles.js
vendored
14
react-client/src/App/BaseStyles.js
vendored
@ -10,11 +10,11 @@ export default createGlobalStyle`
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
color: ${color.textDarkest};
|
color: ${ color.textDarkest };
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
font-size: 16px
|
font-size: 16px
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
@ -27,7 +27,7 @@ export default createGlobalStyle`
|
|||||||
optgroup,
|
optgroup,
|
||||||
select,
|
select,
|
||||||
textarea {
|
textarea {
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
*, *:after, *:before, input[type="search"] {
|
*, *:after, *:before, input[type="search"] {
|
||||||
@ -83,17 +83,17 @@ export default createGlobalStyle`
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
select option {
|
select option {
|
||||||
color: ${color.textDarkest};
|
color: ${ color.textDarkest };
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
line-height: 1.4285;
|
line-height: 1.4285;
|
||||||
a {
|
a {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${color.textLink};
|
color: ${ color.textLink };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
&:hover, &:visited, &:active {
|
&:hover, &:visited, &:active {
|
||||||
color: ${color.textLink};
|
color: ${ color.textLink };
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
4
react-client/src/App/Toast/Styles.js
vendored
4
react-client/src/App/Toast/Styles.js
vendored
@ -48,12 +48,12 @@ export const CloseIcon = styled(Icon)`
|
|||||||
export const Title = styled.div`
|
export const Title = styled.div`
|
||||||
padding-right: 22px;
|
padding-right: 22px;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Message = styled.div`
|
export const Message = styled.div`
|
||||||
padding: 8px 10px 0 0;
|
padding: 8px 10px 0 0;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
font-size: 14px
|
font-size: 14px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
@ -10,5 +10,5 @@ export const Header = styled.div`
|
|||||||
|
|
||||||
export const BoardName = styled.div`
|
export const BoardName = styled.div`
|
||||||
font-size: 24px
|
font-size: 24px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
@ -23,8 +23,8 @@ export const Username = styled.div`
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
color: ${color.textDark};
|
color: ${ color.textDark };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const CreatedAt = styled.div`
|
export const CreatedAt = styled.div`
|
||||||
|
@ -7,6 +7,6 @@ export const Comments = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const Title = styled.div`
|
export const Title = styled.div`
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
`;
|
`;
|
||||||
|
@ -5,7 +5,7 @@ import { color, font } from '../../../../shared/utils/styles';
|
|||||||
export const Title = styled.div`
|
export const Title = styled.div`
|
||||||
padding: 20px 0 6px;
|
padding: 20px 0 6px;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const EmptyLabel = styled.div`
|
export const EmptyLabel = styled.div`
|
||||||
|
@ -19,7 +19,7 @@ export const ModalContents = styled.div`
|
|||||||
|
|
||||||
export const ModalTitle = styled.div`
|
export const ModalTitle = styled.div`
|
||||||
padding-bottom: 14px;
|
padding-bottom: 14px;
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 20px
|
font-size: 20px
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -35,8 +35,8 @@ export const InputCont = styled.div`
|
|||||||
|
|
||||||
export const InputLabel = styled.div`
|
export const InputLabel = styled.div`
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
color: ${color.textMedium};
|
color: ${ color.textMedium };
|
||||||
${font.medium};
|
${ font.medium };font-weight: normal;;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@ export const TitleTextarea = styled(Textarea)`
|
|||||||
box-shadow: 0 0 0 1px transparent;
|
box-shadow: 0 0 0 1px transparent;
|
||||||
transition: background 0.1s;
|
transition: background 0.1s;
|
||||||
font-size: 24px
|
font-size: 24px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
&:hover:not(:focus) {
|
&:hover:not(:focus) {
|
||||||
background: ${color.backgroundLight};
|
background: ${ color.backgroundLight };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ErrorText = styled.div`
|
export const ErrorText = styled.div`
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
color: ${color.danger};
|
color: ${ color.danger };
|
||||||
font-size: 13px
|
font-size: 13px
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
@ -87,7 +87,7 @@ export const NoResults = styled.div`
|
|||||||
|
|
||||||
export const NoResultsTitle = styled.div`
|
export const NoResultsTitle = styled.div`
|
||||||
padding-top: 30px;
|
padding-top: 30px;
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 20px
|
font-size: 20px
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export const FormElement = styled(Form.Element)`
|
|||||||
export const FormHeading = styled.h1`
|
export const FormHeading = styled.h1`
|
||||||
padding: 6px 0 15px;
|
padding: 6px 0 15px;
|
||||||
font-size: 24px
|
font-size: 24px
|
||||||
${font.medium}; font-weight: normal;
|
${ font.medium };font-weight: normal;; font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ActionButton = styled(Button)`
|
export const ActionButton = styled(Button)`
|
||||||
|
4
react-client/src/Project/Sidebar/Styles.js
vendored
4
react-client/src/Project/Sidebar/Styles.js
vendored
@ -44,9 +44,9 @@ export const ProjectTexts = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProjectName = styled.div`
|
export const ProjectName = styled.div`
|
||||||
color: ${color.textDark};
|
color: ${ color.textDark };
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
${font.medium};
|
${ font.medium };font-weight: normal;;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ProjectCategory = styled.div`
|
export const ProjectCategory = styled.div`
|
||||||
|
@ -12,14 +12,14 @@ export const Image = styled.div`
|
|||||||
|
|
||||||
export const Letter = styled.div`
|
export const Letter = styled.div`
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: ${props => props.size}px;
|
width: ${ props => props.size }px;
|
||||||
height: ${props => props.size}px;
|
height: ${ props => props.size }px;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: ${props => props.color};
|
background: ${ props => props.color };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
${props => font.size(Math.round(props.size / 1.7))}
|
${ props => font.size(Math.round(props.size / 1.7)) }
|
||||||
& > span {
|
& > span {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -27,16 +27,16 @@ export const StyledButton = styled.button`
|
|||||||
|
|
||||||
const colored = css`
|
const colored = css`
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: ${props => color[props.variant]};
|
background: ${ props => color[props.variant] };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${props => mixin.lighten(color[props.variant], 0.15)};
|
background: ${ props => mixin.lighten(color[props.variant], 0.15) };
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background: ${props => mixin.darken(color[props.variant], 0.1)};
|
background: ${ props => mixin.darken(color[props.variant], 0.1) };
|
||||||
}
|
}
|
||||||
${props =>
|
${ props =>
|
||||||
props.isActive &&
|
props.isActive &&
|
||||||
css`
|
css`
|
||||||
background: ${mixin.darken(color[props.variant], 0.1)} !important;
|
background: ${mixin.darken(color[props.variant], 0.1)} !important;
|
||||||
@ -45,17 +45,17 @@ const colored = css`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const secondaryAndEmptyShared = css`
|
const secondaryAndEmptyShared = css`
|
||||||
color: ${color.textDark};
|
color: ${ color.textDark };
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
&:not(:disabled) {
|
&:not(:disabled) {
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${color.backgroundLight};
|
background: ${ color.backgroundLight };
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
color: ${color.primary};
|
color: ${ color.primary };
|
||||||
background: ${color.backgroundLightPrimary};
|
background: ${ color.backgroundLightPrimary };
|
||||||
}
|
}
|
||||||
${props =>
|
${ props =>
|
||||||
props.isActive &&
|
props.isActive &&
|
||||||
css`
|
css`
|
||||||
color: ${color.primary};
|
color: ${color.primary};
|
||||||
|
@ -10,7 +10,7 @@ export const StyledConfirmModal = styled(Modal)`
|
|||||||
|
|
||||||
export const Title = styled.div`
|
export const Title = styled.div`
|
||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 22px
|
font-size: 22px
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
`;
|
`;
|
||||||
|
@ -9,8 +9,8 @@ export const StyledField = styled.div`
|
|||||||
export const FieldLabel = styled.label`
|
export const FieldLabel = styled.label`
|
||||||
display: block;
|
display: block;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
color: ${color.textMedium};
|
color: ${ color.textMedium };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 13px
|
font-size: 13px
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ export const FieldTip = styled.div`
|
|||||||
export const FieldError = styled.div`
|
export const FieldError = styled.div`
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: ${color.danger};
|
color: ${ color.danger };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
font-size: 12.5px
|
font-size: 12.5px
|
||||||
`;
|
`;
|
||||||
|
@ -15,20 +15,20 @@ export const InputElement = styled.input`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 7px;
|
padding: 0 7px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: 1px solid ${color.borderLightest};
|
border: 1px solid ${ color.borderLightest };
|
||||||
color: ${color.textDarkest};
|
color: ${ color.textDarkest };
|
||||||
background: ${color.backgroundLightest};
|
background: ${ color.backgroundLightest };
|
||||||
transition: background 0.1s;
|
transition: background 0.1s;
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
${props => props.hasIcon && 'padding-left: 32px;'}
|
${ props => props.hasIcon && 'padding-left: 32px;' }
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${color.backgroundLight};
|
background: ${ color.backgroundLight };
|
||||||
}
|
}
|
||||||
&:focus {
|
&:focus {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid ${color.borderInputFocus};
|
border: 1px solid ${ color.borderInputFocus };
|
||||||
box-shadow: 0 0 0 1px ${color.borderInputFocus};
|
box-shadow: 0 0 0 1px ${ color.borderInputFocus };
|
||||||
}
|
}
|
||||||
${props =>
|
${props =>
|
||||||
props.invalid &&
|
props.invalid &&
|
||||||
|
@ -5,5 +5,5 @@ import { font } from 'shared/utils/styles';
|
|||||||
export const Content = styled.div`
|
export const Content = styled.div`
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
`;
|
`;
|
||||||
|
@ -5,16 +5,16 @@ import { color, font } from 'shared/utils/styles';
|
|||||||
export const EditorCont = styled.div`
|
export const EditorCont = styled.div`
|
||||||
.ql-toolbar.ql-snow {
|
.ql-toolbar.ql-snow {
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 4px 4px 0 0;
|
||||||
border: 1px solid ${color.borderLightest};
|
border: 1px solid ${ color.borderLightest };
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
.ql-container.ql-snow {
|
.ql-container.ql-snow {
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
border: 1px solid ${color.borderLightest};
|
border: 1px solid ${ color.borderLightest };
|
||||||
border-top: none;
|
border-top: none;
|
||||||
color: ${color.textDarkest};
|
color: ${ color.textDarkest };
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
}
|
}
|
||||||
.ql-editor {
|
.ql-editor {
|
||||||
min-height: 110px;
|
min-height: 110px;
|
||||||
|
@ -10,17 +10,17 @@ export const StyledTextarea = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px 12px 9px;
|
padding: 8px 12px 9px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: 1px solid ${color.borderLightest};
|
border: 1px solid ${ color.borderLightest };
|
||||||
color: ${color.textDarkest};
|
color: ${ color.textDarkest };
|
||||||
background: ${color.backgroundLightest};
|
background: ${ color.backgroundLightest };
|
||||||
${font.regular}
|
${ font.regular };font-weight: normal;
|
||||||
font-size: 15px
|
font-size: 15px
|
||||||
&:focus {
|
&:focus {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid ${color.borderInputFocus};
|
border: 1px solid ${ color.borderInputFocus };
|
||||||
box-shadow: 0 0 0 1px ${color.borderInputFocus};
|
box-shadow: 0 0 0 1px ${ color.borderInputFocus };
|
||||||
}
|
}
|
||||||
${props =>
|
${ props =>
|
||||||
props.invalid &&
|
props.invalid &&
|
||||||
css`
|
css`
|
||||||
&,
|
&,
|
||||||
|
16
react-client/src/shared/utils/styles.js
vendored
16
react-client/src/shared/utils/styles.js
vendored
@ -66,11 +66,11 @@ export const zIndexValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const font = {
|
export const font = {
|
||||||
regular: 'font-family: "CircularStdBook"; font-weight: normal;',
|
regular: 'font-family: "CircularStdBook";',
|
||||||
medium: 'font-family: "CircularStdMedium"; font-weight: normal;',
|
medium: 'font-family: "CircularStdMedium";',
|
||||||
bold: 'font-family: "CircularStdBold"; font-weight: normal;',
|
bold: 'font-family: "CircularStdBold";',
|
||||||
black: 'font-family: "CircularStdBlack"; font-weight: normal;',
|
black: 'font-family: "CircularStdBlack";',
|
||||||
size: size => `font-size: ${size}px;`,
|
size: size => `font-size: ${ size }px;`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mixin = {
|
export const mixin = {
|
||||||
@ -155,10 +155,10 @@ export const mixin = {
|
|||||||
`,
|
`,
|
||||||
link: (colorValue = color.textLink) => css`
|
link: (colorValue = color.textLink) => css`
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${colorValue};
|
color: ${ colorValue };
|
||||||
${font.medium}
|
${ font.medium };font-weight: normal;
|
||||||
&:hover, &:visited, &:active {
|
&:hover, &:visited, &:active {
|
||||||
color: ${colorValue};
|
color: ${ colorValue };
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
Loading…
Reference in New Issue
Block a user