Add some filters

This commit is contained in:
Adrian Woźniak 2020-03-31 14:28:30 +02:00
parent 4ecba98a7a
commit 8ee9cc8957
54 changed files with 496 additions and 107 deletions

View File

@ -1,3 +1,13 @@
#[package]
#name = "jirs"
#version = "0.1.0"
#authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
#edition = "2018"
#description = "JIRS (Simplified JIRA in Rust)"
#repository = "https://gitlab.com/adrian.wozniak/jirs"
#license = "MPL-2.0"
#license-file = "./LICENSE"
[workspace]
members = [
"./jirs-cli",

View File

@ -3,6 +3,10 @@ name = "jirs-client"
version = "0.1.0"
authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
edition = "2018"
description = "JIRS (Simplified JIRA in Rust) WASM client"
repository = "https://gitlab.com/adrian.wozniak/jirs"
license = "MPL-2.0"
#license-file = "../LICENSE"
[lib]
crate-type = ["cdylib", "rlib"]

1
jirs-client/LICENSE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE

View File

@ -68,7 +68,123 @@
margin-left: 6px;
}
#projectPage > #projectBoardFilters > #clearAllFilters {
height: 32px;
line-height: 32px;
margin-left: 15px;
padding-left: 12px;
border-left: 1px solid var(--borderLightest);
color: var(--textDark);
font-size: 14.5px;
cursor: pointer;
user-select: none;
}
#projectPage > #projectBoardFilters > #clearAllFilters:hover {
color: var(--textMedium);
}
#projectPage > #projectBoardLists {
display: flex;
margin: 26px -5px 0;
}
#projectPage > #projectBoardLists > .list {
display: flex;
flex-direction: column;
margin: 0 5px;
min-height: 400px;
width: 25%;
border-radius: 3px;
background: var(--backgroundLightest);
}
#projectPage > #projectBoardLists > .list > .title {
padding: 13px 10px 17px;
text-transform: uppercase;
color: var(--textMedium);
font-size: 12.5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
#projectPage > #projectBoardLists > .list > .title > .issuesCount {
text-transform: lowercase;
font-size: 13px;
}
#projectPage > #projectBoardLists > .list > .issues {
height: 100%;
padding: 0 5px;
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink {
display: block;
margin-bottom: 5px;
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue {
padding: 10px;
border-radius: 3px;
background: #fff;
box-shadow: 0 1px 2px 0 rgba(9, 30, 66, 0.25);
transition: background 0.1s;
cursor: pointer;
user-select: none;
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue.isBeingDragged {
transform: rotate(3deg);
box-shadow: 5px 10px 30px 0 rgba(9, 30, 66, 0.15);
}
@media (max-width: 1100px) {
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue {
padding: 10px 8px;
}
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue:hover {
background: var(--backgroundLight);
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .title {
padding-bottom: 11px;
font-size: 15px;
}
@media (max-width: 1100px) {
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .title {
font-size: 14.5px
}
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom {
display: flex;
justify-content: space-between;
align-items: center;
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > div {
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > div > .issueTypeIcon {
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > div > .issuePriorityIcon {
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > .assignees {
display: flex;
flex-direction: row-reverse;
margin-left: 2px;
}
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > .assignees > .assigneeAvatar,
#projectPage > #projectBoardLists > .list > .issues > .issueLink > .issue > .bottom > .assignees > .styledAvatar {
margin-left: -2px;
box-shadow: 0 0 0 2px #fff;
}
@media (max-width: 1100px) {

View File

@ -27,6 +27,7 @@ pub enum Msg {
ProjectAvatarFilterChanged(UserId, AvatarFilterActive),
ProjectToggleOnlyMy,
ProjectToggleRecentlyUpdated,
ProjectClearFilters,
}
fn update(msg: Msg, model: &mut model::Model, orders: &mut impl Orders<Msg>) {

View File

@ -171,3 +171,13 @@ impl std::fmt::Display for Icon {
f.write_str(code)
}
}
impl From<IssueType> for Icon {
fn from(t: IssueType) -> Self {
match t {
IssueType::Task => Icon::Task,
IssueType::Bug => Icon::Bug,
IssueType::Story => Icon::Story,
}
}
}

View File

@ -6,6 +6,7 @@ use crate::shared::styled_button::{StyledButton, Variant};
use crate::shared::styled_input::StyledInput;
use crate::shared::{host_client, inner_layout, ToNode};
use crate::Msg;
use jirs_data::{FullProject, Issue, IssuePriority, IssueStatus, IssueType};
pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Orders<Msg>) {
match msg {
@ -44,6 +45,12 @@ pub fn update(msg: Msg, model: &mut crate::model::Model, orders: &mut impl Order
model.project_page.recenlty_updated_filter =
!model.project_page.recenlty_updated_filter;
}
Msg::ProjectClearFilters => {
let pp = &mut model.project_page;
pp.active_avatar_filters = vec![];
pp.recenlty_updated_filter = false;
pp.only_my_filter = false;
}
_ => (),
}
}
@ -105,6 +112,8 @@ fn project_board_filters(model: &Model) -> Node<Msg> {
}
.into_node();
let project_page = &model.project_page;
let only_my = StyledButton {
variant: Variant::Empty,
icon_only: false,
@ -120,19 +129,32 @@ fn project_board_filters(model: &Model) -> Node<Msg> {
variant: Variant::Empty,
icon_only: false,
disabled: false,
active: model.project_page.only_my_filter,
active: model.project_page.recenlty_updated_filter,
text: Some("Recently Updated".to_string()),
icon: None,
on_click: Some(mouse_ev(Ev::Click, |_| Msg::ProjectToggleRecentlyUpdated)),
}
.into_node();
let clear_all = match project_page.only_my_filter
|| project_page.recenlty_updated_filter
|| !project_page.active_avatar_filters.is_empty()
{
true => button![
id!["clearAllFilters"],
"Clear all",
mouse_ev(Ev::Click, |_| Msg::ProjectClearFilters),
],
false => empty![],
};
div![
id!["projectBoardFilters"],
search_input,
avatars_filters(model),
only_my,
recently_updated,
clear_all
]
}
@ -169,5 +191,88 @@ fn avatars_filters(model: &Model) -> Node<Msg> {
}
fn project_board_lists(model: &Model) -> Node<Msg> {
div![id!["projectBoardLists"]]
use jirs_data::IssueStatus;
div![
id!["projectBoardLists"],
project_issue_list(model, IssueStatus::Backlog),
project_issue_list(model, IssueStatus::Selected),
project_issue_list(model, IssueStatus::InProgress),
project_issue_list(model, IssueStatus::Done),
]
}
fn project_issue_list(model: &Model, status: jirs_data::IssueStatus) -> Node<Msg> {
let project = match model.project.as_ref() {
Some(p) => p,
_ => return empty![],
};
let issues: Vec<Node<Msg>> = project
.issues
.iter()
.filter(|issue| status.match_name(issue.status.as_str()))
.map(|issue| project_issue(model, project, issue))
.collect();
let label = status.to_label();
div![
attrs![At::Class => "list"],
div![
attrs![At::Class => "title"],
label,
div![attrs![At::Class => "issuesCount"]]
],
div![attrs![At::Class => "issues"], issues]
]
}
fn project_issue(_model: &Model, project: &FullProject, issue: &Issue) -> Node<Msg> {
let avatars: Vec<Node<Msg>> = project
.users
.iter()
.filter(|user| issue.user_ids.contains(&user.id))
.map(|user| {
StyledAvatar {
avatar_url: user.avatar_url.clone(),
size: 24,
name: user.name.clone(),
on_click: None,
}
.into_node()
})
.collect();
let mut issue_type_icon = match issue.issue_type.parse::<IssueType>() {
Ok(icon) => {
let mut node = crate::shared::styled_icon(icon.into());
node.add_style(
St::Color,
format!("var(--{issue_type})", issue_type = issue.issue_type),
);
node
}
Err(e) => span![format!("{}", e)],
};
let priority_icon = match issue.priority.parse::<IssuePriority>() {
Ok(IssuePriority::Low) | Ok(IssuePriority::Lowest) => {
crate::shared::styled_icon(Icon::ArrowDown)
}
Ok(_) => crate::shared::styled_icon(Icon::ArrowUp),
Err(e) => span![e.clone()],
};
a![
attrs![At::Class => "issueLink"],
div![
attrs![At::Class => "issue"],
p![attrs![At::Class => "title"], issue.title,],
div![
attrs![At::Class => "bottom"],
div![
// <IssueTypeIcon type={issue.type} />
div![attrs![At::Class => "issueTypeIcon"], issue_type_icon],
// <IssuePriorityIcon priority={issue.priority} top={-1} left={4} />
div![attrs![At::Class => "issuePriorityIcon"], priority_icon]
],
div![attrs![At::Class => "assignees"], avatars,],
]
]
]
}

View File

@ -3,6 +3,10 @@ name = "jirs-data"
version = "0.1.0"
authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
edition = "2018"
description = "JIRS (Simplified JIRA in Rust) shared data types"
repository = "https://gitlab.com/adrian.wozniak/jirs"
license = "MPL-2.0"
#license-file = "../LICENSE"
[lib]
name = "jirs_data"

1
jirs-data/LICENSE Symbolic link
View File

@ -0,0 +1 @@
./LICENSE

View File

@ -1,5 +1,6 @@
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use uuid::Uuid;
pub trait ResponseData {
@ -8,6 +9,126 @@ pub trait ResponseData {
fn into_response(self) -> Self::Response;
}
#[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum IssueType {
Task,
Bug,
Story,
}
impl FromStr for IssueType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"task" => Ok(IssueType::Task),
"bug" => Ok(IssueType::Bug),
"story" => Ok(IssueType::Story),
_ => Err(format!("Unknown type {:?}", s)),
}
}
}
impl ToString for IssueType {
fn to_string(&self) -> String {
match self {
IssueType::Task => "Task",
IssueType::Bug => "Bug",
IssueType::Story => "Story",
}
.to_string()
}
}
#[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)]
pub enum IssueStatus {
Backlog,
Selected,
InProgress,
Done,
}
impl IssueStatus {
pub fn to_label(&self) -> &str {
match self {
IssueStatus::Backlog => "Backlog",
IssueStatus::Selected => "Selected for development",
IssueStatus::InProgress => "In Progress",
IssueStatus::Done => "Done",
}
}
pub fn to_payload(&self) -> &str {
match self {
IssueStatus::Backlog => "backlog",
IssueStatus::Selected => "selected",
IssueStatus::InProgress => "in_progress",
IssueStatus::Done => "done",
}
}
#[deprecated]
pub fn to_deprecated_payload(&self) -> &str {
match self {
IssueStatus::Backlog => "backlog",
IssueStatus::Selected => "selected",
IssueStatus::InProgress => "inprogress",
IssueStatus::Done => "done",
}
}
pub fn match_name(&self, name: &str) -> bool {
self.to_payload() == name || self.to_deprecated_payload() == name
}
}
#[derive(Clone, Deserialize, Serialize, Debug, PartialOrd, PartialEq)]
pub enum IssuePriority {
Highest,
High,
Medium,
Low,
Lowest,
}
impl FromStr for IssuePriority {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"highest" => Ok(IssuePriority::Highest),
"high" => Ok(IssuePriority::High),
"medium" => Ok(IssuePriority::Medium),
"low" => Ok(IssuePriority::Low),
"lowest" => Ok(IssuePriority::Lowest),
_ => Err(format!("Unknown priority {}", s)),
}
}
}
impl IssuePriority {
pub fn to_text_value(&self) -> &str {
match self {
IssuePriority::Highest => "5",
IssuePriority::High => "4",
IssuePriority::Medium => "3",
IssuePriority::Low => "2",
IssuePriority::Lowest => "1",
}
}
pub fn to_value(&self) -> i32 {
match self {
IssuePriority::Highest => 5,
IssuePriority::High => 4,
IssuePriority::Medium => 3,
IssuePriority::Low => 2,
IssuePriority::Lowest => 1,
}
}
}
#[derive(Clone, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ErrorResponse {

View File

@ -3,6 +3,10 @@ name = "jirs-server"
version = "0.1.0"
authors = ["Adrian Wozniak <adrian.wozniak@ita-prog.pl>"]
edition = "2018"
description = "JIRS (Simplified JIRA in Rust) Actix server"
repository = "https://gitlab.com/adrian.wozniak/jirs"
license = "MPL-2.0"
#license-file = "../LICENSE"
[[bin]]
name = "jirs_server"

1
jirs-server/LICENSE Symbolic link
View File

@ -0,0 +1 @@
./LICENSE

View File

@ -13,7 +13,7 @@ export default createGlobalStyle`
color: ${color.textDarkest};
-webkit-tap-highlight-color: transparent;
line-height: 1.2;
${font.size(16)}
font-size: 16px
${font.regular}
}

View File

@ -47,13 +47,13 @@ export const CloseIcon = styled(Icon)`
export const Title = styled.div`
padding-right: 22px;
${font.size(15)}
font-size: 15px
${font.medium}
`;
export const Message = styled.div`
padding: 8px 10px 0 0;
white-space: pre-wrap;
${font.size(14)}
font-size: 14px
${font.medium}
`;

View File

@ -25,7 +25,8 @@ export const AvatarIsActiveBorder = styled.div`
margin-left: -2px;
border-radius: 50%;
transition: transform 0.1s;
${mixin.clickable};
cursor: pointer;
user-select: none;;
${props => props.isActive && `box-shadow: 0 0 0 4px ${color.primary}`}
&:hover {
transform: translateY(-5px);
@ -47,8 +48,9 @@ export const ClearAll = styled.div`
padding-left: 12px;
border-left: 1px solid ${color.borderLightest};
color: ${color.textDark};
${font.size(14.5)}
${mixin.clickable}
font-size: 14.5px
cursor: pointer;
user-select: none;
&:hover {
color: ${color.textMedium};
}

View File

@ -9,6 +9,6 @@ export const Header = styled.div`
`;
export const BoardName = styled.div`
${font.size(24)}
font-size: 24px
${font.medium}
`;

View File

@ -5,7 +5,8 @@ import { color, font, mixin } from 'shared/utils/styles';
export const User = styled.div`
display: flex;
align-items: center;
${mixin.clickable}
cursor: pointer;
user-select: none;
${props =>
props.isSelectValue &&
css`
@ -22,5 +23,5 @@ export const User = styled.div`
export const Username = styled.div`
padding: 0 3px 0 8px;
${font.size(14.5)}
font-size: 14.5px
`;

View File

@ -6,7 +6,7 @@ import { Avatar } from 'shared/components';
export const Comment = styled.div`
position: relative;
margin-top: 25px;
${font.size(15)}
font-size: 15px
`;
export const UserAvatar = styled(Avatar)`
@ -31,7 +31,7 @@ export const CreatedAt = styled.div`
display: inline-block;
padding-bottom: 10px;
color: ${color.textDark};
${font.size(14.5)}
font-size: 14.5px
`;
export const Body = styled.p`
@ -43,8 +43,9 @@ const actionLinkStyles = css`
display: inline-block;
padding: 2px 0;
color: ${color.textMedium};
${font.size(14.5)}
${mixin.clickable}
font-size: 14.5px
cursor: pointer;
user-select: none;
&:hover {
text-decoration: underline;
}

View File

@ -7,7 +7,7 @@ export const Tip = styled.div`
align-items: center;
padding-top: 8px;
color: ${color.textMedium};
${font.size(13)}
font-size: 13px
strong {
padding-right: 4px;
}
@ -23,5 +23,5 @@ export const TipLetter = styled.span`
color: ${color.textDarkest};
background: ${color.backgroundMedium};
${font.bold}
${font.size(12)}
font-size: 12px
`;

View File

@ -6,7 +6,7 @@ import { Avatar } from 'shared/components';
export const Create = styled.div`
position: relative;
margin-top: 25px;
${font.size(15)}
font-size: 15px
`;
export const UserAvatar = styled(Avatar)`
@ -24,7 +24,8 @@ export const FakeTextarea = styled.div`
border-radius: 4px;
border: 1px solid ${color.borderLightest};
color: ${color.textLight};
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
border: 1px solid ${color.borderLight};
}

View File

@ -8,5 +8,5 @@ export const Comments = styled.div`
export const Title = styled.div`
${font.medium}
${font.size(15)}
font-size: 15px
`;

View File

@ -8,5 +8,5 @@ export const Dates = styled.div`
line-height: 22px;
border-top: 1px solid ${color.borderLightest};
color: ${color.textMedium};
${font.size(13)}
font-size: 13px
`;

View File

@ -4,7 +4,7 @@ import { color, font, mixin } from 'shared/utils/styles';
export const Title = styled.div`
padding: 20px 0 6px;
${font.size(15)}
font-size: 15px
${font.medium}
`;
@ -14,8 +14,9 @@ export const EmptyLabel = styled.div`
border-radius: 3px;
color: ${color.textMedium}
transition: background 0.1s;
${font.size(15)}
${mixin.clickable}
font-size: 15px
cursor: pointer;
user-select: none;
&:hover {
background: ${color.backgroundLight};
}

View File

@ -6,7 +6,8 @@ export const TrackingLink = styled.div`
padding: 4px 4px 2px 0;
border-radius: 4px;
transition: background 0.1s;
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
background: ${color.backgroundLight};
}
@ -19,7 +20,7 @@ export const ModalContents = styled.div`
export const ModalTitle = styled.div`
padding-bottom: 14px;
${font.medium}
${font.size(20)}
font-size: 20px
`;
export const Inputs = styled.div`
@ -36,7 +37,7 @@ export const InputLabel = styled.div`
padding-bottom: 5px;
color: ${color.textMedium};
${font.medium};
${font.size(13)};
font-size: 13px;
`;
export const Actions = styled.div`

View File

@ -35,5 +35,5 @@ export const Values = styled.div`
display: flex;
justify-content: space-between;
padding-top: 3px;
${font.size(14.5)};
font-size: 14.5px;
`;

View File

@ -19,5 +19,5 @@ export const Priority = styled.div`
export const Label = styled.div`
padding: 0 3px 0 8px;
${font.size(14.5)}
font-size: 14.5px
`;

View File

@ -35,6 +35,6 @@ export const SectionTitle = styled.div`
margin: 24px 0 5px;
text-transform: uppercase;
color: ${color.textMedium};
${font.size(12.5)}
font-size: 12.5px
${font.bold}
`;

View File

@ -16,7 +16,7 @@ export const TitleTextarea = styled(Textarea)`
border: 1px solid transparent;
box-shadow: 0 0 0 1px transparent;
transition: background 0.1s;
${font.size(24)}
font-size: 24px
${font.medium}
&:hover:not(:focus) {
background: ${color.backgroundLight};
@ -27,6 +27,6 @@ export const TitleTextarea = styled(Textarea)`
export const ErrorText = styled.div`
padding-top: 4px;
color: ${color.danger};
${font.size(13)}
font-size: 13px
${font.medium}
`;

View File

@ -7,7 +7,7 @@ export const TypeButton = styled(Button)`
text-transform: uppercase;
letter-spacing: 0.5px;
color: ${color.textMedium};
${font.size(13)}
font-size: 13px
`;
export const Type = styled.div`
@ -17,5 +17,5 @@ export const Type = styled.div`
export const TypeLabel = styled.div`
padding: 0 5px 0 7px;
${font.size(15)}
font-size: 15px
`;

View File

@ -1,8 +1,8 @@
import styled, { css } from 'styled-components';
import { Link } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { color, font, mixin } from 'shared/utils/styles';
import { Avatar } from 'shared/components';
import { Avatar } from 'shared/components';
export const IssueLink = styled(Link)`
display: block;
@ -15,7 +15,8 @@ export const Issue = styled.div`
background: #fff;
box-shadow: 0px 1px 2px 0px rgba(9, 30, 66, 0.25);
transition: background 0.1s;
${mixin.clickable}
cursor: pointer;
user-select: none;
@media (max-width: 1100px) {
padding: 10px 8px;
}
@ -32,9 +33,9 @@ export const Issue = styled.div`
export const Title = styled.p`
padding-bottom: 11px;
${font.size(15)}
font-size: 15px
@media (max-width: 1100px) {
${font.size(14.5)}
font-size: 14.5px
}
`;

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { useRouteMatch } from 'react-router-dom';
import { Draggable } from 'react-beautiful-dnd';
import { IssueTypeIcon, IssuePriorityIcon } from 'shared/components';
import { IssueTypeIcon, IssuePriorityIcon } from '../../../../../shared/components';
import { IssueLink, Issue, Title, Bottom, Assignees, AssigneeAvatar } from './Styles';

View File

@ -16,13 +16,13 @@ export const Title = styled.div`
padding: 13px 10px 17px;
text-transform: uppercase;
color: ${color.textMedium};
${font.size(12.5)};
font-size: 12.5px;
${mixin.truncateText}
`;
export const IssuesCount = styled.span`
text-transform: lowercase;
${font.size(13)};
font-size: 13px;
`;
export const Issues = styled.div`

View File

@ -9,17 +9,6 @@ import { IssueStatusCopy } from 'shared/constants/issues';
import Issue from './Issue';
import { List, Title, IssuesCount, Issues } from './Styles';
const propTypes = {
status: PropTypes.string.isRequired,
project: PropTypes.object.isRequired,
filters: PropTypes.object.isRequired,
currentUserId: PropTypes.number,
};
const defaultProps = {
currentUserId: null,
};
const ProjectBoardList = ({ status, project, filters, currentUserId }) => {
const filteredIssues = filterIssues(project.issues, filters, currentUserId);
const filteredListIssues = getSortedListIssues(filteredIssues, status);
@ -78,7 +67,14 @@ const formatIssuesCount = (allListIssues, filteredListIssues) => {
return allListIssues.length;
};
ProjectBoardList.propTypes = propTypes;
ProjectBoardList.defaultProps = defaultProps;
ProjectBoardList.propTypes = {
status: PropTypes.string.isRequired,
project: PropTypes.object.isRequired,
filters: PropTypes.object.isRequired,
currentUserId: PropTypes.number,
};
ProjectBoardList.defaultProps = {
currentUserId: null,
};
export default ProjectBoardList;

View File

@ -20,7 +20,7 @@ export const SearchInputDebounced = styled(InputDebounced)`
border: none;
border-bottom: 2px solid ${color.primary};
background: #fff;
${font.size(21)}
font-size: 21px
&:focus,
&:hover {
box-shadow: none;
@ -50,7 +50,8 @@ export const Issue = styled.div`
padding: 4px 10px;
border-radius: 4px;
transition: background 0.1s;
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
background: ${color.backgroundLight};
}
@ -62,13 +63,13 @@ export const IssueData = styled.div`
export const IssueTitle = styled.div`
color: ${color.textDark};
${font.size(15)}
font-size: 15px
`;
export const IssueTypeId = styled.div`
text-transform: uppercase;
color: ${color.textMedium};
${font.size(12.5)}
font-size: 12.5px
`;
export const SectionTitle = styled.div`
@ -76,7 +77,7 @@ export const SectionTitle = styled.div`
text-transform: uppercase;
color: ${color.textMedium};
${font.bold}
${font.size(11.5)}
font-size: 11.5px
`;
export const NoResults = styled.div`
@ -87,10 +88,10 @@ export const NoResults = styled.div`
export const NoResultsTitle = styled.div`
padding-top: 30px;
${font.medium}
${font.size(20)}
font-size: 20px
`;
export const NoResultsTip = styled.div`
padding-top: 10px;
${font.size(15)}
font-size: 15px
`;

View File

@ -33,7 +33,8 @@ export const StyledLogo = styled(Logo)`
display: inline-block;
margin-left: 8px;
padding: 10px;
${mixin.clickable}
cursor: pointer;
user-select: none;
`;
export const Bottom = styled.div`
@ -51,7 +52,8 @@ export const Item = styled.div`
padding-left: 64px;
color: #deebff;
transition: color 0.1s;
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
@ -70,7 +72,7 @@ export const ItemText = styled.div`
transition: all 0.1s;
transition-property: right, visibility, opacity;
${font.bold}
${font.size(12)}
font-size: 12px
${NavLeft}:hover & {
right: 0;
visibility: visible;

View File

@ -15,7 +15,7 @@ export const FormElement = styled(Form.Element)`
export const FormHeading = styled.h1`
padding: 6px 0 15px;
${font.size(24)}
font-size: 24px
${font.medium}
`;

View File

@ -33,13 +33,13 @@ export const ProjectTexts = styled.div`
export const ProjectName = styled.div`
color: ${color.textDark};
${font.size(15)};
font-size: 15px;
${font.medium};
`;
export const ProjectCategory = styled.div`
color: ${color.textMedium};
${font.size(13)};
font-size: 13px;
`;
export const Divider = styled.div`
@ -53,7 +53,8 @@ export const LinkItem = styled.div`
display: flex;
padding: 8px 12px;
border-radius: 3px;
${mixin.clickable}
cursor: pointer;
user-select: none;
${props =>
!props.to ? `cursor: not-allowed;` : `&:hover { background: ${color.backgroundLight}; }`}
i {
@ -71,7 +72,7 @@ export const LinkItem = styled.div`
export const LinkText = styled.div`
padding-top: 2px;
${font.size(14.7)};
font-size: 14.7px;
`;
export const NotImplemented = styled.div`
@ -86,7 +87,7 @@ export const NotImplemented = styled.div`
color: ${color.textDark};
background: ${color.backgroundMedium};
opacity: 0;
${font.size(11.5)};
font-size: 11.5px;
${font.bold}
${LinkItem}:hover & {
opacity: 1;

View File

@ -16,7 +16,7 @@ export const FeedbackImage = styled.img`
export const FeedbackParagraph = styled.p`
margin-bottom: 12px;
${font.size(15)}
font-size: 15px
&:last-of-type {
margin-bottom: 22px;
}

View File

@ -4,12 +4,12 @@ import { color, font } from 'shared/utils/styles';
export const Container = styled.div`
color: ${color.textMedium};
${font.size(15)};
font-size: 15px;
`;
export const Divider = styled.span`
position: relative;
top: 2px;
margin: 0 10px;
${font.size(18)};
font-size: 18px;
`;

View File

@ -15,8 +15,9 @@ export const StyledButton = styled.button`
border-radius: 3px;
transition: all 0.1s;
appearance: none;
${mixin.clickable}
${font.size(14.5)}
cursor: pointer;
user-select: none;
font-size: 14.5px
${props => buttonVariants[props.variant]}
&:disabled {
opacity: 0.6;

View File

@ -11,14 +11,14 @@ export const StyledConfirmModal = styled(Modal)`
export const Title = styled.div`
padding-bottom: 25px;
${font.medium}
${font.size(22)}
font-size: 22px
line-height: 1.5;
`;
export const Message = styled.p`
padding-bottom: 25px;
white-space: pre-wrap;
${font.size(15)}
font-size: 15px
`;
export const Actions = styled.div`

View File

@ -32,14 +32,14 @@ export const SelectedMonthYear = styled.div`
display: inline-block;
padding-left: 7px;
${font.bold}
${font.size(16)}
font-size: 16px
`;
export const YearSelect = styled.select`
margin-left: 5px;
width: 60px;
height: 22px;
${font.size(13)}
font-size: 13px
`;
export const PrevNextIcons = styled.div`
@ -50,7 +50,8 @@ export const PrevNextIcons = styled.div`
padding: 7px 5px 4px;
font-size: 22px;
color: ${color.textLight};
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
color: ${color.textDarkest};
}
@ -69,7 +70,7 @@ export const DayName = styled.div`
height: 30px;
line-height: 30px;
color: ${color.textLight};
${font.size(13)}
font-size: 13px
`;
export const Day = styled.div`
@ -77,7 +78,7 @@ export const Day = styled.div`
height: 30px;
line-height: 30px;
border-radius: 3px;
${font.size(15)}
font-size: 15px
${props => !props.isFiller && hoverStyles}
${props => props.isToday && font.bold}
${props => props.isSelected && selectedStyles}
@ -96,13 +97,14 @@ export const TimeSection = styled.div`
export const Time = styled.div`
padding: 5px 0 5px 20px;
${font.size(14)}
font-size: 14px
${props => !props.isFiller && hoverStyles}
${props => props.isSelected && selectedStyles}
`;
const hoverStyles = css`
${mixin.clickable}
cursor: pointer;
user-select: none;
&:hover {
background: ${color.backgroundMedium};
}

View File

@ -11,13 +11,13 @@ export const FieldLabel = styled.label`
padding-bottom: 5px;
color: ${color.textMedium};
${font.medium}
${font.size(13)}
font-size: 13px
`;
export const FieldTip = styled.div`
padding-top: 6px;
color: ${color.textMedium};
${font.size(12.5)}
font-size: 12.5px
`;
export const FieldError = styled.div`
@ -25,5 +25,5 @@ export const FieldError = styled.div`
line-height: 1;
color: ${color.danger};
${font.medium}
${font.size(12.5)}
font-size: 12.5px
`;

View File

@ -20,7 +20,7 @@ export const InputElement = styled.input`
background: ${color.backgroundLightest};
transition: background 0.1s;
${font.regular}
${font.size(15)}
font-size: 15px
${props => props.hasIcon && 'padding-left: 32px;'}
&:hover {
background: ${color.backgroundLight};

View File

@ -1,7 +1,7 @@
import styled from 'styled-components';
import { issuePriorityColors } from 'shared/utils/styles';
import { Icon } from 'shared/components';
import { issuePriorityColors } from '../../../shared/utils/styles';
import { Icon } from '../../../shared/components';
export const PriorityIcon = styled(Icon)`
color: ${props => issuePriorityColors[props.color]};

View File

@ -1,7 +1,7 @@
import styled from 'styled-components';
import { issueTypeColors } from 'shared/utils/styles';
import { Icon } from 'shared/components';
import { issueTypeColors } from '../../../shared/utils/styles';
import { Icon } from '../../components';
export const TypeIcon = styled(Icon)`
color: ${props => issueTypeColors[props.color]};

View File

@ -3,14 +3,12 @@ import PropTypes from 'prop-types';
import { TypeIcon } from './Styles';
const propTypes = {
type: PropTypes.string.isRequired,
};
const IssueTypeIcon = ({ type, ...otherProps }) => (
<TypeIcon type={type} color={type} size={18} {...otherProps} />
);
IssueTypeIcon.propTypes = propTypes;
IssueTypeIcon.propTypes = {
type: PropTypes.string.isRequired,
};
export default IssueTypeIcon;

View File

@ -56,7 +56,8 @@ export const CloseIcon = styled(Icon)`
font-size: 25px;
color: ${color.textMedium};
transition: all 0.1s;
${mixin.clickable}
cursor: pointer;
user-select: none;
${props => closeIconStyles[props.variant]}
`;

View File

@ -41,5 +41,5 @@ export const StyledIcon = styled(Icon)`
export const Title = styled.h1`
margin-bottom: 16px;
padding-left: 42px;
${font.size(29)}
font-size: 29px
`;

View File

@ -7,7 +7,7 @@ export const StyledSelect = styled.div`
position: relative;
border-radius: 4px;
cursor: pointer;
${font.size(14)}
font-size: 14px
${props => props.variant === 'empty' && `display: inline-block;`}
${props =>
props.variant === 'normal' &&
@ -80,7 +80,7 @@ export const AddMore = styled.div`
display: inline-block;
margin-bottom: 3px;
padding: 3px 0;
${font.size(12.5)}
font-size: 12.5px
${mixin.link()}
i {
margin-right: 3px;
@ -118,7 +118,8 @@ export const ClearIcon = styled(Icon)`
padding: 5px;
font-size: 16px;
color: ${color.textMedium};
${mixin.clickable}
cursor: pointer;
user-select: none;
`;
export const Options = styled.div`

View File

@ -4,6 +4,6 @@ import { font } from 'shared/utils/styles';
export const Content = styled.div`
padding: 0 !important;
${font.size(15)}
font-size: 15px
${font.regular}
`;

View File

@ -13,7 +13,7 @@ export const EditorCont = styled.div`
border: 1px solid ${color.borderLightest};
border-top: none;
color: ${color.textDarkest};
${font.size(15)}
font-size: 15px
${font.regular}
}
.ql-editor {

View File

@ -14,7 +14,7 @@ export const StyledTextarea = styled.div`
color: ${color.textDarkest};
background: ${color.backgroundLightest};
${font.regular}
${font.size(15)}
font-size: 15px
&:focus {
background: #fff;
border: 1px solid ${color.borderInputFocus};

View File

@ -175,7 +175,7 @@ export const mixin = {
color: ${colorValue};
background: ${background};
${font.bold}
${font.size(12)}
font-size: 12px
i {
margin-left: 4px;
}