Add some styling to messages, parse description

This commit is contained in:
Adrian Wozniak 2020-05-28 14:06:28 +02:00
parent c0fcd62b69
commit ce440ae08c
8 changed files with 141 additions and 31 deletions

View File

@ -122,4 +122,22 @@ nav#sidebar .linkItem > a > .linkText {
font-family: var(--font-regular);
}
.styledTooltip.messages > .messagesList > .message > .hyperlink {}
.styledTooltip.messages > .messagesList > .message > .hyperlink {
margin-top: 15px;
}
.styledTooltip.messages > .messagesList > .message > .hyperlink > a {
color: var(--primary);
}
.styledTooltip.messages > .messagesList > .message > .hyperlink > a > .styledIcon {
padding-right: 15px;
}
.styledTooltip.messages > .messagesList > .message > .actions {
margin-top: 15px;
}
.styledTooltip.messages > .messagesList > .message > .actions > .styledButton {
margin-right: 15px;
}

View File

@ -176,3 +176,7 @@ i.styledIcon.user:before {
i.styledIcon.message:before {
content: "\efac";
}
i.styledIcon.check:before {
content: "\ec4b";
}

View File

@ -127,11 +127,7 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order
fn init_load(model: &mut Model, orders: &mut impl Orders<Msg>) {
enqueue_ws_msg(
vec![
WsMsg::ProjectIssuesRequest,
WsMsg::ProjectUsersRequest,
WsMsg::IssueStatusesRequest,
],
vec![WsMsg::ProjectIssuesRequest, WsMsg::IssueStatusesRequest],
model.ws.as_ref(),
orders,
);

View File

@ -16,6 +16,7 @@ pub fn update(msg: &Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
WsMsg::UserProjectsLoad,
WsMsg::ProjectsLoad,
WsMsg::MessagesRequest,
WsMsg::ProjectUsersRequest,
],
model.ws.as_ref(),
orders,

View File

@ -1,6 +1,6 @@
use seed::{prelude::*, *};
use jirs_data::Message;
use jirs_data::{Message, MessageType};
use crate::model::Model;
use crate::shared::styled_avatar::StyledAvatar;
@ -111,25 +111,9 @@ fn messages_tooltip_popup(model: &Model) -> Node<Msg> {
});
let mut messages: Vec<Node<Msg>> = vec![];
for (idx, message) in model.messages.iter().enumerate() {
let Message {
id: _,
receiver_id: _,
sender_id: _,
summary,
description,
message_type,
hyper_link,
created_at: _,
updated_at: _,
} = message;
let message_ui = message_ui(model, message);
messages.push(div![
class!["message"],
attrs![At::Class => format!("{}", message_type)],
div![class!["summary"], summary],
div![class!["description"], description],
div![class!["hyperlink"], hyper_link],
]);
messages.push(message_ui);
if idx != model.messages.len() - 1 {
messages.push(divider());
}
@ -144,6 +128,70 @@ fn messages_tooltip_popup(model: &Model) -> Node<Msg> {
.into_node()
}
fn message_ui(model: &Model, message: &Message) -> Node<Msg> {
let Message {
id: _,
receiver_id: _,
sender_id: _,
summary,
description,
message_type,
hyper_link,
created_at: _,
updated_at: _,
} = message;
let hyperlink = if hyper_link.is_empty() {
empty![]
} else {
let link_icon = StyledIcon::build(Icon::Link).build().into_node();
div![
class!["hyperlink"],
a![attrs![At::Href => hyper_link], link_icon, hyper_link]
]
};
let message_description = parse_description(model, description.as_str());
match message_type {
MessageType::ReceivedInvitation => {
let accept = StyledButton::build()
.primary()
.text("Accept")
.active(true)
.icon(Icon::Check)
.build()
.into_node();
let reject = StyledButton::build()
.danger()
.text("Dismiss")
.icon(Icon::Close)
.active(true)
.build()
.into_node();
div![
class!["message"],
attrs![At::Class => format!("{}", message_type)],
div![class!["summary"], summary],
div![class!["description"], message_description],
div![class!["actions"], accept, reject],
]
}
MessageType::AssignedToIssue => div![
class!["message assignedToIssue"],
div![class!["summary"], summary],
div![class!["description"], message_description],
hyperlink,
],
MessageType::Mention => div![
class!["message mention"],
div![class!["summary"], summary],
div![class!["description"], message_description],
hyperlink,
],
}
}
fn about_tooltip_popup(model: &Model) -> Node<Msg> {
let visit_website = StyledButton::build()
.text("Visit Website".to_string())
@ -207,3 +255,37 @@ fn about_tooltip_popup(model: &Model) -> Node<Msg> {
.build()
.into_node()
}
fn parse_description(model: &Model, desc: &str) -> Node<Msg> {
let mut container: Node<Msg> = div![];
for word in desc.split(' ') {
let child = parse_email(word)
.and_then(|email| {
model
.users
.iter()
.enumerate()
.find(|(_, user)| user.email == email)
})
.map(|(index, user)| {
let avatar = StyledAvatar::build()
.avatar_url(user.avatar_url.as_ref().cloned().unwrap_or_default())
.user_index(index)
.size(16)
.build()
.into_node();
span![class!["mention"], avatar, user.name.as_str()]
})
.unwrap_or_else(|| span![word]);
container.add_child(child).add_text(" ");
}
container
}
fn parse_email(word: &str) -> Option<&str> {
if word.starts_with("@<") && word.ends_with(">") {
Some(&word[2..(word.len() - 1)])
} else {
None
}
}

View File

@ -52,9 +52,9 @@ impl StyledButtonBuilder {
self.variant(Variant::Success)
}
// pub fn danger(self) -> Self {
// self.variant(Variant::Danger)
// }
pub fn danger(self) -> Self {
self.variant(Variant::Danger)
}
pub fn secondary(self) -> Self {
self.variant(Variant::Secondary)

View File

@ -30,6 +30,7 @@ pub enum Icon {
Issues,
Settings,
Close,
Check,
Feedback,
Trash,
Github,
@ -83,6 +84,7 @@ impl std::fmt::Display for Icon {
Icon::Issues => "issues",
Icon::Settings => "settings",
Icon::Close => "close",
Icon::Check => "check",
Icon::Feedback => "feedback",
Icon::Trash => "trash",
Icon::Github => "github",

View File

@ -178,12 +178,19 @@ VALUES (
'Bar',
'Suspendisse tincidunt euismod justo, at porttitor dolor fermentum ut. Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse maximus sed ex ut sollicitudin. Etiam volutpat ultricies vehicula. Sed at est in mauris cursus fermentum. Duis et lacus metus. Sed ut egestas ipsum, ac consectetur metus. In felis diam, cursus eu felis non, tincidunt elementum lacus. Etiam et massa odio. Vestibulum ornare felis maximus facilisis semper.',
'assigned_to_issue',
'/issue/1',
'/issues/1',
now(), now()
), (
1, 1,
'Foz Baz',
'Suspendisse quam ligula, @<John Doe> auctor vel diam sit amet, tincidunt venenatis justo. Vestibulum tincidunt mauris et est iaculis, vel consequat turpis porta. Integer eu urna quis diam pharetra lobortis vel nec lacus. Donec ac mollis risus. Morbi pellentesque pulvinar libero, sit amet finibus risus fermentum ac. Vivamus imperdiet mi congue ligula luctus condimentum. Duis arcu turpis, dignissim quis purus eget, dignissim elementum risus. Donec mattis rhoncus lorem quis blandit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dignissim tellus eu cursus finibus. Ut pellentesque mi at eros maximus, eu tempor est sodales. Mauris vel feugiat ligula. Integer quis interdum velit, at iaculis arcu. Duis leo sapien, egestas eget erat id, fringilla pulvinar nulla. Nam sollicitudin ullamcorper finibus.',
'mention',
'',
now(), now()
), (
2, 1,
'Foz Baz',
'Suspendisse quam ligula, @<John Doe> auctor vel diam sit amet, tincidunt venenatis justo. Vestibulum tincidunt mauris et est iaculis, vel consequat turpis porta. Integer eu urna quis diam pharetra lobortis vel nec lacus. Donec ac mollis risus. Morbi pellentesque pulvinar libero, sit amet finibus risus fermentum ac. Vivamus imperdiet mi congue ligula luctus condimentum. Duis arcu turpis, dignissim quis purus eget, dignissim elementum risus. Donec mattis rhoncus lorem quis blandit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dignissim tellus eu cursus finibus. Ut pellentesque mi at eros maximus, eu tempor est sodales. Mauris vel feugiat ligula. Integer quis interdum velit, at iaculis arcu. Duis leo sapien, egestas eget erat id, fringilla pulvinar nulla. Nam sollicitudin ullamcorper finibus.',
'Hello world',
'Suspendisse quam ligula, @<kate@exampe.com> auctor vel diam sit amet, tincidunt venenatis justo. Vestibulum tincidunt mauris et est iaculis, vel consequat turpis porta. Integer eu urna quis diam pharetra lobortis vel nec lacus. Donec ac mollis risus. Morbi pellentesque pulvinar libero, sit amet finibus risus fermentum ac. Vivamus imperdiet mi congue ligula luctus condimentum. Duis arcu turpis, dignissim quis purus eget, dignissim elementum risus. Donec mattis rhoncus lorem quis blandit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec dignissim tellus eu cursus finibus. Ut pellentesque mi at eros maximus, eu tempor est sodales. Mauris vel feugiat ligula. Integer quis interdum velit, at iaculis arcu. Duis leo sapien, egestas eget erat id, fringilla pulvinar nulla. Nam sollicitudin ullamcorper finibus.',
'mention',
'',
now(), now()