Commit 0f8bb75e authored by Andrew Hrdy's avatar Andrew Hrdy

Continued working on alerts. Using react-notification-system instead of material-ui's SnackBar.

parent f5c7cd80
Pipeline #2028 passed with stage
in 1 minute and 39 seconds
......@@ -9470,6 +9470,16 @@
}
}
},
"react-notification-system": {
"version": "0.2.16",
"resolved": "https://registry.npmjs.org/react-notification-system/-/react-notification-system-0.2.16.tgz",
"integrity": "sha1-m52iCw00eGtgBXxStCUW6hKVN0o=",
"requires": {
"create-react-class": "15.6.2",
"object-assign": "4.1.1",
"prop-types": "15.6.0"
}
},
"react-popper": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-0.7.4.tgz",
......@@ -10187,7 +10197,6 @@
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
},
"osenv": {
......
import React from 'react';
import Snackbar from 'material-ui/Snackbar';
import IconButton from 'material-ui/IconButton';
import CloseIcon from 'material-ui-icons/Close';
class Alert extends React.Component {
constructor() {
super();
this.state = {
open: true
};
}
isActive = () => {
const curDate = new Date();
const startDate = new Date(this.props.alert.start_datetime);
const endDate = new Date(this.props.alert.end_datetime);
return this.state.open && (curDate > startDate && curDate < endDate);
};
handleClose = (event, reason) => {
//The alert should not close if the user clicks anywhere on the screen.
if (reason === 'clickaway') {
return;
}
this.setState({
open: false
});
};
getAlertClass = () => {
switch (this.props.alert.urgency_tag.toLowerCase()) {
case 'emergency':
return 'alert-emergency';
case 'major':
return 'alert-major';
case 'minor':
return 'alert-minor';
case 'info':
default:
return 'alert-info';
}
};
render() {
const alert = this.props.alert;
return (
<Snackbar
open={this.isActive()}
//autoHideDuration={6000}
onClose={this.handleClose}
message={<span>{alert.message}</span>}
action={
<IconButton
color="inherit"
onClick={this.handleClose}>
<CloseIcon/>
</IconButton>
}
classes={{
root: this.getAlertClass()
}}
anchorOrigin={{
vertical: 'top',
horizontal: 'center'
}}/>
);
}
}
export default Alert;
\ No newline at end of file
import React from 'react';
import Alert from './Alert';
//TODO: Alerts should not stack on top of each other.
const AlertContainer = ({alerts}) => {
return (
<div>
{alerts && alerts.map((alert) => {
return (
<Alert key={alert.id} alert={alert}/>
);
})}
</div>
);
};
import NotificationSystem from 'react-notification-system';
class AlertContainer extends React.Component {
notificationSystem;
constructor() {
super();
/*
The alerts that have been shown need to be stored because componentWillReceiveProps will be called on
change detection. Because of this, whenever an action occurs on the screen, the alerts will be reshown.
*/
this.state = {
shownAlertIds: []
};
}
componentWillReceiveProps(nextProps) {
//TODO: Only show alerts that the user has not seen before.
nextProps.alerts.filter((alert) => !this.state.shownAlertIds.includes(alert.id)).filter(this.isAlertActive).forEach((alert) => {
this.addNotification(alert);
});
}
isAlertActive = (alert) => {
const curDate = new Date();
const startDate = new Date(alert.start_datetime);
const endDate = new Date(alert.end_datetime);
return curDate > startDate && curDate < endDate;
};
addNotification = (alert) => {
//TODO: Support alerts with links
this.state.shownAlertIds.push(alert.id);
this.notificationSystem.addNotification({
message: alert.message,
level: this.resolveNotificationLevel(alert),
position: 'bl',
autoDismiss: 6,
dismissible: true,
uid: alert.id
});
};
/**
* The What's Open API tells us if an alert is an info, minor, major, or emergency. However, the library that
* deals with notifications requires either a info, success, warning, or error. This function maps the
* What's Open API to the library.
*
* @param alert The What's Open Alert.
* @returns {string} The notification level used by the third party library.
*/
resolveNotificationLevel = (alert) => {
switch (alert.urgency_tag) {
case 'emergency':
return 'error';
case 'major':
return 'warning';
case 'minor':
return 'success';
default:
case 'info':
return 'info';
}
};
render() {
return (
<div>
<NotificationSystem ref={(c) => {
this.notificationSystem = c;
}}/>
</div>
);
}
}
export default AlertContainer;
\ No newline at end of file
.alert-info {
> div {
background-color: #42A5F5;
}
}
.alert-minor {
> div {
background-color: #66BB6A;
}
}
.alert-major {
> div {
background-color: #FFA726;
}
}
.alert-emergency {
> div {
background-color: #EF5350;
}
}
\ No newline at end of file
.notification {
height: auto !important;
.notification-message {
font-family: "Roboto", "-apple-system", "Helvetica", "Arial", sans-serif;
line-height: 24px;
font-size: 14px;
font-weight: 500;
}
}
@media screen and (max-width: 500px) {
.notifications-bl {
width: 100% !important;
}
}
\ No newline at end of file
@import './variables.scss';
@import './mixins.scss';
/* Components */
@import './components/alert';
@import 'components/alertContainer';
@import './components/appBar';
@import './components/cardContainer';
@import './components/facilityCategory';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment