Commit f5c7cd80 authored by Andrew Hrdy's avatar Andrew Hrdy

Basic alert added. Only supports one alert.

parent 8c8f4370
Pipeline #2023 passed with stage
in 1 minute and 40 seconds
export const SET_SIDEBAR = 'SET_SIDEBAR';
export const SET_FACILITIES = 'SET_FACILITIES';
export const GET_FACILITIES = 'GET_FACILITIES';
export const SET_ALERTS = 'SET_ALERTS';
export const GET_ALERTS = 'GET_ALERTS';
export const SET_SELECTED_FACILITY = 'SET_SELECTED_FACILITY';
export const SET_SEARCH_TERM = 'SET_SEARCH_TERM';
export const SET_CAMPUS_REGION = 'SET_CAMPUS_REGION';
......
import {GET_FACILITIES, SET_FACILITIES, SORT_BY_FAVORITES} from './action-types';
import {GET_ALERTS, GET_FACILITIES, SET_ALERTS, SET_FACILITIES, SORT_BY_FAVORITES} from './action-types';
const API_GET_FACILITIES = 'https://api.srct.gmu.edu/whatsopen/v2/facilities/';
const API_GET_ALERTS = 'https://api.srct.gmu.edu/whatsopen/v2/alerts/?ordering=urgency_tag';
// SHOP MASON ONLY
//const API_GET_FACILITIES = 'https://api.srct.gmu.edu/whatsopen/v2/facilities/?facility_classifier=shopmason';
export const getFacilities = () => (dispatch) => {
......@@ -40,3 +41,31 @@ export const setFacilities = (facilities) => {
export const sortByFavorites = () => ({
type: SORT_BY_FAVORITES
});
export const getAlerts = () => (dispatch) => {
dispatch({
type: GET_ALERTS
});
const request = new Request(API_GET_ALERTS, {
method: 'GET'
});
return fetch(request)
.then((res) => {
if (res.status < 200 || res.status >= 300) {
throw new Error(res.statusText);
}
return res.json();
}).then((json) => {
dispatch(setAlerts(JSON.stringify(json)));
});
};
export const setAlerts = (alerts) => {
return {
type: SET_ALERTS,
alerts: JSON.parse(alerts)
};
};
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>
);
};
export default AlertContainer;
\ No newline at end of file
import React from 'react';
import {connect} from 'react-redux';
import {setAllFavorites} from '../actions/ui';
import {setAllFavorites, setSelectedFacility, setSidebar} from '../actions/ui';
import AppBar from '../components/AppBar';
import AlertContainer from '../components/AlertContainer';
import Sidebar from '../components/Sidebar';
import {getFacilities, setFacilities, sortByFavorites} from '../actions/api';
import {setSidebar, setSelectedFacility} from '../actions/ui';
import {getAlerts, getFacilities, setAlerts, setFacilities, sortByFavorites} from '../actions/api';
import CardContainer from '../components/CardContainer';
class Layout extends React.Component {
......@@ -35,23 +35,27 @@ class Layout extends React.Component {
}
this.props.getFacilities();
this.props.getAlerts();
};
render() {
const {isSidebarOpen, selectedFacility, facilities, searchTerm, campusRegion, setSidebar, setSelectedFacility} = this.props;
const {isSidebarOpen, selectedFacility, facilities, alerts, searchTerm, campusRegion, setSidebar, setSelectedFacility} = this.props;
return (
<div className={'layout-root'}>
<AppBar isOpen={false} />
<AppBar isOpen={false}/>
<AlertContainer alerts={alerts}/>
<div className={'layout-container'}>
<div className={'layout-main-content'}>
<div className={'layout-card-container'}>
<CardContainer styles={'layout-card-container'} searchTerm={searchTerm}
campusRegion={campusRegion} facilities={facilities} />
campusRegion={campusRegion} facilities={facilities}/>
</div>
</div>
<Sidebar facilities={facilities} facility={selectedFacility} isSidebarOpen={isSidebarOpen} setSidebar={setSidebar} setSelectedFacility={setSelectedFacility} campusRegion={campusRegion}/>
<Sidebar facilities={facilities} facility={selectedFacility} isSidebarOpen={isSidebarOpen}
setSidebar={setSidebar} setSelectedFacility={setSelectedFacility}
campusRegion={campusRegion}/>
</div>
</div>
);
......@@ -61,6 +65,7 @@ class Layout extends React.Component {
function mapStateToProps(state) {
return {
facilities: state.facilities.data,
alerts: state.alerts,
favorites: state.ui.favorites,
searchTerm: state.ui.search.term,
campusRegion: state.ui.search.campusRegion,
......@@ -73,6 +78,8 @@ function mapStateToProps(state) {
export default connect(mapStateToProps, {
getFacilities,
setFacilities,
getAlerts,
setAlerts,
setAllFavorites,
sortByFavorites,
setSidebar,
......
import {GET_FACILITIES, SET_FACILITIES, SORT_BY_FAVORITES} from '../actions/action-types';
import {GET_ALERTS, GET_FACILITIES, SET_ALERTS, SET_FACILITIES, SORT_BY_FAVORITES} from '../actions/action-types';
import cloneDeep from 'lodash/cloneDeep';
const defaultState = {
const defaultFacilityState = {
isLoading: false,
data: []
};
export const facilities = (state = defaultState, action, ui) => {
export const facilities = (state = defaultFacilityState, action, ui) => {
const sortFunc = (a, b) => {
const favoriteCheck = ui.favorites.includes(b.slug) - ui.favorites.includes(a.slug);
......@@ -44,3 +44,14 @@ export const facilities = (state = defaultState, action, ui) => {
return state;
}
};
export const alerts = (state = [], action) => {
switch (action.type) {
case GET_ALERTS:
return state;
case SET_ALERTS:
return [...state, ...action.alerts];
default:
return state;
}
};
import {routerReducer} from 'react-router-redux';
import ui from './ui';
import {facilities} from './api';
import {facilities, alerts} from './api';
const reducers = (state = {}, action) => ({
router: routerReducer(state.router, action),
ui: ui(state.ui, action),
facilities: facilities(state.facilities, action, state.ui)
facilities: facilities(state.facilities, action, state.ui),
alerts: alerts(state.alerts, action)
});
export default reducers;
.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
@import './variables.scss';
@import './mixins.scss';
/* Components */
@import './components/alert';
@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