Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oskar/notification #40

Merged
merged 10 commits into from
May 17, 2019
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import React from 'react';
import { expect } from 'chai';
import { configure, shallow } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import Toast from '../toast.jsx';
import Notification from '../notification.jsx';

configure({ adapter: new Adapter() });

describe('Toast', () => {
it('should render one <Toast /> component', () => {
const wrapper = shallow(<Toast />);
describe('Notification', () => {
it('should render one <Notification /> component', () => {
const wrapper = shallow(<Notification />);
expect(wrapper).to.have.length(1);
});
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import PropTypes from 'prop-types';
import React from 'react';

const CloseButton = ({ onClick }) => (
const CloseButton = ({ onClick, className }) => (
<button
className='toast__close-button'
className={className}
type='button'
onClick={onClick}
/>
);

CloseButton.propTypes = {
onClick: PropTypes.func.isRequired,
className: PropTypes.string,
onClick : PropTypes.func.isRequired,
};

export default CloseButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const default_delay = 3000;

export const max_display_notifications = 3;

export const types = {
danger : 'notification--danger',
info : 'notification--info',
success : 'notification--success',
warning : 'notification--warning',
contract_sold: 'notification--info',
};

export const sortNotifications = (() => {
const notification_order = {
contract_sold: 1,
danger : 2,
warning : 3,
info : 4,
success : 5,
};

return (a, b) => notification_order[a.type] - notification_order[b.type];
})();
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export default from './notification.jsx';
export * from './constants.js';
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import PropTypes from 'prop-types';
import React from 'react';
import classNames from 'classnames';
import { Icon } from 'Assets/Common';
import { IconDanger } from 'Assets/Common/icon-danger.jsx';
import { IconInformation } from 'Assets/Common/icon-information.jsx';
import { IconWarning } from 'Assets/Common/icon-warning.jsx';
import { IconSuccess } from 'Assets/Common/icon-success.jsx';
import CloseButton from './close-button.jsx';
import {
default_delay,
types } from './constants';

const Notification = ({
data,
removeNotification,
}) => {
const destroy = (is_closed_by_user) => {
removeNotification(data);

if (data.closeOnClick) {
data.closeOnClick(data, is_closed_by_user);
}
};

const onClick = () => destroy(true);

if (data.is_auto_close) {
setTimeout(destroy, data.delay || default_delay);
}

return (
<div className={
classNames('notification', types[data.type], {
'notification--small': (data.size === 'small'),
})}
>
<div className='notification__icon'>
{ data.type === 'danger' && <Icon icon={IconDanger} className='notification__icon-type' /> }
{ (data.type === 'info' || data.type === 'contract_sold')
&& <Icon icon={IconInformation} className='notification__icon-type' /> }
{ data.type === 'success' && <Icon icon={IconSuccess} className='notification__icon-type' /> }
{ data.type === 'warning' && <Icon icon={IconWarning} className='notification__icon-type' /> }
</div>
<div className='notification__text-container'>
<h4 className='notification__header'>{data.header}</h4>
<p className='notification__text-body'> {data.message}</p>
</div>
{ data.should_hide_close_btn ? undefined : <CloseButton onClick={onClick} className='notification__close-button' />}
</div>
);
};

Notification.propTypes = {
data: PropTypes.shape({
closeOnClick : PropTypes.func,
delay : PropTypes.number,
header : PropTypes.string,
is_auto_close : PropTypes.bool,
message : PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
should_hide_close_btn: PropTypes.bool,
size : PropTypes.oneOf(['small']),
type : PropTypes.oneOf(['warning', 'info', 'success', 'danger', 'contract_sold']).isRequired,
}),
removeNotification: PropTypes.func,
};

export default Notification;

This file was deleted.

This file was deleted.

This file was deleted.

66 changes: 0 additions & 66 deletions src/javascript/app/App/Components/Elements/ToastMessage/toast.jsx

This file was deleted.

This file was deleted.

46 changes: 46 additions & 0 deletions src/javascript/app/App/Containers/notification-messages.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'Stores/connect';
import Notification, {
max_display_notifications } from '../Components/Elements/NotificationMessage';

const NotificationMessages = ({
notification_messages,
removeNotification,
}) => (
<div className='notification-messages'>
{
notification_messages
.slice(0, max_display_notifications)
.map((notification, idx) => (
<Notification
key={idx}
data={notification}
removeNotification={removeNotification}
/>
))
}
</div>
);

NotificationMessages.propTypes = {
notification_messages: PropTypes.arrayOf(
PropTypes.shape({
closeOnClick : PropTypes.func,
delay : PropTypes.number,
header : PropTypes.string,
is_auto_close: PropTypes.bool,
message : PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
size : PropTypes.oneOf(['small']),
type : PropTypes.oneOf(['warning', 'info', 'success', 'danger', 'contract_sold']),
}),
),
removeNotification: PropTypes.func,
};

export default connect(
({ ui }) => ({
notification_messages: ui.notification_messages,
removeNotification : ui.removeNotification,
})
)(NotificationMessages);
46 changes: 0 additions & 46 deletions src/javascript/app/App/Containers/toast-message.jsx

This file was deleted.

3 changes: 0 additions & 3 deletions src/javascript/app/App/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
import getBaseName from 'Utils/URL/base-name';
import { MobxProvider } from 'Stores/connect';
import ErrorBoundary from './Components/Elements/Errors/error-boundary.jsx';
import { POSITIONS } from './Components/Elements/ToastMessage';
import PushNotification from './Containers/push-notification.jsx';
import ToastMessage from './Containers/toast-message.jsx';
import AppContents from './Containers/Layout/app-contents.jsx';
import Footer from './Containers/Layout/footer.jsx';
import Header from './Containers/Layout/header.jsx';
Expand All @@ -30,7 +28,6 @@ const App = ({ root_store }) => (
<ErrorBoundary>
<AppContents>
<Routes />
<ToastMessage position={POSITIONS.TOP_RIGHT} />
<PushNotification />
</AppContents>
<DenialOfServiceModal />
Expand Down
12 changes: 12 additions & 0 deletions src/javascript/app/Assets/Common/icon-danger.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

const IconDanger = ({ className }) => (
<svg className={className} xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'>
<g fill='none' fillRule='evenodd'>
<circle cx='12' cy='12' r='12' fill='#FFF' />
<path fill='#E31C4B' fillRule='nonzero' d='M10.931 4.346C11.232 4.108 11.621 4 12 4s.76.108 1.062.346c.301.237.499.615.499 1.042v.195c.208-.079.433-.113.655-.113.38 0 .767.108 1.069.345.302.238.499.61.499 1.037V9.88c.206-.078.427-.113.648-.113.38 0 .768.106 1.07.345.3.24.498.614.498 1.043v3.524c0 1.74-.755 3.095-1.888 3.99C14.979 19.561 13.488 20 12 20s-2.986-.438-4.119-1.332C6.748 17.774 6 16.42 6 14.68V8.956c0-.427.197-.805.499-1.042a1.73 1.73 0 0 1 1.069-.346c.222 0 .447.04.655.12v-.83c0-.427.198-.798.5-1.036a1.708 1.708 0 0 1 1.06-.346c.22 0 .442.037.65.113v-.2c0-.428.197-.806.498-1.043zm1.509.795A.721.721 0 0 0 12 5a.721.721 0 0 0-.44.14c-.11.088-.193.207-.193.428v6.295c.004.206-.207.396-.44.396-.232 0-.443-.19-.44-.396V7.035c-.001-.176-.017-.304-.185-.458a.721.721 0 0 0-.44-.14.721.721 0 0 0-.44.14c-.11.087-.186.2-.186.421v5.512c.003.207-.207.397-.44.397-.232 0-.443-.19-.44-.397V9.076c-.002-.178-.017-.323-.193-.464a.719.719 0 0 0-.44-.141.74.74 0 0 0-.446.14c-.11.088-.186.207-.186.428v5.567c0 1.499.614 2.574 1.526 3.3S10.761 19 12 19c1.239 0 2.47-.368 3.383-1.094.912-.726 1.526-1.801 1.526-3.3v-3.428c0-.224-.082-.34-.192-.428a.719.719 0 0 0-.44-.14.719.719 0 0 0-.44.14c-.117.1-.184.262-.186.459v3.287c.003.207-.208.397-.44.397-.233 0-.443-.19-.44-.397V6.992c0-.221-.075-.334-.186-.422a.74.74 0 0 0-.447-.14.74.74 0 0 0-.447.14.602.602 0 0 0-.185.453V11.8c.003.207-.208.397-.44.397-.233 0-.444-.19-.44-.397V5.568c0-.221-.076-.34-.186-.427zm-4.35 9.033c.078-.106.199-.17.328-.174a.434.434 0 0 1 .434.359c.27 1.298.694 1.888 1.443 2.298.75.41 1.739.561 2.54.358a.42.42 0 0 1 .417.124.46.46 0 0 1 .102.437.438.438 0 0 1-.315.308c-.981.249-2.177.094-3.144-.436-.968-.529-1.568-1.385-1.884-2.9-.029-.13 0-.268.079-.374zm6.361 3.555c-.302 0-.548-.229-.548-.51 0-.283.246-.512.548-.512.303 0 .549.23.549.511 0 .282-.246.511-.549.511z' />
</g>
</svg>
);

export { IconDanger };
15 changes: 0 additions & 15 deletions src/javascript/app/Assets/Common/icon-error.jsx

This file was deleted.

Loading