first commit

This commit is contained in:
Senad Uka
2018-05-07 16:07:00 +02:00
commit 8b4f09f9d5
3368 changed files with 852614 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
/* global document, window */
const axios = require('axios');
const Instance = () => {
const apiUrl = process.env.NODE_ENV === 'production'
? 'https://portal-api.bcbsinstitute.com'
: 'https://portal-api.dev.bcbsinstitute.com';
window.localStorage.setItem('App', '8a266a40-ed2e-4be2-bdfc-459a507bf02e');
let instance = axios.create({
baseURL: apiUrl,
timeout: 60000,
headers: { App: window.localStorage.getItem('App') },
});
const setCookie = (cname, cvalue, date) => {
const d = new Date(date * 1000);
const expires = `expires=${d.toUTCString()}`;
document.cookie = `${cname}=${cvalue};${expires};path=/`;
};
const getCookie = (cname) => {
const name = `${cname}=`;
const decodedCookie = decodeURIComponent(document.cookie);
const ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i += 1) {
let c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return '';
};
const setToken = (token) => {
if (token && token !== null) {
instance = axios.create({
baseURL: apiUrl,
timeout: 60000,
headers: { App: window.localStorage.getItem('App'), Token: `Bearer ${token}` },
});
} else {
instance = axios.create({
baseURL: apiUrl,
timeout: 60000,
headers: { App: window.localStorage.getItem('App') },
});
}
return instance;
};
const getConnection = () => {
const token = getCookie('token');
return setToken(token);
};
const getRawConn = () => {
const token = getCookie('token');
if (token && token !== null && token !== '') {
return instance;
}
window.location.href = '/#/login';
return null;
};
const token = getCookie('token');
instance = setToken(token);
return {
getCookie,
setCookie,
getConnection,
setToken,
getRawConn,
};
};
export default Instance();

View File

@@ -0,0 +1,22 @@
import React from 'react';
import APPCONFIG from 'constants/Config';
import { Link } from 'react-router';
class Footer extends React.Component {
render() {
return (
<section className="app-footer">
<div className="container-fluid">
<span className="float-left">
<span>Copyright©{APPCONFIG.year} <a className="brand" target="_blank" href={APPCONFIG.productLink}>{APPCONFIG.brand}</a></span>
</span>
<span className="float-right">
<span></span>
</span>
</div>
</section>
);
}
}
module.exports = Footer;

View File

@@ -0,0 +1,33 @@
import React from 'react';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton/IconButton';
import { hashHistory } from 'react-router';
import Divider from 'material-ui/Divider';
import Badge from 'material-ui/Badge';
import NotificationsIcon from 'material-ui/svg-icons/social/notifications';
const HeaderIconButtonStyle = {
width: '60px',
height: '60px'
};
const listItemStyle = {
paddingLeft: '40px' // 36 + 16, algin with sub list
};
class NavLeftList extends React.Component {
handleChange = (event, value) => {
hashHistory.push(value);
}
render() {
return (
<div> </div>
);
}
}
module.exports = NavLeftList;

View File

@@ -0,0 +1,80 @@
import React from 'react';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton/IconButton';
import { hashHistory } from 'react-router';
const ImgIconButtonStyle = {
width: '60px',
height: '60px'
};
const listItemStyle = {
paddingLeft: '50px' // 36 + 16, algin with sub list
};
class NavRightList extends React.Component {
constructor(props) {
super(props);
this.props = props;
this.state = {
name: '',
useruuid: ''
}
this.handleChange = this.handleChange.bind(this);
}
handleChange = (event, value) => {
hashHistory.push(value);
}
componentDidMount() {
const user = JSON.parse(localStorage.getItem('loggedUser'));
if (user) {
this.setState(Object.assign(this.state, user));
}
}
render() {
return (
<ul className="list-unstyled float-right">
<li>
<IconMenu
iconButtonElement={<IconButton style={ImgIconButtonStyle}><img src="assets/images/ic_account_circle_white_48dp_1x.png" alt="" className="rounded-circle img30_30" /></IconButton>}
onChange={this.handleChange}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
targetOrigin={{ horizontal: 'right', vertical: 'top' }}
menuStyle={{ minWidth: '150px' }}
>
<MenuItem
onTouchTap={(e) => this.handleChange(e, `/app/authorizedusers/${this.state.useruuid}`)}
primaryText="Profile"
style={{ fontSize: '14px', lineHeight: '48px' }}
innerDivStyle={listItemStyle}
leftIcon={<i className="material-icons">account_circle</i>}
/>
<MenuItem
onTouchTap={(e) => this.handleChange(e, `/app/form/steppers/${this.state.useruuid}`)}
primaryText="Book Ride"
innerDivStyle={listItemStyle}
style={{ fontSize: '14px', lineHeight: '48px' }}
leftIcon={<i className="material-icons">mode_edit</i>}
/>
<MenuItem
onTouchTap={(e) => this.handleChange(e, `/login`)}
primaryText="Log Out"
innerDivStyle={listItemStyle}
style={{ fontSize: '14px', lineHeight: '48px' }}
leftIcon={<i className="material-icons">forward</i>}
/>
</IconMenu>
</li>
<li style={{ marginRight: '10px' }}><h6>{this.state.name}</h6></li>
</ul>
);
}
}
module.exports = NavRightList;

View File

@@ -0,0 +1,70 @@
import React from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import { Link } from 'react-router';
import APPCONFIG from 'constants/Config';
import NavLeftList from './NavLeftList';
import NavRightList from './NavRightList';
class Header extends React.Component {
componentDidMount() {
const sidebarToggler = this.sidebarBtn;
const $sidebarToggler = $(sidebarToggler);
const $body = $('#body');
$sidebarToggler.on('click', (e) => {
// _sidebar.scss, _page-container.scss
$body.toggleClass('sidebar-mobile-open');
});
}
render() {
const { isFixedHeader, colorOption } = this.props;
return (
<section className="app-header">
<div
className={classnames('app-header-inner', {
'bg-color-light': ['11', '12', '13', '14', '15', '16', '21'].indexOf(colorOption) >= 0,
'bg-color-dark': colorOption === '31',
'bg-color-primary': ['22', '32'].indexOf(colorOption) >= 0,
'bg-color-success': ['23', '33'].indexOf(colorOption) >= 0,
'bg-color-info': ['24', '34'].indexOf(colorOption) >= 0,
'bg-color-warning': ['25', '35'].indexOf(colorOption) >= 0,
'bg-color-danger': ['26', '36'].indexOf(colorOption) >= 0
})}
>
<div className="hidden-lg-up float-left">
<a href="javascript:;" className="md-button header-icon toggle-sidebar-btn" ref={(c) => { this.sidebarBtn = c; }}>
<i className="material-icons">menu</i>
</a>
</div>
<div className="brand hidden-md-down">
<h2><Link to="/">{APPCONFIG.brand}</Link></h2>
</div>
<div className="top-nav-left hidden-md-down">
<NavLeftList />
</div>
<div className="top-nav-right">
<NavRightList />
</div>
</div>
</section>
);
}
}
const mapStateToProps = state => ({
colorOption: state.settings.colorOption,
isFixedHeader: state.settings.isFixedHeader
});
module.exports = connect(
mapStateToProps
)(Header);

View File

@@ -0,0 +1,245 @@
import 'jquery-slimscroll/jquery.slimscroll.min';
import React from 'react';
import APPCONFIG from 'constants/Config';
import Badge from 'material-ui/Badge';
import NotificationsIcon from 'material-ui/svg-icons/social/notifications';
import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';
import { List, ListItem } from 'material-ui/List';
import Divider from 'material-ui/Divider';
import Subheader from 'material-ui/Subheader';
import MapsDirectionsCar from 'material-ui/svg-icons/maps/directions-car';
import ContactList from '../../routes/app/components/ContactList';
import Avatar from 'material-ui/Avatar';
import { grey400, darkBlack, lightBlack } from 'material-ui/styles/colors';
import IconButton from 'material-ui/IconButton';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import NavigationChevronRight from 'material-ui/svg-icons/navigation/more-vert';
// SocialNotificationsActive
class Notifications extends React.Component {
constructor(props) {
super(props);
const socketURL = process.env.NODE_ENV === 'production'
? 'wss://portal-api.bcbsinstitute.com/v1/notification/ws?id='
: 'wss://portal-api.dev.bcbsinstitute.com/v1/notification/ws?id='
this.props = props;
this.state = {
user: {
useruuid: '',
name: ''
},
socket_url: socketURL,
notifications: {},
totalNotifications: 0,
notificationList: [],
};
this.socket = null;
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
}
componentDidMount() {
this.setState(Object.assign(this.state, { user: this.props.user, notifications: [], totalNotifications: 0 }));
if (this.state.user.useruuid && this.state.user.useruuid != '') {
this.setState(Object.assign(this.state, { socket_url: this.state.socket_url + this.state.user.useruuid }));
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
// }
// const quickviewInner = this.quickview;
// $(quickviewInner).slimscroll({
// height: '100%'
// });
}
componentWillReceiveProps(nextProps) {
if (nextProps.user.useruuid !== this.state.user.useruuid) {
if (this.socket) {
this.socket.close();
}
this.setState(Object.assign(this.state, { user: nextProps.user, notifications: [], totalNotifications: 0 }));
if (this.state.user.useruuid && this.state.user.useruuid != '') {
this.setState(Object.assign(this.state, { socket_url: this.state.socket_url + this.state.user.useruuid }));
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
}
}
disableNotification(n) {
n.content.type = "disable-notification";
this.socket.send(JSON.stringify(n));
this.setState(Object.assign(this.state, { totalNotifications: this.state.totalNotifications-- }));
}
socketMessageListener(event) {
let n = JSON.parse(event.data);
let notifications = this.state.notifications;
if (notifications[n.nid] === null || notifications[n.nid] === undefined) {
notifications[n.nid] = n;
let notificationList = []
Object.keys(notifications).map((k) => {
const n = notifications[k];
switch (n.content.type) {
case 'ride':
const ride = n.content.payload;
const driverPhoneNumber = (ride.driver && ride.driver.phone_number) ? ride.driver.phone_number : '';
const rideContactList = {
driverMobile: driverPhoneNumber,
memberMobile: ride.user.phonenumber,
memberEmail: ride.user.email,
schedulerEmail: ride.created_user.email,
schedulerMobile: ride.created_user.phonenumber,
rideID: ride.ride_uuid,
};
const iconButtonElement = (
<IconButton
touch={true}
tooltip="Actions"
tooltipPosition="bottom-left"
>
<NavigationChevronRight color={grey400} />
{/* <MoreVertIcon color={grey400} /> */}
</IconButton>
);
const rightIconMenu = (
<IconMenu iconButtonElement={iconButtonElement}>
<MenuItem> <a href={"/#/app/member/" + n.content.payload.user.useruuid}>Member</a> </MenuItem>
<MenuItem> <a href="/#/app/table/visits/" > Visits </a> </MenuItem>
<MenuItem> <a href={"/#/ride/" + n.content.payload.ride_uuid + "/" + n.content.payload.user.useruuid}> Ride</a> </MenuItem>
<MenuItem><a href={"/#/app/page/map/" + n.content.payload.ride_uuid}> Ride Details </a> </MenuItem>
<MenuItem> <ContactList data={rideContactList} /> </MenuItem>
</IconMenu>
);
notificationList.push(
<div>
<ListItem
leftAvatar={<i className="nav-icon material-icons">directions_car</i>}
rightIconButton={rightIconMenu}
primaryText={n.content.subject}
secondaryText={
<p>
<span>{ride.user.name}</span><br />
{n.content.body}
</p>
}
secondaryTextLines={2}
/>
<Divider inset={true} />
</div>
);
break;
case 'message':
return
notificationList.push(
<Card id={n.id}>
<CardHeader
title={n.content.subject}
subtitle={ride.user.name + " | " + "Time Here"}
avatar={<Message />}
/>
<CardText>
{n.content.body}
</CardText>
<CardActions>
<ContactList data={rideContactList} />
</CardActions>
</Card>)
break;
}
})
this.setState(Object.assign(this.state, { notifications: notifications, totalNotifications: this.state.totalNotifications + 1, notificationList: notificationList }));
if (this.props.onNotificationUpdate) {
this.props.onNotificationUpdate(n, this.state.totalNotifications);
}
this.forceUpdate();
}
}
socketOpenListener(event) {
console.log('Connected for the ID: ' + this.state.user.useruuid);
}
socketCloseListener(event) {
if (this.socket) {
console.error('Disconnected.');
}
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
toggleCustomizer = () => {
const $body = $('#body');
$body.toggleClass('quickview-open-customizer');
}
closeCustomizer = () => {
const $body = $('#body');
$body.removeClass('quickview-open-customizer');
}
render() {
return (
<section
className="quickview-wrapper customizer theme-light"
id="quickview-customizer"
>
<a className="customizer-toggle" href="javascript:;" onClick={this.toggleCustomizer}>
<Badge
badgeStyle={{ top: 22, right: 16 }}
badgeContent={this.state.totalNotifications}
secondary={true}
primary={false}
>
<NotificationsIcon />
</Badge>
</a>
<List>
<Subheader>Today</Subheader>
{this.state.notificationList}
</List>
</section>
);
}
}
module.exports = Notifications;

View File

@@ -0,0 +1,106 @@
import React from 'react';
import PropTypes from 'prop-types';
import echarts from 'echarts';
import 'echarts/theme/macarons';
import elementResizeEvent from 'element-resize-event';
class ReactEcharts extends React.Component {
propTypes: {
option: PropTypes.object.isRequired,
notMerge: PropTypes.bool,
lazyUpdate: PropTypes.bool,
style: PropTypes.object,
className: PropTypes.string,
theme: PropTypes.string,
onChartReady: PropTypes.func,
showLoading: PropTypes.bool,
loadingOption: PropTypes.object,
onEvents: PropTypes.object
}
// first add
componentDidMount() {
const echartObj = this.renderEchartDom();
const onEvents = this.props.onEvents || {};
let reizeEvent;
this.bindEvents(echartObj, onEvents);
// on chart ready
if (typeof this.props.onChartReady === 'function') this.props.onChartReady(echartObj);
function resize() {
clearTimeout(reizeEvent);
reizeEvent = setTimeout(() => { echartObj.resize(); }, 200);
}
// on resize
elementResizeEvent(this.echartsDom, () => {
resize();
});
}
// update
componentDidUpdate() {
this.renderEchartDom();
this.bindEvents(this.getEchartsInstance(), this.props.onEvents || []);
}
// remove
componentWillUnmount() {
echarts.dispose(this.echartsDom);
}
// bind the events
bindEvents(instance, events) {
const loop = function loop(eventName) {
// ignore the event config which not satisfy
if (typeof eventName === 'string' && typeof events[eventName] === 'function') {
// binding event
instance.off(eventName);
instance.on(eventName, (param) => {
events[eventName](param, instance);
});
}
};
for (const eventName in events) {
loop(eventName);
}
}
// render the dom
renderEchartDom() {
// init the echart object
const echartObj = this.getEchartsInstance();
// set the echart option
echartObj.setOption(this.props.option, this.props.notMerge || false, this.props.lazyUpdate || false);
// set loading mask
if (this.props.showLoading) echartObj.showLoading(this.props.loadingOption || null);
else echartObj.hideLoading();
return echartObj;
}
getEchartsInstance() {
// return the echart object
const theme = this.props.theme ? this.props.theme : 'macarons';
return echarts.getInstanceByDom(this.echartsDom) || echarts.init(this.echartsDom, theme);
}
render() {
const style = this.props.style || {
height: '350px'
};
// for render
return (
<div
ref={(c) => { this.echartsDom = c; }}
className={this.props.className}
style={style} />
);
}
}
module.exports = ReactEcharts;

View File

@@ -0,0 +1,297 @@
import React, { Component } from 'react'
import Message from 'material-ui/svg-icons/communication/message';
import ReactMaterialUiNotifications from 'react-materialui-notifications';
import moment from 'moment';
import { deepOrange500 } from 'material-ui/styles/colors';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import lightTheme from '../../containers/themes/lightTheme';
import darkTheme from '../../containers/themes/darkTheme';
import grayTheme from '../../containers/themes/grayTheme';
import PropTypes from 'prop-types';
import FontIcon from 'material-ui/FontIcon';
import { indigo500 } from 'material-ui/styles/colors';
import Paper from 'material-ui/Paper';
import MapsDirectionsCar from 'material-ui/svg-icons/maps/directions-car';
import ContactList from '../../routes/app/components/ContactList';
const nearbyIcon = <FontIcon className="material-icons">perm phone msg</FontIcon>;
const paperStyle = {
height: 240,
width: 270,
margin: 10,
textAlign: 'center',
display: 'inline-block',
position: 'relative'
};
const styles = {
appbar: {
textAlign: 'left'
},
buttonContainer: {
display: 'flex',
justifyContent: 'space-around'
},
footer: {
marginTop: 15,
width: 'calc(100% - 30px)',
fontSize: 16,
padding: 15,
backgroundColor: '#fff'
},
logo: {
width: 48
},
paper: {
width: '100%',
textAlign: 'left',
marginBottom: 15,
padding: 15,
fontSize: 18
},
rightIcon: {
width: 36,
height: 36,
fill: '#fff'
},
table: {
marginTop: 15
},
headerStyle: {
tableLayout: 'auto'
},
table1Col1: {
width: 137
},
table1Col2: {
width: 72
},
table1Col3: {
width: 128
},
table1Col2C: {
width: 72,
},
table2Col3: {
width: 36
}
};
export default class Notification extends React.Component {
constructor(props) {
super(props);
const socketURL = process.env.NODE_ENV === 'production'
? 'wss://portal-api.bcbsinstitute.com/v1/notification/ws?id='
: 'wss://portal-api.dev.bcbsinstitute.com/v1/notification/ws?id='
this.props = props;
this.state = {
user: {
useruuid: '',
name: ''
},
socket_url: socketURL,
notifications: {},
totalNotifications: 0
};
this.socket = null;
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
}
componentDidMount() {
this.setState(Object.assign(this.state, { user: this.props.user, notifications: [], totalNotifications: 0 }));
if (this.state.user.useruuid && this.state.user.useruuid != '') {
this.setState(Object.assign(this.state, { socket_url: this.state.socket_url + this.state.user.useruuid }));
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.user.useruuid !== this.state.user.useruuid) {
if (this.socket) {
this.socket.close();
}
this.setState(Object.assign(this.state, { user: nextProps.user, notifications: [], totalNotifications: 0 }));
if (this.state.user.useruuid && this.state.user.useruuid != '') {
this.setState(Object.assign(this.state, { socket_url: this.state.socket_url + this.state.user.useruuid }));
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
}
}
disableNotification(n) {
n.content.type = "disable-notification";
this.socket.send(JSON.stringify(n));
this.setState(Object.assign(this.state, { totalNotifications: this.state.totalNotifications-- }));
}
socketMessageListener(event) {
let n = JSON.parse(event.data);
let notifications = this.state.notifications;
if (notifications[n.nid] === null || notifications[n.nid] === undefined) {
switch (n.content.type) {
case 'ride':
const ride = n.content.payload;
const driverPhoneNumber = (ride.driver && ride.driver.phone_number) ? ride.driver.phone_number : '';
const rideContactList = {
driverMobile: driverPhoneNumber,
memberMobile: ride.user.phonenumber,
memberEmail: ride.user.email,
schedulerEmail: ride.created_user.email,
schedulerMobile: ride.created_user.phonenumber,
rideID: ride.ride_uuid,
}
ReactMaterialUiNotifications.showNotification({
title: n.content.subject,
additionalText: n.content.payload.user.name,
priority: true,
icon: <MapsDirectionsCar />,
// icon: <Message />,
iconBadgeColor: indigo500,
personalized: true,
timestamp: moment(n.date).format('ddd, MMMM DD, hh:mm A'),
onClick: () => { this.disableNotification(n); },
overflowContent:
<div>
<div>
<div>
{n.content.body}
<p>
<a href={"/#/app/member/" + n.content.payload.user.useruuid}>Member</a> |
<a href="/#/app/table/visits/" > Visits </a> |
<a href={"/#/ride/" + n.content.payload.ride_uuid + "/" + n.content.payload.user.useruuid}> Ride</a> |
<a href={"/#/app/page/map/" + n.content.payload.ride_uuid}> Ride Details | </a>
<ContactList data={rideContactList} />
</p>
</div>
</div>
<div >
</div>
</div>,
});
if (this.props.onRideUpdate) {
this.props.onRideUpdate(n.content.payload);
}
break;
case 'message':
ReactMaterialUiNotifications.showNotification({
title: `Message Received`,
additionalText: n.content.payload.user.name,
priority: true,
icon: <Message />,
iconBadgeColor: deepOrange500,
personalized: true,
avatar: '/assets/images/ic_account_circle_white_48dp_1x.png',
timestamp: moment(n.date).format('ddd, MMMM DD, hh:mm A'),
onClick: () => { this.disableNotification(n); },
overflowContent:
<div>
<div>
{n.content.body}
</div>
<div>
<Paper style={paperStyle} zDepth={1} />
</div>
</div>
});
break;
}
notifications[n.nid] = n;
this.setState(Object.assign(this.state, { notifications: notifications, totalNotifications: this.state.totalNotifications++ }));
if (this.props.onNotificationUpdate) {
this.props.onNotificationUpdate(n, this.state.totalNotifications);
}
this.forceUpdate();
}
}
socketOpenListener(event) {
console.log('Connected for the ID: ' + this.state.user.useruuid);
}
socketCloseListener(event) {
if (this.socket) {
console.error('Disconnected.');
}
this.socket = new WebSocket(this.state.socket_url);
this.socketMessageListener = this.socketMessageListener.bind(this);
this.socketOpenListener = this.socketOpenListener.bind(this);
this.socketCloseListener = this.socketCloseListener.bind(this);
this.socket.addEventListener('open', this.socketOpenListener);
this.socket.addEventListener('message', this.socketMessageListener);
this.socket.addEventListener('close', this.socketCloseListener);
}
render() {
const { layoutBoxed, navCollapsed, navBehind, fixedHeader, sidebarWidth, theme } = this.props;
let materialUITheme;
switch (theme) {
case 'gray':
materialUITheme = grayTheme;
break;
case 'dark':
materialUITheme = darkTheme;
break;
default:
materialUITheme = lightTheme;
}
return (
<MuiThemeProvider muiTheme={getMuiTheme(materialUITheme)}>
<ReactMaterialUiNotifications
desktop={false}
transitionName={{
leave: 'dummy',
leaveActive: 'fadeOut',
appear: 'dummy',
appearActive: 'zoomInUp'
}}
transitionAppear={true}
transitionLeave={true}
/>
</MuiThemeProvider>
);
}
}
Notification.propTypes = {
user: PropTypes.object.isRequired,
onRideUpdate: PropTypes.func,
onNotificationUpdate: PropTypes.func,
}

View File

View File

@@ -0,0 +1,155 @@
import React from 'react';
import { Link, hashHistory } from 'react-router';
import FlatButton from 'material-ui/FlatButton';
import 'jquery-slimscroll/jquery.slimscroll.min';
import {
loggedUser,
planScheduler,
providerScheduler,
} from 'utils/authorization';
class SidebarContent extends React.Component {
state = {
user: {
user_uuid: '',
},
}
componentDidMount() {
const nav = this.nav;
const $nav = $(nav);
// scroll
$nav.slimscroll({
height: '100%'
});
// Append icon to submenu
// Append to child `div`
$nav.find('.prepend-icon').children('div').prepend('<i class="material-icons">keyboard_arrow_right</i>');
// AccordionNav
const slideTime = 250;
const $lists = $nav.find('ul').parent('li');
$lists.append('<i class="material-icons icon-has-ul">arrow_drop_down</i>');
const $As = $lists.children('a');
// Disable A link that has ul
$As.on('click', event => event.preventDefault());
// Accordion nav
$nav.on('click', (e) => {
const target = e.target;
const $parentLi = $(target).closest('li'); // closest, insead of parent, so it still works when click on i icons
if (!$parentLi.length) return; // return if doesn't click on li
const $subUl = $parentLi.children('ul');
// let depth = $subUl.parents().length; // but some li has no sub ul, so...
const depth = $parentLi.parents().length + 1;
// filter out all elements (except target) at current depth or greater
const allAtDepth = $nav.find('ul').filter(function () {
if ($(this).parents().length >= depth && this !== $subUl.get(0)) {
return true;
}
return false;
});
allAtDepth.slideUp(slideTime).closest('li').removeClass('open');
// Toggle target
if ($parentLi.has('ul').length) {
$parentLi.toggleClass('open');
}
$subUl.stop().slideToggle(slideTime);
});
// HighlightActiveItems
const $links = $nav.find('a');
const currentLocation = hashHistory.getCurrentLocation();
function highlightActive(pathname) {
const path = `#${pathname}`;
$links.each((i, link) => {
const $link = $(link);
const $li = $link.parent('li');
const href = $link.attr('href');
// console.log(href);
if ($li.hasClass('active')) {
$li.removeClass('active');
}
if (path.indexOf(href) === 0) {
$li.addClass('active');
}
});
}
highlightActive(currentLocation.pathname);
hashHistory.listen((location) => {
highlightActive(location.pathname);
});
const user = JSON.parse(localStorage.getItem('loggedUser'));
if (user) {
this.setState(Object.assign(this.state, { user: user }));
}
}
render() {
return (
<ul className="nav" ref={(c) => { this.nav = c; }}>
<li>
<FlatButton href="#/app/form"><i className="nav-icon material-icons cyan-text text-lighter-4">directions_car</i><span className="nav-text">Rides</span></FlatButton>
<ul>
<li><FlatButton className="prepend-icon" href={"#/app/form/steppers/" + this.state.user.useruuid}><span>Book Rides</span></FlatButton></li>
<li><FlatButton className="prepend-icon" href="#/app/table/rides"><span>Manage Rides</span></FlatButton></li>
</ul>
</li>
<li>
<FlatButton href="#/app/chart"><i className="nav-icon material-icons">people_outline</i><span className="nav-text">Members</span></FlatButton>
<ul>
<li><FlatButton className="prepend-icon" href="#/app/page/eligibility"><span>Verify Eligibility</span></FlatButton></li>
<li><FlatButton className="prepend-icon" href="#/app/table/members"><span>Manage Members</span></FlatButton></li>
</ul>
</li>
<li>
<FlatButton href="#/app/table/visits"><i className="nav-icon material-icons">schedule</i><span className="nav-text">Visits</span></FlatButton>
</li>
{/* <li>
<FlatButton href="#/app/table/message"><i className="nav-icon material-icons">mail_outline</i><span className="nav-text">Message Center</span></FlatButton>
</li> */}
<li>
<FlatButton href="#/app/chart"><i className="nav-icon material-icons">settings</i><span className="nav-text">Manage</span></FlatButton>
<ul>
{!loggedUser.anyOf(planScheduler, providerScheduler) &&
<li>
<FlatButton href="#/app/table/authorizedusers"><i className="nav-icon material-icons">people</i><span className="nav-text">Authorized Users</span></FlatButton>
</li>
}
<li>
<FlatButton href="#/app/table/organizations"><i className="nav-icon material-icons">assignment</i><span className="nav-text">Organizations</span></FlatButton>
</li>
<li>
<FlatButton href="#/app/table/provider"><i className="nav-icon material-icons">local_hospital</i><span className="nav-text">Participating Providers</span></FlatButton>
</li>
<li>
<FlatButton href={"#/app/authorizedusers/" + this.state.user.useruuid}><i className="nav-icon material-icons">account_circle</i><span className="nav-text">Profile</span></FlatButton>
</li>
{/* <li>
<FlatButton href="#/app/dashboard"><i className="nav-icon material-icons">equalizer</i><span className="nav-text">Reports</span></FlatButton>
</li> */}
</ul>
</li>
<li className="nav-divider" />
</ul>
);
}
}
module.exports = SidebarContent;

View File

@@ -0,0 +1,107 @@
import React from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import { Link, hashHistory } from 'react-router';
import APPCONFIG from 'constants/Config';
import {
toggleCollapsedNav
} from '../../actions';
import SidenavContent from './SidenavContent';
class Sidebar extends React.Component {
componentDidMount() {
// AutoCloseMobileNav
const $body = $('#body');
if (APPCONFIG.AutoCloseMobileNav) {
hashHistory.listen((location) => {
setTimeout(() => {
$body.removeClass('sidebar-mobile-open');
}, 0);
});
}
}
onToggleCollapsedNav = (e) => {
const val = !this.props.navCollapsed;
const { handleToggleCollapsedNav } = this.props;
handleToggleCollapsedNav(val);
}
render() {
const { navCollapsed, colorOption } = this.props;
let toggleIcon = null;
if (navCollapsed) {
toggleIcon = <i className="material-icons">radio_button_unchecked</i>;
} else {
toggleIcon = <i className="material-icons">radio_button_checked</i>;
}
return (
<nav
className={classnames('app-sidebar', {
'bg-color-light': ['31', '32', '33', '34', '35', '36'].indexOf(colorOption) >= 0,
'bg-color-dark': ['31', '32', '33', '34', '35', '36'].indexOf(colorOption) < 0
})}
>
<section
className={classnames('sidebar-header', {
'bg-color-dark': ['11', '31'].indexOf(colorOption) >= 0,
'bg-color-light': colorOption === '21',
'bg-color-primary': ['12', '22', '32'].indexOf(colorOption) >= 0,
'bg-color-success': ['13', '23', '33'].indexOf(colorOption) >= 0,
'bg-color-info': ['14', '24', '34'].indexOf(colorOption) >= 0,
'bg-color-warning': ['15', '25', '35'].indexOf(colorOption) >= 0,
'bg-color-danger': ['16', '26', '36'].indexOf(colorOption) >= 0
})}
>
<svg className="logo-img logo-react" viewBox="0 0 3925 3525" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle className="react-dot" stroke="none" cx="1960" cy="1760" r="355" />
<g className="react-curve" strokeWidth="170" fill="none">
<ellipse cx="2575" cy="545" rx="715" ry="1875" transform="rotate(30)" />
<ellipse cx="1760" cy="-1960" rx="715" ry="1875" transform="rotate(90)" />
<ellipse cx="-815" cy="-2505" rx="715" ry="1875" transform="rotate(-210)" />
</g>
</svg>
<Link to="/" className="brand">{APPCONFIG.brand}</Link>
<a href="javascript:;" className="collapsednav-toggler" onClick={this.onToggleCollapsedNav}>
{toggleIcon}
</a>
</section>
<section className="sidebar-content">
<SidenavContent />
</section>
<section className="sidebar-footer">
<ul className="nav">
<li>
<a target="_blank" href={APPCONFIG.productLink}>
<i className="nav-icon material-icons">help</i>
<span className="nav-text"><span>Help</span> & <span>Support</span></span>
</a>
</li>
</ul>
</section>
</nav>
);
}
}
const mapStateToProps = state => ({
navCollapsed: state.settings.navCollapsed,
colorOption: state.settings.colorOption
});
const mapDispatchToProps = dispatch => ({
handleToggleCollapsedNav: (isNavCollapsed) => {
dispatch(toggleCollapsedNav(isNavCollapsed));
},
});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(Sidebar);