Start notifications. Disable work in progress features

This commit is contained in:
Adrian Wozniak 2020-05-20 15:41:54 +02:00
parent 778f56cf8d
commit 92e129115a
9 changed files with 105 additions and 33 deletions

View File

@ -62,19 +62,15 @@ aside#navbar-left .item > .styledIcon > .styledAvatar {
height: 27px; height: 27px;
} }
aside#navbar-left > .item > .styledIcon.search { aside#navbar-left > .item > i.styledIcon.search {
font-size: 22px; font-size: 22px;
color: #DEEBFE; color: var(--asideIcon);
} }
aside#navbar-left > .item > .styledIcon.plus { aside#navbar-left > .item > i.styledIcon,
aside#navbar-left > .bottom > .item > i.styledIcon {
font-size: 27px; font-size: 27px;
color: #DEEBFE; color: var(--asideIcon);
}
aside#navbar-left .item > .styledIcon.help {
font-size: 27px;
color: #DEEBFE;
} }
aside#navbar-left .item > .itemText { aside#navbar-left .item > .itemText {
@ -97,7 +93,8 @@ aside#navbar-left > .bottom {
width: 100%; width: 100%;
} }
aside#navbar-left > .bottom > .aboutTooltip { aside#navbar-left > .bottom > .aboutTooltip > .item > i.styledIcon {
color: var(--asideIcon);
} }
aside#navbar-left:hover .item > .itemText { aside#navbar-left:hover .item > .itemText {

View File

@ -73,6 +73,12 @@ nav#sidebar .linkItem > a {
nav#sidebar .linkItem.notAllowed, nav#sidebar .linkItem.notAllowed > a { nav#sidebar .linkItem.notAllowed, nav#sidebar .linkItem.notAllowed > a {
cursor: not-allowed; cursor: not-allowed;
color: var(--textDark);
}
nav#sidebar .linkItem.notAllowed, nav#sidebar .linkItem.notAllowed > a > .styledIcon {
cursor: not-allowed;
color: var(--textDark);
} }
nav#sidebar .linkItem:hover { nav#sidebar .linkItem:hover {

View File

@ -168,3 +168,11 @@ i.styledIcon.arrowRight:before {
font-family: "jira"; font-family: "jira";
content: "\e91f"; content: "\e91f";
} }
i.styledIcon.user:before {
content: "\ec8e";
}
i.styledIcon.message:before {
content: "\efac";
}

View File

@ -1,12 +1,19 @@
.styledImageInput { .styledImageInput {
} }
.styledImageInput > .label {
width: 120px;
height: 120px;
margin: 0 auto;
display: block;
}
.styledImageInput > .label > .mask { .styledImageInput > .label > .mask {
display: block; display: block;
width: 120px; width: 120px;
height: 120px; height: 120px;
margin: 0 auto;
border-radius: 60px; border-radius: 60px;
cursor: pointer;
} }
.styledImageInput > .input { .styledImageInput > .input {

View File

@ -18,6 +18,7 @@
--borderLightest: rgb(223, 225, 230); --borderLightest: rgb(223, 225, 230);
--borderLight: rgb(193, 199, 208); --borderLight: rgb(193, 199, 208);
--borderInputFocus: rgb(76, 154, 255); --borderInputFocus: rgb(76, 154, 255);
--asideIcon: rgb(222, 235, 254);
} }
:root { :root {

View File

@ -1,5 +1,6 @@
use std::collections::hash_map::HashMap; use std::collections::hash_map::HashMap;
use seed::browser::web_socket::WebSocket;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
@ -13,7 +14,6 @@ use crate::shared::styled_image_input::StyledImageInputState;
use crate::shared::styled_input::StyledInputState; use crate::shared::styled_input::StyledInputState;
use crate::shared::styled_select::StyledSelectState; use crate::shared::styled_select::StyledSelectState;
use crate::{EditIssueModalSection, FieldId, ProjectFieldId /*HOST_URL*/}; use crate::{EditIssueModalSection, FieldId, ProjectFieldId /*HOST_URL*/};
use seed::browser::web_socket::WebSocket;
#[derive(Clone, Debug, PartialOrd, PartialEq)] #[derive(Clone, Debug, PartialOrd, PartialEq)]
pub enum ModalType { pub enum ModalType {
@ -460,6 +460,7 @@ pub struct Model {
pub users: Vec<User>, pub users: Vec<User>,
pub comments: Vec<Comment>, pub comments: Vec<Comment>,
pub issue_statuses: Vec<IssueStatus>, pub issue_statuses: Vec<IssueStatus>,
pub messages: Vec<Message>,
} }
impl Model { impl Model {
@ -483,6 +484,17 @@ impl Model {
comments: vec![], comments: vec![],
about_tooltip_visible: false, about_tooltip_visible: false,
issue_statuses: vec![], issue_statuses: vec![],
messages: vec![Message {
id: 0,
receiver_id: 1,
sender_id: 2,
summary: "You have been invited".to_string(),
description: "You have been invited to project A".to_string(),
message_type: "project-invitation".to_string(),
hyper_link: "/project/1".to_string(),
created_at: chrono::NaiveDateTime::from_timestamp(4567890, 123),
updated_at: chrono::NaiveDateTime::from_timestamp(1234567, 098),
}],
} }
} }
} }

View File

@ -3,10 +3,26 @@ use seed::{prelude::*, *};
use crate::model::Model; use crate::model::Model;
use crate::shared::styled_avatar::StyledAvatar; use crate::shared::styled_avatar::StyledAvatar;
use crate::shared::styled_button::StyledButton; use crate::shared::styled_button::StyledButton;
use crate::shared::styled_icon::Icon; use crate::shared::styled_icon::{Icon, StyledIcon};
use crate::shared::{styled_tooltip, ToNode}; use crate::shared::{styled_tooltip, ToNode};
use crate::Msg; use crate::Msg;
trait IntoNavItemIcon {
fn into_nav_item_icon(self) -> Node<Msg>;
}
impl IntoNavItemIcon for Node<Msg> {
fn into_nav_item_icon(self) -> Node<Msg> {
self
}
}
impl IntoNavItemIcon for Icon {
fn into_nav_item_icon(self) -> Node<Msg> {
StyledIcon::build(self).size(21).build().into_node()
}
}
pub fn render(model: &Model) -> Vec<Node<Msg>> { pub fn render(model: &Model) -> Vec<Node<Msg>> {
let logo_svg = Node::from_html(include_str!("../../static/logo.svg")); let logo_svg = Node::from_html(include_str!("../../static/logo.svg"));
@ -20,7 +36,13 @@ pub fn render(model: &Model) -> Vec<Node<Msg>> {
.build() .build()
.into_node() .into_node()
], ],
_ => i![attrs![At::Class => format!("styledIcon {}", Icon::Plus)]], _ => StyledIcon::build(Icon::User).size(21).build().into_node(),
};
let messages = if model.messages.is_empty() {
empty![]
} else {
navbar_left_item("Messages", Icon::Message, None)
}; };
vec![ vec![
@ -31,30 +53,28 @@ pub fn render(model: &Model) -> Vec<Node<Msg>> {
attrs![At::Class => "logoLink", At::Href => "/"], attrs![At::Class => "logoLink", At::Href => "/"],
div![attrs![At::Class => "styledLogo"], logo_svg] div![attrs![At::Class => "styledLogo"], logo_svg]
], ],
navbar_left_item(model, "Search issues", Icon::Search), navbar_left_item("Search issues", Icon::Search, None),
a![ navbar_left_item("Create Issue", Icon::Plus, Some("/add-issue")),
attrs![At::Class => "item"; At::Href=> "/add-issue"; ],
i![attrs![At::Class => format!("styledIcon {}", Icon::Plus)]],
span![attrs![At::Class => "itemText"], "Create Issue"]
],
div![ div![
class!["bottom"], class!["bottom"],
div![ navbar_left_item("Profile", user_icon, Some("/profile")),
class!["item"], messages,
attrs![At::Href=> "/profile"], about_tooltip(model, navbar_left_item("About", Icon::Help, None)),
user_icon,
span![class!["itemText"], "Profile"]
],
about_tooltip(model, navbar_left_item(model, "About", Icon::Help)),
], ],
], ],
] ]
} }
fn navbar_left_item(_model: &Model, text: &str, logo: Icon) -> Node<Msg> { fn navbar_left_item<I>(text: &str, icon: I, href: Option<&str>) -> Node<Msg>
div![ where
I: IntoNavItemIcon,
{
let styled_icon = icon.into_nav_item_icon();
let href = href.unwrap_or_else(|| "#");
a![
class!["item"], class!["item"],
i![attrs![At::Class => format!("styledIcon {}", logo)]], attrs![At::Href => href],
styled_icon,
span![class!["itemText"], text] span![class!["itemText"], text]
] ]
} }

View File

@ -41,6 +41,8 @@ pub enum Icon {
ArrowLeft, ArrowLeft,
ArrowRight, ArrowRight,
Cop, Cop,
Message,
User,
} }
impl Icon { impl Icon {
@ -92,6 +94,8 @@ impl std::fmt::Display for Icon {
Icon::ArrowLeft => "arrowLeft", Icon::ArrowLeft => "arrowLeft",
Icon::ArrowRight => "arrowRight", Icon::ArrowRight => "arrowRight",
Icon::Cop => "cop", Icon::Cop => "cop",
Icon::Message => "message",
Icon::User => "user",
}; };
f.write_str(code) f.write_str(code)
} }

View File

@ -26,6 +26,7 @@ pub type TokenId = i32;
pub type IssueStatusId = i32; pub type IssueStatusId = i32;
pub type InvitationId = i32; pub type InvitationId = i32;
pub type Position = i32; pub type Position = i32;
pub type MessageId = i32;
pub type EmailString = String; pub type EmailString = String;
pub type UsernameString = String; pub type UsernameString = String;
pub type TitleString = String; pub type TitleString = String;
@ -506,8 +507,8 @@ pub struct UpdateIssuePayload {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct IssueAssignee { pub struct IssueAssignee {
pub id: i32, pub id: i32,
pub issue_id: i32, pub issue_id: IssueId,
pub user_id: i32, pub user_id: UserId,
pub created_at: NaiveDateTime, pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime, pub updated_at: NaiveDateTime,
} }
@ -532,6 +533,19 @@ impl From<Issue> for UpdateIssuePayload {
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct Message {
pub id: MessageId,
pub receiver_id: UserId,
pub sender_id: UserId,
pub summary: String,
pub description: String,
pub message_type: String,
pub hyper_link: String,
pub created_at: NaiveDateTime,
pub updated_at: NaiveDateTime,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct CreateCommentPayload { pub struct CreateCommentPayload {
pub user_id: Option<UserId>, pub user_id: Option<UserId>,
@ -541,7 +555,7 @@ pub struct CreateCommentPayload {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct UpdateCommentPayload { pub struct UpdateCommentPayload {
pub id: i32, pub id: CommentId,
pub body: String, pub body: String,
} }
@ -719,4 +733,7 @@ pub enum WsMsg {
AvatarUrlChanged(UserId, String), AvatarUrlChanged(UserId, String),
ProfileUpdate(EmailString, UsernameString), ProfileUpdate(EmailString, UsernameString),
ProfileUpdated, ProfileUpdated,
// messages
Message(Message),
} }