react-customized-notifications
Version:
A React Notification System forked from https://github.com/igorprado/react-notification-system
285 lines (230 loc) • 7.94 kB
JSX
var React = require('react');
var createReactClass = require('create-react-class');
var PropTypes = require('prop-types');
var merge = require('object-assign');
var NotificationContainer = require('./NotificationContainer');
var Constants = require('./constants');
var Styles = require('./styles');
var NotificationSystem = createReactClass({
uid: 3400,
_isMounted: false,
_getStyles: {
overrideStyle: {},
overrideWidth: null,
elements: {
notification: 'NotificationItem',
title: 'Title',
messageWrapper: 'MessageWrapper',
dismiss: 'Dismiss',
action: 'Action',
actionWrapper: 'ActionWrapper'
},
setOverrideStyle: function(style) {
this.overrideStyle = style;
},
wrapper: function() {
if (!this.overrideStyle) return {};
return merge({}, Styles.Wrapper, this.overrideStyle.Wrapper);
},
container: function(position) {
var override = this.overrideStyle.Containers || {};
if (!this.overrideStyle) return {};
this.overrideWidth = Styles.Containers.DefaultStyle.width;
if (override.DefaultStyle && override.DefaultStyle.width) {
this.overrideWidth = override.DefaultStyle.width;
}
if (override[position] && override[position].width) {
this.overrideWidth = override[position].width;
}
return merge({}, Styles.Containers.DefaultStyle, Styles.Containers[position], override.DefaultStyle, override[position]);
},
byElement: function(element) {
var self = this;
return function(level) {
var _element = self.elements[element];
var override = self.overrideStyle[_element] || {};
if (!self.overrideStyle) return {};
return merge({}, Styles[_element].DefaultStyle, Styles[_element][level], override.DefaultStyle, override[level]);
};
}
},
_didNotificationRemoved: function(uid) {
var notification;
var notifications = this.state.notifications.filter(function(toCheck) {
if (toCheck.uid === uid) {
notification = toCheck;
return false;
}
return true;
});
if (this._isMounted) {
this.setState({ notifications: notifications });
}
if (notification && notification.onRemove) {
notification.onRemove(notification);
}
},
getInitialState: function() {
return {
notifications: []
};
},
propTypes: {
style: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.object
]),
noAnimation: PropTypes.bool,
allowHTML: PropTypes.bool,
itemClassName: PropTypes.string,
containerClassName: PropTypes.string,
itemOnClick: PropTypes.func
},
getDefaultProps: function() {
return {
style: {},
noAnimation: false,
allowHTML: false,
itemClassName: '',
containerClassName: ''
};
},
addNotification: function(notification) {
var _notification = merge({}, Constants.notification, notification);
var notifications = this.state.notifications;
var i;
_notification.itemClassName = this.props.itemClassName;
if (!_notification.level) {
throw new Error('notification level is required.');
}
if (Object.keys(Constants.levels).indexOf(_notification.level) === -1) {
throw new Error('\'' + _notification.level + '\' is not a valid level.');
}
// eslint-disable-next-line
if (isNaN(_notification.autoDismiss)) {
throw new Error('\'autoDismiss\' must be a number.');
}
if (Object.keys(Constants.positions).indexOf(_notification.position) === -1) {
throw new Error('\'' + _notification.position + '\' is not a valid position.');
}
// Some preparations
_notification.position = _notification.position.toLowerCase();
_notification.level = _notification.level.toLowerCase();
_notification.autoDismiss = parseInt(_notification.autoDismiss, 10);
_notification.uid = _notification.uid || this.uid;
_notification.ref = 'notification-' + _notification.uid;
this.uid += 1;
// do not add if the notification already exists based on supplied uid
for (i = 0; i < notifications.length; i += 1) {
if (notifications[i].uid === _notification.uid) {
return false;
}
}
notifications.push(_notification);
if (typeof _notification.onAdd === 'function') {
notification.onAdd(_notification);
}
this.setState({
notifications: notifications
});
return _notification;
},
getNotificationRef: function(notification) {
var self = this;
var foundNotification = null;
Object.keys(this.refs).forEach(function(container) {
if (container.indexOf('container') > -1) {
Object.keys(self.refs[container].refs).forEach(function(_notification) {
var uid = notification.uid ? notification.uid : notification;
if (_notification === 'notification-' + uid) {
// NOTE: Stop iterating further and return the found notification.
// Since UIDs are uniques and there won't be another notification found.
foundNotification = self.refs[container].refs[_notification];
}
});
}
});
return foundNotification;
},
removeNotification: function(notification) {
var foundNotification = this.getNotificationRef(notification);
return foundNotification && foundNotification._hideNotification();
},
editNotification: function(notification, newNotification) {
var foundNotification = null;
// NOTE: Find state notification to update by using
// `setState` and forcing React to re-render the component.
var uid = notification.uid ? notification.uid : notification;
var newNotifications = this.state.notifications.filter(function(stateNotification) {
if (uid === stateNotification.uid) {
foundNotification = stateNotification;
return false;
}
return true;
});
if (!foundNotification) {
return;
}
newNotifications.push(merge(
{},
foundNotification,
newNotification
));
this.setState({
notifications: newNotifications
});
},
clearNotifications: function() {
var self = this;
Object.keys(this.refs).forEach(function(container) {
if (container.indexOf('container') > -1) {
Object.keys(self.refs[container].refs).forEach(function(_notification) {
self.refs[container].refs[_notification]._hideNotification();
});
}
});
},
componentDidMount: function() {
this._getStyles.setOverrideStyle(this.props.style);
this._isMounted = true;
},
componentWillUnmount: function() {
this._isMounted = false;
},
render: function() {
var self = this;
var containers = null;
var notifications = this.state.notifications;
var itemOnClick = self.props.itemOnClick;
if (notifications.length) {
containers = Object.keys(Constants.positions).map(function(position) {
var _notifications = notifications.filter(function(notification) {
return position === notification.position;
});
if (!_notifications.length) {
return null;
}
return (
<NotificationContainer
containerClassName={ self.props.containerClassName || '' }
ref={ 'container-' + position }
key={ position }
position={ position }
notifications={ _notifications }
getStyles={ self._getStyles }
onRemove={ self._didNotificationRemoved }
noAnimation={ self.props.noAnimation }
allowHTML={ self.props.allowHTML }
itemOnClick={ itemOnClick }
/>
);
});
}
return (
<div className="notifications-wrapper" style={ this._getStyles.wrapper() }>
{ containers }
</div>
);
}
});
module.exports = NotificationSystem;