diff --git a/src/components/Notification/NotificationGroups/components/Group/index.js b/src/components/Notification/NotificationGroups/components/Group/index.js new file mode 100644 index 00000000..c3915b77 --- /dev/null +++ b/src/components/Notification/NotificationGroups/components/Group/index.js @@ -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 ( + + {groupNotifications.length > 1 && ( +
+ + + + {groupNotifications.length} {groupNotifications.length > 1 ? `${type}s` : type} + + + + + +
+ )} + + {groupNotifications + .slice(0, this.state.visibleCount) + .map(notification => ( + + ))} + +
+ ); + } +} + +Group.propTypes = { + type: PropTypes.string, + groupNotifications: PropTypes.arrayOf({ + key: PropTypes.string, + type: PropTypes.string, + title: PropTypes.string, + message: PropTypes.string, + }), +}; + +export default Group; \ No newline at end of file diff --git a/src/components/Notification/NotificationGroups/index.js b/src/components/Notification/NotificationGroups/index.js new file mode 100644 index 00000000..715b1da3 --- /dev/null +++ b/src/components/Notification/NotificationGroups/index.js @@ -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 ( + + {Object.keys(sortedNotifications).map(group => ( + + ))} + + ); + } +} + +export default NotificationsGroup; \ No newline at end of file diff --git a/src/components/Notification/index.js b/src/components/Notification/index.js index 6654a152..49953fff 100644 --- a/src/components/Notification/index.js +++ b/src/components/Notification/index.js @@ -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, + close: (notif?: any) => Action, +}; + +type NProps = { + type: string, + cancelable?: boolean; + title: string; + message?: string; + actions?: Array; + 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 => { 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 ( @@ -120,7 +119,7 @@ export const Notification = (props: NProps): React$Element => { {props.cancelable && ( close()}> @@ -129,8 +128,8 @@ export const Notification = (props: NProps): React$Element => { { props.title } @@ -161,7 +160,7 @@ export const Notification = (props: NProps): React$Element => { ); }; -export const NotificationGroup = (props) => { +export const NotificationGroup = (props: Props) => { const { notifications, close } = props; return notifications.map(n => ( ({ close: bindActionCreators(NotificationActions.close, dispatch), }), -)(NotificationGroup); \ No newline at end of file +)(NotificationGroup); diff --git a/src/constants/notifications.js b/src/constants/notifications.js new file mode 100644 index 00000000..1ffed4c1 --- /dev/null +++ b/src/constants/notifications.js @@ -0,0 +1,8 @@ +export default { + PRIORITY: { + error: 0, + warning: 1, + info: 2, + success: 3, + }, +}; \ No newline at end of file diff --git a/src/utils/notification.js b/src/utils/notification.js new file mode 100644 index 00000000..7567a542 --- /dev/null +++ b/src/utils/notification.js @@ -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, +}; \ No newline at end of file