Merge pull request #91 from satoshilabs/notification-groups

Implement notification groups + little refactor
pull/97/head
Vaclav Mlejnsky 6 years ago committed by GitHub
commit b9820daf87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,113 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import Icon from 'components/Icon';
import ICONS from 'config/icons';
import colors from 'config/colors';
import { Notification } from 'components/Notification';
import { getIcon, getColor } from 'utils/notification';
const Wrapper = styled.div``;
const Header = styled.div`
display: flex;
cursor: pointer;
justify-content: space-between;
background: ${colors.WHITE};
align-items: center;
padding: 5px 10px;
border-bottom: 1px solid ${colors.BACKGROUND};
`;
const Left = styled.div`
display: flex;
justify-content: flex-start;
align-items: center;
`;
const Right = styled.div``;
const Body = styled.div``;
const Title = styled.div`
color: ${props => props.color};
`;
class Group extends Component {
constructor() {
super();
this.state = {
visibleCount: 1,
visible: true,
};
}
toggle = () => {
if (this.state.visible) {
this.setState({
visible: false,
visibleCount: 0,
});
} else {
this.setState({
visible: true,
visibleCount: this.props.groupNotifications.length,
});
}
}
render() {
const { type, groupNotifications } = this.props;
const color = getColor(type);
return (
<Wrapper>
{groupNotifications.length > 1 && (
<Header onClick={this.toggle}>
<Left>
<Icon
color={color}
size={30}
icon={getIcon(type)}
/>
<Title color={color}>
{groupNotifications.length} {groupNotifications.length > 1 ? `${type}s` : type}
</Title>
</Left>
<Right>
<Icon
icon={ICONS.ARROW_DOWN}
color={colors.TEXT_SECONDARY}
size={24}
isActive={this.state.visible}
canAnimate
/>
</Right>
</Header>
)}
<Body>
{groupNotifications
.slice(0, this.state.visibleCount)
.map(notification => (
<Notification
key={notification.title}
type={notification.type}
title={notification.title}
message={notification.message}
/>
))}
</Body>
</Wrapper>
);
}
}
Group.propTypes = {
type: PropTypes.string,
groupNotifications: PropTypes.arrayOf({
key: PropTypes.string,
type: PropTypes.string,
title: PropTypes.string,
message: PropTypes.string,
}),
};
export default Group;

@ -0,0 +1,56 @@
import React, { Component } from 'react';
import styled from 'styled-components';
import { PRIORITY } from 'constants/notifications';
import Group from './components/Group';
const Wrapper = styled.div``;
class NotificationsGroup extends Component {
constructor() {
super();
this.notifications = [
{ type: 'warning', title: 'adddaa', message: 'aaaa' },
{ type: 'error', title: 'aaddda', message: 'aaaa' },
{ type: 'info', title: 'aafffa', message: 'aaaa' },
{ type: 'error', title: 'aggaa', message: 'aaaa' },
{ type: 'warning', title: 'aasssa', message: 'aaaa' },
{ type: 'success', title: 'afaa', message: 'aaaa' },
{ type: 'error', title: 'aada', message: 'aaaa' },
{ type: 'error', title: 'aafffa', message: 'aaaa' },
];
}
groupNotifications = notifications => notifications
.reduce((acc, obj) => {
const key = obj.type;
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
}, {});
sortByPriority(notifications) {
return notifications;
}
render() {
const { notifications } = this;
const notificationGroups = this.groupNotifications(notifications);
const sortedNotifications = this.sortByPriority(notificationGroups);
return (
<Wrapper>
{Object.keys(sortedNotifications).map(group => (
<Group
groupNotifications={notificationGroups[group]}
type={group}
/>
))}
</Wrapper>
);
}
}
export default NotificationsGroup;

@ -1,16 +1,36 @@
/* @flow */
import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import styled, { css } from 'styled-components';
import colors from 'config/colors';
import { getColor, getIcon } from 'utils/notification';
import Icon from 'components/Icon';
import icons from 'config/icons';
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
import * as NotificationActions from 'actions/NotificationActions';
import Loader from 'components/Loader';
import type { Action, State } from 'flowtype';
import NotificationButton from './components/NotificationButton';
type Props = {
key?: number,
notifications: $ElementType<State, 'notifications'>,
close: (notif?: any) => Action,
};
type NProps = {
type: string,
cancelable?: boolean;
title: string;
message?: string;
actions?: Array<any>;
close?: typeof NotificationActions.close,
loading?: boolean
};
const Wrapper = styled.div`
position: relative;
color: ${colors.TEXT_PRIMARY};
@ -92,27 +112,6 @@ const ActionContent = styled.div`
export const Notification = (props: NProps): React$Element<string> => {
const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action
const getIconColor = (type) => {
let color;
switch (type) {
case 'info':
color = colors.INFO_PRIMARY;
break;
case 'error':
color = colors.ERROR_PRIMARY;
break;
case 'warning':
color = colors.WARNING_PRIMARY;
break;
case 'success':
color = colors.SUCCESS_PRIMARY;
break;
default:
color = null;
}
return color;
};
return (
<Wrapper type={props.type}>
@ -120,7 +119,7 @@ export const Notification = (props: NProps): React$Element<string> => {
{props.cancelable && (
<CloseClick onClick={() => close()}>
<Icon
color={getIconColor(props.type)}
color={getColor(props.type)}
icon={icons.CLOSE}
size={20}
/>
@ -129,8 +128,8 @@ export const Notification = (props: NProps): React$Element<string> => {
<Body>
<MessageContent>
<StyledIcon
color={getIconColor(props.type)}
icon={icons[props.type.toUpperCase()]}
color={getColor(props.type)}
icon={getIcon(props.type)}
/>
<Texts>
<Title>{ props.title }</Title>
@ -161,7 +160,7 @@ export const Notification = (props: NProps): React$Element<string> => {
);
};
export const NotificationGroup = (props) => {
export const NotificationGroup = (props: Props) => {
const { notifications, close } = props;
return notifications.map(n => (
<Notification
@ -183,4 +182,4 @@ export default connect(
dispatch => ({
close: bindActionCreators(NotificationActions.close, dispatch),
}),
)(NotificationGroup);
)(NotificationGroup);

@ -0,0 +1,8 @@
export default {
PRIORITY: {
error: 0,
warning: 1,
info: 2,
success: 3,
},
};

@ -0,0 +1,31 @@
import colors from 'config/colors';
import icons from 'config/icons';
const getColor = (type) => {
let color;
switch (type) {
case 'info':
color = colors.INFO_PRIMARY;
break;
case 'error':
color = colors.ERROR_PRIMARY;
break;
case 'warning':
color = colors.WARNING_PRIMARY;
break;
case 'success':
color = colors.SUCCESS_PRIMARY;
break;
default:
color = null;
}
return color;
};
const getIcon = type => icons[type.toUpperCase()];
export {
getColor,
getIcon,
};
Loading…
Cancel
Save