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

23
src/actions/index.js Normal file
View File

@@ -0,0 +1,23 @@
import * as types from '../constants/ActionTypes';
export function toggleBoxedLayout(isLayoutBoxed) {
return { type: types.TOGGLE_BOXED_LAYOUT, isLayoutBoxed };
}
export function toggleCollapsedNav(isNavCollapsed) {
return { type: types.TOGGLE_COLLAPSED_NAV, isNavCollapsed };
}
export function toggleNavBehind(isNavBehind) {
return { type: types.TOGGLE_NAV_BEHIND, isNavBehind };
}
export function toggleFixedHeader(isFixedHeader) {
return { type: types.TOGGLE_FIXED_HEADER, isFixedHeader };
}
export function changeSidebarWidth(sidebarWidth) {
return { type: types.CHANGE_SIDEBAR_WIDTH, sidebarWidth };
}
export function changeColorOption(colorOption) {
return { type: types.CHANGE_COLOR_OPTION, colorOption };
}
export function changeTheme(themeOption) {
return { type: types.CHANGE_THEME, theme: themeOption };
}

BIN
src/assets/images/5_min.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
src/assets/images/5_min.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,29 @@
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
<svg width="55" height="80" viewBox="0 0 55 80" xmlns="http://www.w3.org/2000/svg" fill="#00BCD4">
<g transform="matrix(1 0 0 -1 0 80)">
<rect width="10" height="20" rx="1">
<animate attributeName="height"
begin="0s" dur="4.3s"
values="20;45;57;80;64;32;66;45;64;23;66;13;64;56;34;34;2;23;76;79;20" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="15" width="10" height="80" rx="1">
<animate attributeName="height"
begin="0s" dur="2s"
values="80;55;33;5;75;23;73;33;12;14;60;80" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="30" width="10" height="50" rx="1">
<animate attributeName="height"
begin="0s" dur="1.4s"
values="50;34;78;23;56;23;34;76;80;54;21;50" calcMode="linear"
repeatCount="indefinite" />
</rect>
<rect x="45" width="10" height="30" rx="1">
<animate attributeName="height"
begin="0s" dur="2s"
values="30;45;13;80;56;72;45;76;34;23;67;30" calcMode="linear"
repeatCount="indefinite" />
</rect>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

BIN
src/assets/images/g1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
src/assets/images/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

BIN
src/assets/images/prius.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

8
src/assets/react.svg Normal file
View File

@@ -0,0 +1,8 @@
<svg viewBox="0 0 3925 3525" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle stroke="none" fill="#67DAF9" cx="1960" cy="1760" r="355"></circle>
<g stroke="#67DAF9" stroke-width="170" fill="none">
<ellipse cx="2575" cy="545" rx="715" ry="1875" transform="rotate(30)"></ellipse>
<ellipse cx="1760" cy="-1960" rx="715" ry="1875" transform="rotate(90)"></ellipse>
<ellipse cx="-815" cy="-2505" rx="715" ry="1875" transform="rotate(-210)"></ellipse>
</g>
</svg>

After

Width:  |  Height:  |  Size: 503 B

88
src/client.js Normal file
View File

@@ -0,0 +1,88 @@
/* globals window, document */
/* eslint react/jsx-filename-extension: "off" */
import React from 'react';
import { render } from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { Router, hashHistory, browserHistory } from 'react-router';
import { syncHistoryWithStore, routerMiddleware } from 'react-router-redux';
import reducers from './reducers';
import Instance from './components/Connection';
const middleware = routerMiddleware(hashHistory);
const store = createStore(
reducers,
applyMiddleware(middleware),
);
window.localStorage.setItem('App', '8a266a40-ed2e-4be2-bdfc-459a507bf02e');
// instance.post('/v1/authenticate/portal', {
// email: 'carlos@brighterdevelopment.com',
// pass: 'VGVzdDIwMTc=',
// }).then(function (res) { localStorage.setItem('Token', res.data.token) });
const history = syncHistoryWithStore(hashHistory, store);
const isFunction = (functionToCheck) => {
const getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
};
const requireAuth = (nextState, replace, next) => {
if (nextState.location.pathname === '/login' || nextState.location.pathname === '/sign-up' || (nextState.location.pathname.indexOf('/ride') > -1 && nextState.params.ride_uuid !== undefined && nextState.params.user_uuid !== undefined)
|| (!isFunction(replace) && (replace.location.pathname === '/login' || replace.location.pathname === '/sign-up' || (replace.location.pathname.indexOf('/ride') > -1 && replace.params.ride_uuid !== undefined && replace.params.user_uuid !== undefined)))) {
next();
}
const token = Instance.getCookie('token');
if (!token || token === null || token === undefined || token === '') {
if (isFunction(replace)) {
replace('/login');
} else {
browserHistory.transitionTo('/login');
}
}
next();
};
function scrollToTop() {
window.scrollTo(0, 0);
}
const rootRoute = {
childRoutes: [{
path: '/',
onChange: requireAuth,
onEnter: requireAuth,
component: require('./containers/App'),
indexRoute: { onEnter: (nextState, replace) => replace('/app/table/rides') },
childRoutes: [
require('./routes/app'),
require('./routes/404'),
require('./routes/500'),
require('./routes/confirmEmail'),
require('./routes/forgotPassword'),
require('./routes/lockScreen'),
require('./routes/login'),
require('./routes/signUp'),
require('./routes/fullscreen'),
require('./routes/ride'),
require('./routes/ready'),
{
path: '*',
indexRoute: { onEnter: (nextState, replace) => replace('/404') },
},
],
}],
};
render(
<Provider store={store}>
<Router
onUpdate={scrollToTop}
history={history}
routes={rootRoute}
/>
</Provider>,
document.getElementById('app-container'),
);

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);

View File

@@ -0,0 +1,7 @@
export const TOGGLE_BOXED_LAYOUT = 'TOGGLE_BOXED_LAYOUT';
export const TOGGLE_COLLAPSED_NAV = 'TOGGLE_COLLAPSED_NAV';
export const TOGGLE_NAV_BEHIND = 'TOGGLE_NAV_BEHIND';
export const TOGGLE_FIXED_HEADER = 'TOGGLE_FIXED_HEADER';
export const CHANGE_SIDEBAR_WIDTH = 'CHANGE_SIDEBAR_WIDTH';
export const CHANGE_COLOR_OPTION = 'CHANGE_COLOR_OPTION';
export const CHANGE_THEME = 'CHANGE_THEME';

View File

@@ -0,0 +1,16 @@
const CHARTCONFIG = {
color: {
primary: 'rgba(33,150,243,.85)', // #0099CC
success: 'rgba(102,187,106,.85)', // #66BB6A
info: 'rgba(0,188,212,.85)', // #00BCD4
infoAlt: 'rgba(126,87,194,.85)', // #7E57C2
warning: 'rgba(255,202,40,.85)', // #FFCA28
danger: 'rgba(233,75,59,.85)', // #E94B3B
gray: 'rgba(221,221,221,.3)',
text: '#898989', // for dark theme as well
splitLine: 'rgba(0,0,0,.05)',
splitArea: ['rgba(250,250,250,0.035)', 'rgba(200,200,200,0.1)'],
}
};
module.exports = CHARTCONFIG;

31
src/constants/Config.js Normal file
View File

@@ -0,0 +1,31 @@
const date = new Date();
const year = date.getFullYear();
const APPCONFIG = {
brand: 'CHM Hub®',
user: 'Michael',
year,
productLink: 'portal.bdctest.com',
AutoCloseMobileNav: true, // true, false. Automatically close sidenav on route change (Mobile only)
color: {
primary: '#00BCD4',
success: '#8BC34A',
info: '#66BB6A',
infoAlt: '#7E57C2',
warning: '#FFCA28',
danger: '#F44336',
text: '#3D4051',
gray: '#EDF0F1'
},
settings: {
layoutBoxed: false, // true, false
navCollapsed: false, // true, false
navBehind: false, // true, false
fixedHeader: true, // true, false
sidebarWidth: 'middle', // small, middle, large
colorOption: '32', // String: 11,12,13,14,15,16; 21,22,23,24,25,26; 31,32,33,34,35,36
theme: 'light', // light, gray, dark
}
};
module.exports = APPCONFIG;

76
src/containers/App.js Normal file
View File

@@ -0,0 +1,76 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
// = styles =
// 3rd
import 'styles/bootstrap.scss';
// custom
import 'styles/layout.scss';
import 'styles/theme.scss';
import 'styles/ui.scss';
import 'styles/app.scss';
import lightTheme from './themes/lightTheme';
import darkTheme from './themes/darkTheme';
import grayTheme from './themes/grayTheme';
injectTapEventPlugin(); // Needed for onTouchTap for Material UI
class App extends Component {
componentDidMount() {}
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)}>
<div id="app-inner">
<div className="preloaderbar hide"><span className="bar" /></div>
<div
className={classnames('app-main full-height', {
'fixed-header': fixedHeader,
'nav-collapsed': navCollapsed,
'nav-behind': navBehind,
'layout-boxed': layoutBoxed,
'theme-gray': theme === 'gray',
'theme-dark': theme === 'dark',
'sidebar-sm': sidebarWidth === 'small',
'sidebar-lg': sidebarWidth === 'large'})
}>
{this.props.children}
</div>
</div>
</MuiThemeProvider>
);
}
}
const mapStateToProps = (state, ownProps) => ({
layoutBoxed: state.settings.layoutBoxed,
navCollapsed: state.settings.navCollapsed,
navBehind: state.settings.navBehind,
fixedHeader: state.settings.fixedHeader,
sidebarWidth: state.settings.sidebarWidth,
theme: state.settings.theme,
});
module.exports = connect(
mapStateToProps
)(App);

View File

@@ -0,0 +1,33 @@
import {
cyan700,
grey600,
green600, green400, green200,
fullWhite,
} from 'material-ui/styles/colors';
import {fade} from 'material-ui/utils/colorManipulator';
import spacing from 'material-ui/styles/spacing';
// $dark: #333C44 !default; // darken Blue 100 > #343E46
// $theme_dark_text_color: rgba(255,255,255,.7);
export default {
spacing,
fontFamily: 'Roboto, sans-serif',
borderRadius: 2,
palette: {
primary1Color: cyan700,
primary2Color: cyan700,
primary3Color: grey600,
accent1Color: green600,
accent2Color: green400,
accent3Color: green200,
textColor: 'rgba(255,255,255,.7)',
secondaryTextColor: fade(fullWhite, 0.54),
alternateTextColor: '#333C44',
canvasColor: '#333C44',
borderColor: fade(fullWhite, 0.15),
disabledColor: fade(fullWhite, 0.3),
pickerHeaderColor: fade(fullWhite, 0.12),
clockCircleColor: fade(fullWhite, 0.12),
},
};

View File

@@ -0,0 +1,33 @@
import {
cyan700,
grey600,
green600, green200, green400,
fullWhite,
} from 'material-ui/styles/colors';
import {fade} from 'material-ui/utils/colorManipulator';
import spacing from 'material-ui/styles/spacing';
// $theme_gray_sidebar_bg_color: grayscale($theme_dark_sidebar_bg_color); // or 3c3c3c
// $theme_dark_text_color: rgba(255,255,255,.7);
export default {
spacing,
fontFamily: 'Roboto, sans-serif',
borderRadius: 2,
palette: {
primary1Color: cyan700,
primary2Color: cyan700,
primary3Color: grey600,
accent1Color: green600,
accent2Color: green400,
accent3Color: green200,
textColor: 'rgba(255,255,255,.7)',
secondaryTextColor: fade(fullWhite, 0.54),
alternateTextColor: '#3c3c3c',
canvasColor: '#3c3c3c',
borderColor: fade(fullWhite, 0.15),
disabledColor: fade(fullWhite, 0.3),
pickerHeaderColor: fade(fullWhite, 0.12),
clockCircleColor: fade(fullWhite, 0.12),
},
};

View File

@@ -0,0 +1,36 @@
import {
cyan500, cyan700,
green400,
grey100, grey300, grey400, grey500,
white, darkBlack, fullBlack,
} from 'material-ui/styles/colors';
import {fade} from 'material-ui/utils/colorManipulator';
import spacing from 'material-ui/styles/spacing';
/**
* Light Theme is the default theme used in material-ui. It is guaranteed to
* have all theme variables needed for every component. Variables not defined
* in a custom theme will default to these values.
*/
export default {
spacing,
fontFamily: 'Roboto, sans-serif',
borderRadius: 2,
palette: {
primary1Color: cyan500,
primary2Color: cyan700,
primary3Color: grey400,
accent1Color: green400,
accent2Color: grey100,
accent3Color: grey500,
textColor: darkBlack,
secondaryTextColor: fade(darkBlack, 0.54),
alternateTextColor: white,
canvasColor: white,
borderColor: grey300,
disabledColor: fade(darkBlack, 0.3),
pickerHeaderColor: cyan500,
clockCircleColor: fade(darkBlack, 0.07),
shadowColor: fullBlack,
},
};

10
src/reducers/index.js Normal file
View File

@@ -0,0 +1,10 @@
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import settings from './settings';
const reducers = {
routing: routerReducer,
settings
};
module.exports = combineReducers(reducers);

57
src/reducers/settings.js Normal file
View File

@@ -0,0 +1,57 @@
import APPCONFIG from 'constants/Config';
import {
TOGGLE_BOXED_LAYOUT,
TOGGLE_COLLAPSED_NAV,
TOGGLE_NAV_BEHIND,
TOGGLE_FIXED_HEADER,
CHANGE_SIDEBAR_WIDTH,
CHANGE_COLOR_OPTION,
CHANGE_THEME
} from '../constants/ActionTypes';
const initialSettings = APPCONFIG.settings;
const settings = (state = initialSettings, action) => {
// console.log(action)
switch (action.type) {
case TOGGLE_BOXED_LAYOUT:
return {
...state,
layoutBoxed: action.isLayoutBoxed
};
case TOGGLE_COLLAPSED_NAV:
return {
...state,
navCollapsed: action.isNavCollapsed
};
case TOGGLE_NAV_BEHIND:
return {
...state,
navBehind: action.isNavBehind
};
case TOGGLE_FIXED_HEADER:
return {
...state,
fixedHeader: action.isFixedHeader
};
case CHANGE_SIDEBAR_WIDTH:
return {
...state,
sidebarWidth: action.sidebarWidth
};
case CHANGE_COLOR_OPTION:
return {
...state,
colorOption: action.colorOption
};
case CHANGE_THEME:
return {
...state,
theme: action.theme
};
default:
return state;
}
};
module.exports = settings;

View File

@@ -0,0 +1,29 @@
import React from 'react';
import QueueAnim from 'rc-queue-anim';
const Error404 = () => (
<div className="err-container text-center">
<div className="err">
<h1>404</h1>
<h2>Sorry, page not found</h2>
</div>
<div className="err-body">
<a href="#/" className="btn btn-raised btn-lg btn-default">
Go Back to Home Page
</a>
</div>
</div>
);
const Page = () => (
<div className="page-err">
<QueueAnim type="bottom" className="ui-animate">
<div key="1">
<Error404 />
</div>
</QueueAnim>
</div>
);
module.exports = Page;

8
src/routes/404/index.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
path: '404',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/404'));
});
}
};

View File

@@ -0,0 +1,29 @@
import React from 'react';
import QueueAnim from 'rc-queue-anim';
const Error500 = () => (
<div className="err-container text-center">
<div className="err">
<h1>500</h1>
<h2>Sorry, server goes wrong</h2>
</div>
<div className="err-body">
<a href="#/" className="btn btn-raised btn-lg btn-default">
Go Back to Home Page
</a>
</div>
</div>
);
const Page = () => (
<div className="page-err">
<QueueAnim type="bottom" className="ui-animate">
<div key="1">
<Error500 />
</div>
</QueueAnim>
</div>
);
module.exports = Page;

8
src/routes/500/index.js Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
path: '500',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/500'));
});
}
};

View File

@@ -0,0 +1,245 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import Link from 'react-router';
import ActionHome from 'material-ui/svg-icons/action/home';
import ActionWork from 'material-ui/svg-icons/action/work';
import MapsMyLocation from 'material-ui/svg-icons/maps/my-location';
import MapsAddLocation from 'material-ui/svg-icons/maps/add-location';
import MapsNearMe from 'material-ui/svg-icons/maps/near-me';
import MapsLocalHospital from 'material-ui/svg-icons/maps/local-hospital';
import MapsLocalPharmacy from 'material-ui/svg-icons/maps/local-pharmacy';
import AutoComplete from 'material-ui/AutoComplete';
import { fullWhite } from 'material-ui/styles/colors';
import Dialog from 'material-ui/Dialog';
import { List, ListItem, makeSelectable } from 'material-ui/List';
import TextField from 'material-ui/TextField';
import Divider from 'material-ui/Divider';
import ArrowDropRight from 'material-ui/svg-icons/navigation-arrow-drop-right';
import RaisedButton from 'material-ui/RaisedButton';
// import FlatButton from 'material-ui/FlatButton';
import IconButton from 'material-ui/IconButton';
import Popover from 'material-ui/Popover';
import CommunicationChatBubble from 'material-ui/svg-icons/communication/chat-bubble';
import { indigo500 } from 'material-ui/styles/colors';
import CommunicationEmail from 'material-ui/svg-icons/communication/email';
import CommunicationTextsms from 'material-ui/svg-icons/communication/textsms';
import CommunicationCall from 'material-ui/svg-icons/communication/call';
import Close from 'material-ui/svg-icons/navigation/close';
import $ from 'jquery';
import Instance from '../../../components/Connection';
export default class ContactList extends React.Component {
constructor(props) {
super(props);
this.props = props;
this.state = {
open: false,
data: {
driverMobile: "",
memberMobile: "",
memberEmail: "",
schedulerEmail: "",
schedulerMobile: "",
rideID: "",
},
anchorEl: null,
formMode: 'hide',
formDisplay: 'none',
message: '',
};
this.handleMobileCall = this.handleMobileCall.bind(this);
this.handleMailTo = this.handleMailTo.bind(this);
this.handleSMS = this.handleSMS.bind(this);
this.handleCancelMessage = this.handleCancelMessage.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleRequestClose = this.handleRequestClose.bind(this);
this.handleMessage = this.handleMessage.bind(this);
this.handleMessageField = this.handleMessageField.bind(this);
this.handleSend = this.handleSend.bind(this);
}
componentDidMount = () => {
const self = this;
if (this.props.data && this.props.data !== null) {
this.setState(Object.assign(this.state, { data: this.props.data }));
}
}
componentWillReceiveProps = (nextProps) => {
const self = this;
if (nextProps.data && nextProps.data !== null) {
this.setState(Object.assign(this.state, { data: nextProps.data }));
}
}
handleDriverMessage = (message) => {
const rideID = this.state.data.rideID;
let url = '/v1/nemt/rides/' + rideID + '/message/driver';
url = encodeURI(url);
Instance.getRawConn().post(url, { message: message }).then(function (res) {
alert('Message Send');
}).catch(function (err) {
console.error(err);
});
}
handleMessage = (message) => {
const rideID = this.state.data.rideID;
let url = '/v1/nemt/rides/' + rideID + '/message';
url = encodeURI(url);
return Instance.getRawConn().post(url, { message: message });
}
handleCancelMessage = () => {
event.preventDefault();
this.setState(Object.assign(this.state, { formDisplay: 'none', open: false }));
console.log("handleCancelMessage")
};
handleMailTo = (event, to, from, subject) => {
event.preventDefault();
this.setState(Object.assign(this.state, { formMode: subject, formDisplay: 'block' }));
console.log("handleMailTo" + to + from + subject)
};
handleMobileCall = (event, to, from, subject) => {
event.preventDefault();
this.setState(Object.assign(this.state, { formMode: subject, formDisplay: 'none' }));
// window.open("tel:" + this.state.memberMobile );
window.open("tel:" + to);
console.log("handleMobileCall" + "to " + to + "from " + from)
};
handleSMS = (event, toMobilePhone, fromMobilePhone, subject) => {
event.preventDefault();
this.setState(Object.assign(this.state, { formMode: subject, formDisplay: 'block', message: '' }));
}
handleSend = (event, toMobilePhone, fromMobilePhone, subject) => {
event.preventDefault();
const self = this;
self.handleMessage(self.state.message).then(res => {
alert('Message Sent');
self.setState(Object.assign(self.state, { formMode: '', formDisplay: 'none', message: '' }));
}).catch(console.error);
};
handleClick = (event) => {
event.preventDefault();
this.setState(Object.assign(this.state, { open: true, anchorEl: event.currentTarget }));
};
handleRequestClose = () => {
this.setState(Object.assign(this.state, { formDisplay: 'none' }));
this.setState(Object.assign(this.state, { open: false }));
};
handleMessageField = (e) => {
this.setState(Object.assign(this.state, { message: e.target.value }));
}
render() {
return (
<div style={{ "padding": '0px', 'margin': '0px', 'align': 'top', 'display': 'inline' }} >
<a href="#" onClick={this.handleClick} > Contact </a>
<Popover
open={this.state.open}
anchorEl={this.state.anchorEl}
anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
targetOrigin={{ horizontal: 'left', vertical: 'top' }}
onRequestClose={this.handleRequestClose}
>
<div id="popoverContentWrapper" >
<div id="smsFormWrapper" style={{ display: this.state.formDisplay }}>
<form className="form-vertical" style={{ paddingLeft: '20px', paddingRight: '20px' }} >
<fieldset>
<div className="form-group">
<TextField
floatingLabelText="Subject"
hintText="Subject"
value={this.state.formMode}
// errorText="This field is required.
// onChange={this.handleFirst}
// onBlur={this.buttonValidated}
/>
</div>
<div className="form-group">
<TextField
floatingLabelText="Message"
hintText="Message Field"
errorText="This field is required."
multiLine={true}
rows={3}
onChange={this.handleMessageField}
value={this.state.message}
// onBlur={this.buttonValidated}
/>
</div>
<div className="form-group">
<RaisedButton
label="Send"
primary={true}
onClick={this.handleSend}
// disabled={!this.state.validated}
/>
<RaisedButton
label="Cancel"
onClick={this.handleCancelMessage}
// disabled={!this.state.validated}
/>
</div>
<div className="divider" />
<div className="form-group">
<p className="text-small">By clicking Send, you agree to <a href="javascript:;"><i>terms</i></a> and <a href="javascript:;"><i>privacy policy</i></a></p>
</div>
</fieldset>
</form>
</div>
<div id="contactListWrapper" >
<List>
<ListItem
leftIcon={<CommunicationCall color={indigo500} onTouchTap={(e) => this.handleMobileCall(e, this.state.data.driverMobile, this.state.data.schedulerMobile, "Call to Driver from Scheduler")} />}
insetChildren={true}
rightIcon={<CommunicationChatBubble color={indigo500} onTouchTap={(e) => this.handleSMS(e, this.state.data.driverMobile, this.state.data.schedulerMobile, "SMS to Driver from Scheduler")} />}
primaryText={this.state.data.driverMobile}
secondaryText="Driver"
/>
<ListItem
leftIcon={<CommunicationCall color={indigo500} onTouchTap={(e) => this.handleMobileCall(e, this.state.data.memberMobile, this.state.data.schedulerMobile, "Call to Member from Scheduler")} />}
insetChildren={true}
rightIcon={<CommunicationChatBubble color={indigo500} onTouchTap={(e) => this.handleSMS(e, this.state.data.memberMobile, this.state.data.schedulerMobile, "SMS to Member from Scheduler")} />}
primaryText={this.state.data.memberMobile}
secondaryText="Member"
/>
<ListItem color={indigo500}
leftIcon={<CommunicationEmail onTouchTap={(e) => this.handleMailTo(e, this.state.data.memberEmail, 'no-reply@hcmhub.com', 'Email to Member from Scheduler')} />}
primaryText={this.state.data.memberEmail}
secondaryText="Member"
/>
</List>
</div>
</div>
</Popover>
</div>
);
}
}
ContactList.PropTypes = {
data: PropTypes.object.isRequired,
}

View File

@@ -0,0 +1,105 @@
import React from 'react';
import Delete from 'material-ui/svg-icons/action/delete';
import Create from 'material-ui/svg-icons/content/create';
import Call from 'material-ui/svg-icons/communication/call';
import TextSms from 'material-ui/svg-icons/communication/textsms';
import Mail from 'material-ui/svg-icons/content/mail';
import IconButton from 'material-ui/IconButton';
import PropTypes from 'prop-types';
const ContactOption = (props) => {
const buttonStyle = {
marginTop: -10
};
const divStyle = {
inlineSize: "max-content"
};
const handleRemoveContact = (c) => {
if (props.onContactDeleted) {
props.onContactDeleted(c);
} else {
console.log('onContactDelete is undefined');
console.log(c);
}
};
const handleUpdateContact = (c) => {
if (props.onContactUpdated) {
props.onContactUpdated(c);
} else {
console.log('onContactUpdate is undefined');
console.log(c);
}
};
const handleCustomAction = (c) => {
console.log('This is a custom action: ', c);
if (props.onCustomAction) {
props.onCustomAction(c);
} else {
console.log('onCustomAction is undefined');
console.log(c);
}
}
let deleteButton = null
if (props.showDelete) {
deleteButton = (<IconButton onTouchTap={(e) => handleRemoveContact(props.contact)} style={buttonStyle}><Delete /></IconButton>);
}
let updateButton = null;
if (props.showEdit) {
updateButton = (<IconButton onTouchTap={(e) => handleUpdateContact(props.contact)} style={buttonStyle}><Create /></IconButton>);
}
const actionButton = [];
if (props.showAction && props.contact.type.key) {
switch (props.contact.type.key) {
case "phone":
case "landline":
actionButton.push(<IconButton onTouchTap={(e) => handleCustomAction(props.contact)} style={buttonStyle}><Call /></IconButton>);
break;
case "mobile":
case "sms":
actionButton.push(<IconButton onTouchTap={(e) => handleCustomAction(props.contact)} style={buttonStyle}><TextSms /></IconButton>);
actionButton.push(<IconButton onTouchTap={(e) => handleCustomAction(props.contact)} style={buttonStyle}><Call /></IconButton>);
break;
case "email":
actionButton.push(<IconButton onTouchTap={(e) => handleCustomAction(props.contact)} style={buttonStyle}><Mail /></IconButton>);
break;
}
}
return (
<div style={divStyle}>
{deleteButton}
{updateButton}
{actionButton}
</div>
);
};
ContactOption.propTypes = {
contact: PropTypes.object.isRequired,
showEdit: PropTypes.bool,
showDelete: PropTypes.bool,
showAction: PropTypes.bool,
showName: PropTypes.bool,
showDescription: PropTypes.bool,
onContactDeleted: PropTypes.func,
onContactUpdated: PropTypes.func,
onCustomAction: PropTypes.func,
};
ContactOption.defaultProps = {
showEdit: true,
showDelete: true,
showName: true,
showDescription: true,
showAction: true,
};
module.exports = ContactOption;

View File

@@ -0,0 +1,65 @@
import React from 'react';
import PropTypes from 'prop-types';
const GeolocationService = function () {
let watcherID;
let initTime;
const init = () => {
if (navigator.geolocation) {
stop();
initTime = new Date();
watcherID = navigator.geolocation.watchPosition(geoLocationSuccess, geoLocationError, geoLocationOption());
// console.log(`Start finding location: Watcher ID (${watcherID})`);
}
};
const geoLocationSuccess = (position) => {
const seconds = (new Date().getTime() - initTime.getTime()) / 1000;
// console.log(`Current Position (took ${seconds}s): `);
localStorage.setItem('currentLocation', JSON.stringify({ lat: position.coords.latitude, long: position.coords.longitude }));
initTime = new Date();
};
const geoLocationError = (error) => {
console.error('Error to get position: ', error);
// init();
};
const geoLocationOption = () => {
return {
enableHighAccuracy: true,
};
};
const getCoordinates = () => {
const currentLocation = localStorage.getItem('currentLocation');
if (currentLocation) {
let geo = JSON.parse(currentLocation);
if (!geo.lat || !geo.long) {
return { lat: 41.819078, long: -87.623129 };
} else {
return geo;
}
} else {
return { lat: 41.819078, long: -87.623129 };
};
};
const stop = () => {
if (watcherID) {
navigator.geolocation.clearWatch(watcherID);
}
};
init();
return {
Stop: stop,
GetCoordinates: getCoordinates,
};
}();
module.exports = GeolocationService;

View File

@@ -0,0 +1,63 @@
import React from 'react';
import Header from 'components/Header';
import Sidenav from 'components/Sidenav';
import Footer from 'components/Footer';
import Notifications from 'components/Notifications';
import Notification from 'components/Shared/Notification';
import GeolocationService from './Geolocation';
class MainApp extends React.Component {
constructor(props) {
super(props);
this.props = props;
this.state = {
user: {
useruuid: '',
name: ''
}
}
this.handleRide = this.handleRide.bind(this);
}
componentDidMount() {
const user = JSON.parse(localStorage.getItem('loggedUser'));
if (user) {
this.setState(Object.assign(this.state, { user: user }));
}
}
handleRide(ride) {
if (this.props.onRideUpdate) {
this.props.onRideUpdate(ride);
}
}
render() {
const { children, location } = this.props;
return (
<div className="main-app-container">
<Sidenav />
<section id="page-container" className="app-page-container">
<Header />
<div className="app-content-wrapper">
<div className="app-content">
<div className="full-height">
{children}
</div>
</div>
<Footer />
</div>
</section>
<Notifications user={this.state.user} onRideUpdate={this.handleRide} />
{/* <Notification user={this.state.user} onRideUpdate={this.handleRide} /> */}
</div>
);
}
}
module.exports = MainApp;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
import React from 'react';
import Delete from 'material-ui/svg-icons/action/delete';
import Create from 'material-ui/svg-icons/content/create';
import Call from 'material-ui/svg-icons/communication/call';
import TextSms from 'material-ui/svg-icons/communication/textsms';
import Mail from 'material-ui/svg-icons/content/mail';
import IconButton from 'material-ui/IconButton';
import PropTypes from 'prop-types';
import Instance from '../../../components/Connection';
const RoadTripLink = (props) => {
const onClick = (e, r) => {
let url = `/v1/nemt/rides/${r.ride_uuid}`;
if (props.isOpened) {
url = `/v1/ext/${r.ride_uuid}/${r.user.useruuid}`;
}
Instance.getRawConn().get(url).then(res => {
if (props.onRideClick) {
props.onRideClick(res.data);
} else {
console.log(res.data);
}
}).catch(console.error);
return false;
}
let rideList = [];
if (props.rides) {
console.log(props.rides)
rideList = props.rides.map((r, i) => {
let separator = '|';
if (props.rides.length === 1 || props.rides.length === i + 1) {
separator = '';
}
if (props.isLink == true) {
return (<span> <a href={location.href} onTouchTap={(e) => onClick(e, r)}>{r.trip_type.value}</a> {separator}</span>)
} else {
return (<span> {r.trip_type.value} {separator}</span>)
}
});
}
return (
<div>
{rideList}
</div>
)
}
RoadTripLink.propTypes = {
visit: PropTypes.object.isRequired,
rides: PropTypes.array.isRequired,
currentRide: PropTypes.object,
isOpened: PropTypes.bool,
isLink: PropTypes.bool,
onRideClick: PropTypes.func,
};
RoadTripLink.defaultProps = {
visit: {},
rides: [],
currentRide: {},
isOpened: false,
isLink: false,
onRideClick: (ride) => { console.log(ride); },
};
module.exports = RoadTripLink;

25
src/routes/app/index.js Normal file
View File

@@ -0,0 +1,25 @@
module.exports = {
path: 'app',
getChildRoutes(partialNextState, cb) {
require.ensure([], (require) => {
cb(null, [
require('./routes/charts'),
require('./routes/dashboard'),
// require('./routes/ecommerce'),
require('./routes/forms'),
require('./routes/pageLayouts'),
require('./routes/pages'),
require('./routes/tables'),
require('./routes/ui'),
require('./routes/member'),
require('./routes/organization'),
require('./routes/users'),
]);
});
},
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/MainApp'));
});
}
};

View File

@@ -0,0 +1,16 @@
module.exports = {
path: 'chart',
getChildRoutes(partialNextState, cb) {
require.ensure([], (require) => {
cb(null, [
require('./routes/bar'),
require('./routes/funnel'),
require('./routes/line'),
require('./routes/more'),
require('./routes/pie'),
require('./routes/radar'),
require('./routes/scatter'),
]);
});
}
};

View File

@@ -0,0 +1,546 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const bar1 = {};
const bar2 = {};
const bar3 = {};
const bar4 = {};
const bar5 = {};
bar1.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Evaporation', 'Precipitation'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Evaporation',
type: 'bar',
data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
},
{
name: 'Precipitation',
type: 'bar',
data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],
markPoint: {
data: [
{name: 'Highest', value: 182.2, xAxis: 7, yAxis: 183, symbolSize: 18},
{name: 'Lowest', value: 2.3, xAxis: 11, yAxis: 3}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
}
]
};
bar2.options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Direct', 'Email', 'Affiliate', 'Video Ads', 'Search', 'Baidu', 'Google', 'Bing', 'Others'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Direct',
type: 'bar',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: 'Email',
type: 'bar',
stack: 'Ads',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Affiliate',
type: 'bar',
stack: 'Ads',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Video Ads',
type: 'bar',
stack: 'Ads',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: 'Search',
type: 'bar',
data: [862, 1018, 964, 1026, 1679, 1600, 1570],
markLine: {
itemStyle: {
normal: {
lineStyle: {
type: 'dashed'
}
}
},
data: [
[{type: 'min'}, {type: 'max'}]
]
}
},
{
name: 'Baidu',
type: 'bar',
barWidth: 5,
stack: 'Search',
data: [620, 732, 701, 734, 1090, 1130, 1120]
},
{
name: 'Google',
type: 'bar',
stack: 'Search',
data: [120, 132, 101, 134, 290, 230, 220]
},
{
name: 'Bing',
type: 'bar',
stack: 'Search',
data: [60, 72, 71, 74, 190, 130, 110]
},
{
name: 'Others',
type: 'bar',
stack: 'Search',
data: [62, 82, 91, 84, 109, 110, 120]
}
]
};
bar3.options = {
title: {
text: 'World Population',
subtext: 'From the Internet'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['2011', '2012'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'value',
boundaryGap: [0, 0.01],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'category',
data: ['Brazil', 'Indonesia', 'USA', 'India', 'China', 'World Population (10k)'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: '2011',
type: 'bar',
data: [18203, 23489, 29034, 104970, 131744, 630230]
},
{
name: '2012',
type: 'bar',
data: [19325, 23438, 31000, 121594, 134141, 681807]
}
]
};
bar4.options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Direct', 'Email', 'Affiliate', 'Video Ads', 'Search'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'category',
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Direct',
type: 'bar',
stack: 'Sum',
itemStyle: { normal: {label: {show: true, position: 'insideRight'}}},
data: [320, 302, 301, 334, 390, 330, 320]
},
{
name: 'Email',
type: 'bar',
stack: 'Sum',
itemStyle: { normal: {label: {show: true, position: 'insideRight'}}},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Affiliate',
type: 'bar',
stack: 'Sum',
itemStyle: { normal: {label: {show: true, position: 'insideRight'}}},
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Video Ads',
type: 'bar',
stack: 'Sum',
itemStyle: { normal: {label: {show: true, position: 'insideRight'}}},
data: [150, 212, 201, 154, 190, 330, 410]
},
{
name: 'Search',
type: 'bar',
stack: 'Sum',
itemStyle: { normal: {label: {show: true, position: 'insideRight'}}},
data: [820, 832, 901, 934, 1290, 1330, 1320]
}
]
};
bar5.options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Savings', 'Cost', 'Income'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'category',
axisTick: {show: false},
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Savings',
type: 'bar',
itemStyle: { normal: {label: {show: true, position: 'inside'}}},
data: [200, 170, 240, 244, 200, 220, 210]
},
{
name: 'Income',
type: 'bar',
stack: 'Sum',
barWidth: 5,
itemStyle: {normal: {
label: {show: true}
}},
data: [320, 302, 341, 374, 390, 450, 420]
},
{
name: 'Cost',
type: 'bar',
stack: 'Sum',
itemStyle: {normal: {
label: {show: true, position: 'left'}
}},
data: [-120, -132, -101, -134, -190, -230, -210]
}
]
};
const Section1 = () => (
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Column</div>
<div className="box-body">
<ReactEcharts option={bar1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Stacked Column</div>
<div className="box-body">
<ReactEcharts option={bar2.options} showLoading={false} />
</div>
</div>
</div>
</div>
);
const Section2 = () => (
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Bar</div>
<div className="box-body">
<ReactEcharts option={bar3.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Stacked Bar</div>
<div className="box-body">
<ReactEcharts option={bar4.options} showLoading={false} />
</div>
</div>
</div>
</div>
);
const Section3 = () => (
<div className="row">
<div className="col-xl-12">
<div className="box box-default">
<div className="box-heading">Tornado</div>
<div className="box-body">
<ReactEcharts option={bar5.options} showLoading={false} />
</div>
</div>
</div>
</div>
);
const Bar = () => (
<div className="container-fluid no-breadcrumbs">
<Section1 />
<Section2 />
<Section3 />
</div>
);
module.exports = Bar;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'bar',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Bar'));
});
}
};

View File

@@ -0,0 +1,261 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const funnel1 = {};
const funnel2 = {};
const funnel3 = {};
funnel1.options = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
legend: {
data: ['Dispaly', 'Click', 'Visit', 'Question', 'Order'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
calculable: true,
series: [
{
name: 'Funnel',
type: 'funnel',
x: '10%',
y: 60,
// x2: 80,
y2: 60,
width: '80%',
// height: {totalHeight} - y - y2,
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
sort: 'descending', // 'ascending', 'descending'
gap: 10,
itemStyle: {
normal: {
borderColor: '#fff',
borderWidth: 1,
label: {
show: true,
position: 'inside'
},
labelLine: {
show: false,
length: 10,
lineStyle: {
width: 1,
type: 'solid'
}
}
},
emphasis: {
label: {
show: true,
formatter: '{b}:{c}%'
},
labelLine: {
show: true
}
}
},
data: [
{value: 60, name: 'Visit'},
{value: 40, name: 'Question'},
{value: 20, name: 'Order'},
{value: 80, name: 'Click'},
{value: 100, name: 'Dispaly'}
]
}
]
};
funnel2.options = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
legend: {
data: ['Display', 'Click', 'Visit', 'Question', 'Order'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
series: [
{
name: 'Forecast',
type: 'funnel',
left: '10%',
width: '80%',
label: {
normal: {
formatter: '{b} Forecast'
},
emphasis: {
position: 'inside',
formatter: '{b} Forecast: {c}%'
}
},
labelLine: {
normal: {
show: false
}
},
itemStyle: {
normal: {
opacity: 0.7
}
},
data: [
{value: 60, name: 'Visit'},
{value: 40, name: 'Question'},
{value: 20, name: 'Order'},
{value: 80, name: 'Click'},
{value: 100, name: 'Display'}
]
},
{
name: 'Reality',
type: 'funnel',
left: '10%',
width: '80%',
maxSize: '80%',
label: {
normal: {
position: 'inside',
formatter: '{c}%',
textStyle: {
color: '#fff'
}
},
emphasis: {
position: 'inside',
formatter: '{b} Reality: {c}%'
}
},
itemStyle: {
normal: {
opacity: 0.5,
borderColor: '#fff',
borderWidth: 2
}
},
data: [
{value: 30, name: 'Visit'},
{value: 10, name: 'Ask'},
{value: 5, name: 'Order'},
{value: 50, name: 'Click'},
{value: 80, name: 'Display'}
]
}
]
};
funnel3.options = {
title: {
text: 'Funnel',
subtext: 'Fake Data'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
legend: {
data: ['Dispaly', 'Click', 'Visit', 'Question', 'Order'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
calculable: true,
series: [
{
name: 'Funnel',
type: 'funnel',
width: '40%',
data: [
{value: 60, name: 'Visit'},
{value: 40, name: 'Question'},
{value: 20, name: 'Order'},
{value: 80, name: 'Click'},
{value: 100, name: 'Dispaly'}
]
},
{
name: 'Pyramid',
type: 'funnel',
x: '50%',
sort: 'ascending',
itemStyle: {
normal: {
label: {
position: 'left'
}
}
},
data: [
{value: 60, name: 'Visit'},
{value: 40, name: 'Question'},
{value: 20, name: 'Order'},
{value: 80, name: 'Click'},
{value: 100, name: 'Dispaly'}
]
}
]
};
const Funnel = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Funnel</div>
<div className="box-body">
<ReactEcharts option={funnel1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Multiple Funnel</div>
<div className="box-body">
<ReactEcharts option={funnel2.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="box box-default">
<div className="box-heading">Funnels</div>
<div className="box-body">
<ReactEcharts option={funnel3.options} showLoading={false} />
</div>
</div>
</div>
);
module.exports = Funnel;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'funnel',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Funnel'));
});
}
};

View File

@@ -0,0 +1,419 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const line1 = {};
const line2 = {};
const line3 = {};
const line4 = {};
line1.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Highest temperature', 'Lowest temperature'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
formatter: '{value} °C',
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
formatter: '{value} °C',
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Highest temperature',
type: 'line',
data: [11, 11, 15, 13, 12, 13, 10],
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
},
{
name: 'Lowest temperature',
type: 'line',
data: [1, -2, 2, 5, 3, 2, 0],
markPoint: {
data: [
{name: 'Lowest temperature', value: -2, xAxis: 1, yAxis: -1.5}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
}
]
};
line2.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Email', 'Affiliate', 'Video Ads', 'Direct', 'Search'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Email',
type: 'line',
stack: 'Sum',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Affiliate',
type: 'line',
stack: 'Sum',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Video Ads',
type: 'line',
stack: 'Sum',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: 'Direct',
type: 'line',
stack: 'Sum',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: 'Search',
type: 'line',
stack: 'Sum',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
line3.options = {
title: {
text: 'Miles',
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Intention', 'Pre-order', 'Deal closed'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Deal closed',
type: 'line',
smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [10, 12, 21, 54, 260, 830, 710]
},
{
name: 'Pre-order',
type: 'line',
smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [30, 182, 434, 791, 390, 30, 10]
},
{
name: 'Intention',
type: 'line',
smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [1320, 1132, 601, 234, 120, 90, 20]
}
]
};
line4.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Email', 'Affiliate', 'Video Ads', 'Direct', 'Search'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
type: 'value',
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Email',
type: 'line',
stack: 'Sum',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Affiliate',
type: 'line',
stack: 'Sum',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Video Ads',
type: 'line',
stack: 'Sum',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: 'Direct',
type: 'line',
stack: 'Sum',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: 'Search',
type: 'line',
stack: 'Sum',
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
const Line = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Base Line</div>
<div className="box-body">
<ReactEcharts option={line1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Stacked Line</div>
<div className="box-body">
<ReactEcharts option={line2.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Base Area</div>
<div className="box-body">
<ReactEcharts option={line3.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Stacked Area</div>
<div className="box-body">
<ReactEcharts option={line4.options} showLoading={false} />
</div>
</div>
</div>
</div>
</div>
);
module.exports = Line;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'line',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Line'));
});
}
};

View File

@@ -0,0 +1,189 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const gauge1 = {};
const pie5 = {};
const heatmapHours = [
'12a', '1a', '2a', '3a', '4a', '5a', '6a',
'7a', '8a', '9a', '10a', '11a',
'12p', '1p', '2p', '3p', '4p', '5p',
'6p', '7p', '8p', '9p', '10p', '11p'];
const heatmapDays = ['Saturday', 'Friday', 'Thursday',
'Wednesday', 'Tuesday', 'Monday', 'Sunday'];
const heatmapDataSource = [[0, 0, 5], [0, 1, 1], [0, 2, 0], [0, 3, 0], [0, 4, 0], [0, 5, 0], [0, 6, 0], [0, 7, 0], [0, 8, 0], [0, 9, 0], [0, 10, 0], [0, 11, 2], [0, 12, 4], [0, 13, 1], [0, 14, 1], [0, 15, 3], [0, 16, 4], [0, 17, 6], [0, 18, 4], [0, 19, 4], [0, 20, 3], [0, 21, 3], [0, 22, 2], [0, 23, 5], [1, 0, 7], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0], [1, 5, 0], [1, 6, 0], [1, 7, 0], [1, 8, 0], [1, 9, 0], [1, 10, 5], [1, 11, 2], [1, 12, 2], [1, 13, 6], [1, 14, 9], [1, 15, 11], [1, 16, 6], [1, 17, 7], [1, 18, 8], [1, 19, 12], [1, 20, 5], [1, 21, 5], [1, 22, 7], [1, 23, 2], [2, 0, 1], [2, 1, 1], [2, 2, 0], [2, 3, 0], [2, 4, 0], [2, 5, 0], [2, 6, 0], [2, 7, 0], [2, 8, 0], [2, 9, 0], [2, 10, 3], [2, 11, 2], [2, 12, 1], [2, 13, 9], [2, 14, 8], [2, 15, 10], [2, 16, 6], [2, 17, 5], [2, 18, 5], [2, 19, 5], [2, 20, 7], [2, 21, 4], [2, 22, 2], [2, 23, 4], [3, 0, 7], [3, 1, 3], [3, 2, 0], [3, 3, 0], [3, 4, 0], [3, 5, 0], [3, 6, 0], [3, 7, 0], [3, 8, 1], [3, 9, 0], [3, 10, 5], [3, 11, 4], [3, 12, 7], [3, 13, 14], [3, 14, 13], [3, 15, 12], [3, 16, 9], [3, 17, 5], [3, 18, 5], [3, 19, 10], [3, 20, 6], [3, 21, 4], [3, 22, 4], [3, 23, 1], [4, 0, 1], [4, 1, 3], [4, 2, 0], [4, 3, 0], [4, 4, 0], [4, 5, 1], [4, 6, 0], [4, 7, 0], [4, 8, 0], [4, 9, 2], [4, 10, 4], [4, 11, 4], [4, 12, 2], [4, 13, 4], [4, 14, 4], [4, 15, 14], [4, 16, 12], [4, 17, 1], [4, 18, 8], [4, 19, 5], [4, 20, 3], [4, 21, 7], [4, 22, 3], [4, 23, 0], [5, 0, 2], [5, 1, 1], [5, 2, 0], [5, 3, 3], [5, 4, 0], [5, 5, 0], [5, 6, 0], [5, 7, 0], [5, 8, 2], [5, 9, 0], [5, 10, 4], [5, 11, 1], [5, 12, 5], [5, 13, 10], [5, 14, 5], [5, 15, 7], [5, 16, 11], [5, 17, 6], [5, 18, 0], [5, 19, 5], [5, 20, 3], [5, 21, 4], [5, 22, 2], [5, 23, 0], [6, 0, 1], [6, 1, 0], [6, 2, 0], [6, 3, 0], [6, 4, 0], [6, 5, 0], [6, 6, 0], [6, 7, 0], [6, 8, 0], [6, 9, 0], [6, 10, 1], [6, 11, 0], [6, 12, 2], [6, 13, 1], [6, 14, 3], [6, 15, 4], [6, 16, 0], [6, 17, 0], [6, 18, 0], [6, 19, 0], [6, 20, 1], [6, 21, 2], [6, 22, 2], [6, 23, 6]];
const heatmapData = heatmapDataSource.map(item => [item[1], item[0], item[2] || '-']);
const heatmap1 = {};
gauge1.options = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
series: [
{
name: 'Business metric',
type: 'gauge',
detail: {formatter: '{value}%'},
data: [{value: 50, name: 'Completion'}],
title: {
textStyle: {
color: CHARTCONFIG.color.text
}
}
}
]
};
pie5.options = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
show: false,
orient: 'vertical',
x: 'left',
data: ['Direct', 'Ads', 'Search', 'Email Marketing', 'Affiliates', 'Video Ads', 'Google', 'Bing', 'Others'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
series: [
{
name: 'Traffic Source',
type: 'pie',
selectedMode: 'single',
radius: [0, '30%'],
label: {
normal: {
position: 'inner'
}
},
labelLine: {
normal: {
show: false
}
},
data: [
{value: 355, name: 'Direct', selected: true},
{value: 679, name: 'Ads'},
{value: 1401, name: 'Search'}
]
},
{
name: 'Traffic Source',
type: 'pie',
radius: ['40%', '55%'],
data: [
{value: 355, name: 'Direct'},
{value: 310, name: 'Email Marketing'},
{value: 234, name: 'Affiliates'},
{value: 135, name: 'Video Ads'},
{value: 1048, name: 'Google'},
{value: 251, name: 'Bing'},
{value: 102, name: 'Others'}
]
}
]
};
heatmap1.options = {
tooltip: {
position: 'top'
},
animation: false,
grid: {
height: '50%',
y: '10%'
},
xAxis: {
type: 'category',
data: heatmapHours,
splitArea: {
show: true
}
},
yAxis: {
type: 'category',
data: heatmapDays,
splitArea: {
show: true
}
},
visualMap: {
min: 0,
max: 10,
calculable: true,
orient: 'horizontal',
left: 'center',
bottom: '15%'
},
series: [{
name: 'Punch Card',
type: 'heatmap',
data: heatmapData,
label: {
normal: {
show: true
}
},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}]
};
const More = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Gauge</div>
<div className="box-body">
<ReactEcharts option={gauge1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Pie</div>
<div className="box-body">
<ReactEcharts option={pie5.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="box box-default">
<div className="box-heading">Heatmap</div>
<div className="box-body">
<ReactEcharts option={heatmap1.options} showLoading={false} />
</div>
</div>
</div>
);
module.exports = More;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'more',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/More'));
});
}
};

View File

@@ -0,0 +1,232 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const pie1 = {};
const pie2 = {};
const pie4 = {};
pie1.options = {
title: {
text: 'Traffic Source',
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
x: 'left',
data: ['Direct', 'Email', 'Affiliate', 'Video Ads', 'Search'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
series: [
{
name: 'Vist source',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [
{value: 335, name: 'Direct'},
{value: 310, name: 'Email'},
{value: 234, name: 'Affiliate'},
{value: 135, name: 'Video Ads'},
{value: 1548, name: 'Search'}
]
}
]
};
pie2.options = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
x: 'left',
data: ['Direct', 'Email', 'Affiliate', 'Video Ads', 'Search'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
series: [
{
name: 'Traffic source',
type: 'pie',
radius: ['50%', '70%'],
itemStyle: {
normal: {
label: {
show: false
},
labelLine: {
show: false
}
},
emphasis: {
label: {
show: true,
position: 'center',
textStyle: {
fontSize: '30',
fontWeight: 'bold'
}
}
}
},
data: [
{value: 335, name: 'Direct'},
{value: 310, name: 'Email'},
{value: 234, name: 'Affiliate'},
{value: 135, name: 'Video Ads'},
{value: 1548, name: 'Search'}
]
}
]
};
pie4.options = {
title: {
text: 'Nightingale rose diagram',
x: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
x: 'center',
y: 'bottom',
data: ['rose1', 'rose2', 'rose3', 'rose4', 'rose5', 'rose6', 'rose7', 'rose8'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
series: [
{
name: 'Radius model',
type: 'pie',
radius: [20, 110],
center: ['25%', 200],
roseType: 'radius',
width: '40%', // for funnel
max: 40, // for funnel
itemStyle: {
normal: {
label: {
show: false
},
labelLine: {
show: false
}
},
emphasis: {
label: {
show: true
},
labelLine: {
show: true
}
}
},
data: [
{value: 10, name: 'rose1'},
{value: 5, name: 'rose2'},
{value: 15, name: 'rose3'},
{value: 25, name: 'rose4'},
{value: 20, name: 'rose5'},
{value: 35, name: 'rose6'},
{value: 30, name: 'rose7'},
{value: 40, name: 'rose8'}
]
},
{
name: 'Area model',
type: 'pie',
radius: [30, 110],
center: ['75%', 200],
roseType: 'area',
x: '50%', // for funnel
max: 40, // for funnel
sort: 'ascending', // for funnel
data: [
{value: 10, name: 'rose1'},
{value: 5, name: 'rose2'},
{value: 15, name: 'rose3'},
{value: 25, name: 'rose4'},
{value: 20, name: 'rose5'},
{value: 35, name: 'rose6'},
{value: 30, name: 'rose7'},
{value: 40, name: 'rose8'}
]
}
]
};
const Pie = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Pie</div>
<div className="box-body">
<ReactEcharts option={pie1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Doughnut</div>
<div className="box-body">
<ReactEcharts option={pie2.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-xl-12">
<div className="box box-default">
<div className="box-heading">Nightingale's Rose Diagram</div>
<div className="box-body">
<ReactEcharts option={pie4.options} showLoading={false} />
</div>
</div>
</div>
</div>
</div>
);
module.exports = Pie;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'pie',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Pie'));
});
}
};

View File

@@ -0,0 +1,333 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const radar1 = {};
const radar2 = {};
const radar3 = {};
radar1.options = {
title: {
text: 'Budget vs spending'
},
tooltip: {},
legend: {
orient: 'vertical',
x: 'right',
y: 'bottom',
data: ['Allocated Budget', 'Actual Spending'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
radar: [
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: [
{ name: 'Miles', max: 6000},
{ name: 'Administration', max: 16000},
{ name: 'Information Techology', max: 30000},
{ name: 'Customer Support', max: 38000},
{ name: 'Development', max: 52000},
{ name: 'Marketing', max: 25000}
]
}
],
calculable: true,
series: [
{
name: 'Budget vs spending',
type: 'radar',
data: [
{
value: [4300, 10000, 28000, 35000, 50000, 19000],
name: 'Allocated Budget'
},
{
value: [5000, 14000, 28000, 31000, 42000, 21000],
name: 'Actual Spending'
}
]
}
]
};
radar2.options = {
tooltip: {},
legend: {
x: 'center',
data: ['Ronaldo', 'Andriy Shevchenko'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
calculable: true,
radar: [
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: [
{name: 'Attack', max: 100},
{name: 'Guard', max: 100},
{name: 'Physical', max: 100},
{name: 'Speed', max: 100},
{name: 'Strength', max: 100},
{name: 'Skill', max: 100}
],
radius: 130
}
],
series: [
{
name: 'Full of live data',
type: 'radar',
itemStyle: {
normal: {
areaStyle: {
type: 'default'
}
}
},
data: [
{
value: [97, 42, 88, 94, 90, 86],
name: 'Andriy Shevchenko'
},
{
value: [97, 32, 74, 95, 88, 92],
name: 'Ronaldo'
}
]
}
]
};
radar3.options = {
// title: {
// text: 'Mutiple Radar'
// },
tooltip: {
trigger: 'axis'
},
legend: {
x: 'center',
data: ['Software', 'Galaxy Phone', 'iPhone', 'Precipitation', 'Evaporation'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
radar: [
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: [
{text: 'Brand', max: 100},
{text: 'Content', max: 100},
{text: 'Usability', max: 100},
{text: 'Features', max: 100}
],
center: ['25%', '40%'],
radius: 80
},
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: [
{text: 'Look', max: 100},
{text: 'Camera', max: 100},
{text: 'System', max: 100},
{text: 'Performance', max: 100},
{text: 'Display', max: 100}
],
radius: 80,
center: ['50%', '60%'],
},
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: (function () {
const res = [];
for (let i = 1; i <= 12; i++) {
res.push({text: `Mon. ${i}`, max: 100});
}
return res;
}()),
center: ['75%', '40%'],
radius: 80
}
],
series: [
{
type: 'radar',
tooltip: {
trigger: 'item'
},
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [
{
value: [60, 73, 85, 40],
name: 'Software'
}
]
},
{
type: 'radar',
radarIndex: 1,
data: [
{
value: [85, 90, 90, 95, 95],
name: 'Galaxy Phone'
},
{
value: [95, 80, 95, 90, 93],
name: 'iPhone'
}
]
},
{
type: 'radar',
radarIndex: 2,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [
{
name: 'Precipitation',
value: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 75.6, 82.2, 48.7, 18.8, 6.0, 2.3],
},
{
name: 'Evaporation',
value: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 35.6, 62.2, 32.6, 20.0, 6.4, 3.3]
}
]
}
]
};
const Radar = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Radar</div>
<div className="box-body">
<ReactEcharts option={radar1.options} showLoading={false} />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-heading">Basic Filled Radar</div>
<div className="box-body">
<ReactEcharts option={radar2.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="box box-default">
<div className="box-heading">Basic Gauge</div>
<div className="box-body">
<ReactEcharts option={radar3.options} showLoading={false} />
</div>
</div>
</div>
);
module.exports = Radar;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'radar',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Radar'));
});
}
};

View File

@@ -0,0 +1,366 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const scatter1 = {};
const scatter2 = {};
scatter1.options = {
title: {
text: 'Height and weight distribution',
subtext: 'Data: Heinz 2003'
},
tooltip: {
trigger: 'axis',
showDelay: 0,
formatter(params) {
if (params.value.length > 1) {
return `${params.seriesName} :<br/>${
params.value[0]}cm ${
params.value[1]}kg `;
}
return `${params.seriesName} :<br/>${
params.name} : ${
params.value}kg `;
},
axisPointer: {
show: true,
type: 'cross',
lineStyle: {
type: 'dashed',
width: 1
}
}
},
legend: {
data: ['Femail', 'Male'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
xAxis: [
{
type: 'value',
scale: true,
axisLabel: {
formatter: '{value} cm',
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: false
}
}
],
yAxis: [
{
type: 'value',
scale: true,
axisLabel: {
formatter: '{value} kg',
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Femail',
type: 'scatter',
data: [
[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
[170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
[172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
[147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
[159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
[174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
[154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
[162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
[168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
[167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
[167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
[168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
[156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
[162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
[151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
[164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
[170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
[163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
[161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
[159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
[161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
[171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
[166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
[159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
[162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
[172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
[162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
[158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
[167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
[170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
[160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
[166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
[170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
[167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
[160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
[177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
[172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
[175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
[165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
[168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
[162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
[157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
[172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
[161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
[152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
[160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
[167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
[175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
[174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
[156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
[169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
[176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]
],
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
},
{
name: 'Male',
type: 'scatter',
data: [
[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],
[181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],
[180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],
[184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],
[176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],
[178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],
[183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],
[170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],
[186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],
[182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],
[169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],
[163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],
[177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],
[167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],
[171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],
[174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],
[180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],
[180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],
[175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],
[176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],
[184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],
[157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],
[165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],
[185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],
[177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],
[188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],
[166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],
[185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],
[190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],
[176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],
[172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],
[167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],
[172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],
[193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],
[167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],
[188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],
[171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],
[182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],
[188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],
[175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],
[177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],
[174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],
[167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],
[175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],
[177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],
[174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],
[174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],
[180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],
[170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],
[180.3, 83.2], [180.3, 83.2]
],
markPoint: {
data: [
{type: 'max', name: 'Max'},
{type: 'min', name: 'Min'}
]
},
markLine: {
data: [
{type: 'average', name: 'Average'}
]
}
}
]
};
function random() {
const r = Math.round(Math.random() * 100);
return (r * (r % 2 === 0 ? 1 : -1));
}
function randomDataArray() {
const d = [];
let len = 100;
while (len--) {
d.push([
random(),
random(),
Math.abs(random()),
]);
}
return d;
}
scatter2.options = {
tooltip: {
trigger: 'axis',
showDelay: 0,
axisPointer: {
show: true,
type: 'cross',
lineStyle: {
type: 'dashed',
width: 1
}
}
},
legend: {
data: ['scatter1', 'scatter2'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: true,
feature: {
saveAsImage: {show: true, title: 'save'}
}
},
xAxis: [
{
type: 'value',
splitNumber: 4,
scale: true,
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: false
}
}
],
yAxis: [
{
type: 'value',
splitNumber: 4,
scale: true,
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'scatter1',
type: 'scatter',
symbolSize(value) {
return Math.round(value[2] / 5);
},
data: randomDataArray()
},
{
name: 'scatter2',
type: 'scatter',
symbolSize(value) {
return Math.round(value[2] / 5);
},
data: randomDataArray()
}
]
};
const Scatter = () => (
<div className="container-fluid no-breadcrumbs">
<div className="row">
<div className="col-xl-12">
<div className="box box-default">
<div className="box-heading">Basic Scatter</div>
<div className="box-body">
<ReactEcharts option={scatter1.options} showLoading={false} />
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-xl-12">
<div className="box box-default">
<div className="box-heading">Basic Bubble</div>
<div className="box-body">
<ReactEcharts option={scatter2.options} showLoading={false} />
</div>
</div>
</div>
</div>
</div>
);
module.exports = Scatter;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'Scatter',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Scatter'));
});
}
};

View File

@@ -0,0 +1,71 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
const data = [{
value: 350,
name: 'Display',
}, {
value: 560,
name: 'Social'
}, {
value: 980,
name: 'Direct'
}, {
value: 760,
name: 'Search'
}, {
value: 320,
name: 'Referrals'
}];
const pie = {};
pie.options = {
tooltip: {
show: true,
trigger: 'item',
formatter: '{b}: {c} ({d}%)'
},
legend: {
show: false,
orient: 'vertical',
x: 'right',
data: ['Display', 'Social', 'Direct', 'Search', 'Referrals'],
},
series: [{
type: 'pie',
selectedMode: 'single',
radius: ['40%', '52%'],
color: [
'#EFE04C',
'#69D361',
'#47DAB5',
'#4AC3D6',
'#5EA1DA',
],
label: {
normal: {
position: 'outside',
formatter: '{b}',
textStyle: {
fontSize: 12
}
}
},
labelLine: {
normal: {
show: true
}
},
data,
markPint: {
symbol: 'diamond',
data: [{symbol: 'diamond', }]
}
}]
};
const Chart = () => (
<ReactEcharts style={{height: '400px'}} option={pie.options} showLoading={false} />
);
module.exports = Chart;

View File

@@ -0,0 +1,83 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const radar = {};
radar.options = {
legend: {
orient: 'vertical',
x: 'right',
y: 'bottom',
data: ['Plan Average', 'Independence Blue Cross & Blue Shield'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: false,
},
radar: [
{
axisLine: {
show: true,
lineStyle: {
// for both indicator and axisLine, bad, better seperate them
color: '#b1b1b1'
}
},
splitLine: {
lineStyle: {
color: 'rgba(0,0,0,.1)'
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
},
indicator: [
{ name: 'Miles', max: 6000},
{ name: 'Administration', max: 16000},
{ name: 'Info Tech', max: 30000},
{ name: 'Customer Support', max: 38000},
{ name: 'Development', max: 52000},
{ name: 'Marketing', max: 25000}
]
}
],
calculable: true,
series: [
{
name: 'Budget vs spending',
type: 'radar',
data: [
{
value: [5000, 14000, 28000, 31000, 42000, 21000],
name: 'Plan Average',
itemStyle: {
normal: {
color: CHARTCONFIG.color.success
}
}
},
{
value: [4300, 10000, 28000, 35000, 50000, 19000],
name: 'Independence Blue Cross & Blue Shield',
itemStyle: {
normal: {
color: CHARTCONFIG.color.info
}
}
}
]
}
]
};
const Chart = () => (
<ReactEcharts option={radar.options} showLoading={false} />
);
module.exports = Chart;

View File

@@ -0,0 +1,84 @@
import React from 'react';
import QueueAnim from 'rc-queue-anim';
import KPIsChart from './KPIsChart';
import AquisitionChart from './AquisitionChart';
import StatBoxes from './StatBoxes';
import EngagementStats from './EngagementStats';
import BenchmarkChart from './BenchmarkChart';
const Main = () => (
<div className="row">
<div className="col-xl-6">
<div className="box box-default">
<div className="box-body">
<KPIsChart />
</div>
</div>
</div>
<div className="col-xl-6">
<div className="box box-default">
<div className="box-body">
<AquisitionChart />
</div>
</div>
</div>
</div>
);
const Engagement = () => (
<div className="box box-default">
<div className="box-body">
<div className="row">
<div className="col-xl-8">
<div className="box box-transparent">
<div className="box-header">Engagement</div>
<div className="box-body">
<div className="row text-center metrics">
<div className="col-xs-6 col-md-3 metric-box">
<span className="metric">2.6M</span>
<span className="metric-info">Visits</span>
</div>
<div className="col-xs-6 col-md-3 metric-box">
<span className="metric">4.5M</span>
<span className="metric-info">Users</span>
</div>
<div className="col-xs-6 col-md-3 metric-box">
<span className="metric">08:03</span>
<span className="metric-info">RIDE DURATION</span>
</div>
<div className="col-xs-6 col-md-3 metric-box">
<span className="metric">5.25</span>
<span className="metric-info">MILES PER RIDE</span>
</div>
</div>
<EngagementStats />
</div>
</div>
</div>
<div className="col-xl-4">
<div className="box box-transparent">
<div className="box-header">Benchmark</div>
<div className="box-body">
<BenchmarkChart />
</div>
</div>
</div>
</div>
</div>
</div>
);
const Dashboard = () => (
<div className="container-fluid no-breadcrumbs page-dashboard">
<QueueAnim type="bottom" className="ui-animate">
<Main />
<div key="2"><StatBoxes /></div>
<div key="3"><Engagement /></div>
</QueueAnim>
</div>
);
module.exports = Dashboard;

View File

@@ -0,0 +1,133 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
// Engagment pie charts
const labelTop = {
normal: {
show: true,
position: 'center',
formatter: '{b}',
textStyle: {
color: 'rgba(0,0,0,.54)',
baseline: 'bottom',
fontSize: 14
}
}
};
// const labelTop = {
// normal : {
// color: CHARTCONFIG.color.info,
// label : {
// show : true,
// position : 'center',
// formatter : '{b}',
// textStyle: {
// color: CHARTCONFIG.color.text,
// baseline : 'bottom',
// fontSize: 14
// }
// },
// labelLine : {
// show : false
// }
// }
// };
const labelFromatter = {
normal: {
label: {
formatter(params) {
return `${100 - params.value}%`;
},
textStyle: {
color: 'rgba(0,0,0,.54)',
baseline: 'bottom',
fontSize: 12
}
}
},
};
const labelBottom = {
normal: {
color: 'rgba(0,0,0,.1)',
label: {
show: true,
position: 'center'
},
labelLine: {
show: false
}
}
};
const radius = [65, 70];
const pie = {};
const pie1 = {};
const pie2 = {};
const pie3 = {};
const pie4 = {};
pie1.options = {
series: [{
type: 'pie',
radius,
itemStyle: labelFromatter,
data: [
{name: 'To Provider', value: 36, label: labelTop, labelLine: {normal: {show: false}}, itemStyle: {normal: {color: CHARTCONFIG.color.success}}},
{name: 'other', value: 64, itemStyle: labelBottom}
]
}]
};
pie2.options = {
series: [{
type: 'pie',
radius,
itemStyle: labelFromatter,
data: [
{name: 'From Provider', value: 45, label: labelTop, itemStyle: {normal: {color: CHARTCONFIG.color.info}}},
{name: 'other', value: 55, itemStyle: labelBottom}
]
}]
};
pie3.options = {
series: [{
type: 'pie',
radius,
itemStyle: labelFromatter,
data: [
{name: 'Round Trip', value: 25, label: labelTop, itemStyle: {normal: {color: CHARTCONFIG.color.success}}},
{name: 'other', value: 75, itemStyle: labelBottom}
]
}]
};
pie4.options = {
series: [{
type: 'pie',
radius,
itemStyle: labelFromatter,
data: [
{name: 'Referral', value: 75, label: labelTop, itemStyle: {normal: {color: CHARTCONFIG.color.info}}},
{name: 'other', value: 25, itemStyle: labelBottom}
]
}]
};
const Stats = () => (
<div className="row">
<div className="col-xl-3 col-lg-6">
<ReactEcharts style={{height: '200px'}} option={pie1.options} showLoading={false} />
</div>
<div className="col-xl-3 col-lg-6">
<ReactEcharts style={{height: '200px'}} option={pie2.options} showLoading={false} />
</div>
<div className="col-xl-3 col-lg-6">
<ReactEcharts style={{height: '200px'}} option={pie3.options} showLoading={false} />
</div>
<div className="col-xl-3 col-lg-6">
<ReactEcharts style={{height: '200px'}} option={pie4.options} showLoading={false} />
</div>
</div>
);
module.exports = Stats;

View File

@@ -0,0 +1,108 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const area = {};
area.options = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['Rides', 'ER Visits'],
textStyle: {
color: CHARTCONFIG.color.text
}
},
toolbox: {
show: false
},
calculable: true,
xAxis: [
{
type: 'category',
data: ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.'],
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
}
}
],
yAxis: [
{
max: 100,
axisLabel: {
textStyle: {
color: CHARTCONFIG.color.text
}
},
splitLine: {
lineStyle: {
color: CHARTCONFIG.color.splitLine
}
},
splitArea: {
show: true,
areaStyle: {
color: CHARTCONFIG.color.splitArea
}
}
}
],
series: [
{
name: 'Rides',
type: 'bar',
data: [17, 11, 22, 35, 76, 40, 28, 25],
itemStyle: {
normal: {
color: CHARTCONFIG.color.info
}
},
lineStyle: {
normal: {
color: CHARTCONFIG.color.info
}
},
areaStyle: {
normal: {
color: CHARTCONFIG.color.info
}
},
symbol: 'diamond'
},
{
name: 'ER Visits',
type: 'bar',
barCategoryGap: '35%',
data: [15, 13, 20, 40, 81, 37, 26, 26],
itemStyle: {
normal: {
color: CHARTCONFIG.color.success
}
},
lineStyle: {
normal: {
color: CHARTCONFIG.color.success
}
},
areaStyle: {
normal: {
color: CHARTCONFIG.color.success
}
},
symbol: 'diamond'
}
]
};
const Chart = () => (
<ReactEcharts style={{height: '400px'}} option={area.options} showLoading={false} />
);
module.exports = Chart;

View File

@@ -0,0 +1,62 @@
import React from 'react';
import ReactEcharts from 'components/ReactECharts';
import CHARTCONFIG from 'constants/ChartConfig';
const Statboxes = () => (
<div className="row">
<div className="col-xl-3 col-sm-6">
<div className="box box-default">
<div className="box-top">
<span>35<span className="size-h5">%</span></span>
</div>
<div className="box-info">
<span>Growth</span>
</div>
<div className="box-bottom">
<i className="material-icons color-success">airplanemode_active</i>
</div>
</div>
</div>
<div className="col-xl-3 col-sm-6">
<div className="box box-default">
<div className="box-top">
<span>42<span className="size-h5">%</span></span>
</div>
<div className="box-info">
<span>New Users</span>
</div>
<div className="box-bottom">
<i className="material-icons color-info">supervisor_account</i>
</div>
</div>
</div>
<div className="col-xl-3 col-sm-6">
<div className="box box-default">
<div className="box-top">
<span>37<span className="size-h5">k</span></span>
</div>
<div className="box-info">
<span>Savings</span>
</div>
<div className="box-bottom">
<i className="material-icons color-warning">attach_money</i>
</div>
</div>
</div>
<div className="col-xl-3 col-sm-6">
<div className="box box-default">
<div className="box-top">
<span>25<span className="size-h5">k</span></span>
</div>
<div className="box-info">
<span>Miles</span>
</div>
<div className="box-bottom">
<i className="material-icons color-danger">card_travel</i>
</div>
</div>
</div>
</div>
);
module.exports = Statboxes;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'dashboard',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Dashboard'));
});
}
};

View File

@@ -0,0 +1,12 @@
module.exports = {
path: 'form',
getChildRoutes(partialNextState, cb) {
require.ensure([], (require) => {
cb(null, [
require('./routes/components'),
require('./routes/layouts'),
require('./routes/steppers'),
]);
});
}
};

View File

@@ -0,0 +1,234 @@
import React, {Component} from 'react';
import AutoComplete from 'material-ui/AutoComplete';
import MenuItem from 'material-ui/MenuItem';
//
class AutoCompleteExampleSimple extends Component {
state = {
dataSource: [],
};
handleUpdateInput = (value) => {
this.setState({
dataSource: [
value,
value + value,
value + value + value,
],
});
};
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Simple examples</div>
<div className="box-body">
<AutoComplete
hintText="Type anything"
dataSource={this.state.dataSource}
onUpdateInput={this.handleUpdateInput}
/>
<AutoComplete
hintText="Type anything"
dataSource={this.state.dataSource}
onUpdateInput={this.handleUpdateInput}
floatingLabelText="Full width"
fullWidth
/>
</div>
</div>
</div>
);
}
}
//
const dataSource1 = [
{
text: 'text-value1',
value: (
<MenuItem
primaryText="text-value1"
secondaryText="&#9786;"
/>
),
},
{
text: 'text-value2',
value: (
<MenuItem
primaryText="text-value2"
secondaryText="&#9786;"
/>
),
},
];
const dataSource2 = ['12345', '23456', '34567'];
const dataSource3 = [
{textKey: 'Some Text', valueKey: 'someFirstValue'},
{textKey: 'Some Text', valueKey: 'someSecondValue'},
];
const dataSourceConfig = {
text: 'textKey',
value: 'valueKey',
};
const AutoCompleteExampleDataSource = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Data sources</div>
<div className="box-body">
<AutoComplete
hintText="text-value data"
filter={AutoComplete.noFilter}
dataSource={dataSource1}
/><br />
<AutoComplete
floatingLabelText="showAllItems"
filter={AutoComplete.noFilter}
openOnFocus
dataSource={dataSource2}
/><br />
<AutoComplete
floatingLabelText="Same text, different values"
filter={AutoComplete.noFilter}
openOnFocus
dataSource={dataSource3}
dataSourceConfig={dataSourceConfig}
/>
</div>
</div>
</div>
);
//
const colors = [
'Red',
'Orange',
'Yellow',
'Green',
'Blue',
'Purple',
'Black',
'White',
];
const fruit = [
'Apple', 'Apricot', 'Avocado',
'Banana', 'Bilberry', 'Blackberry', 'Blackcurrant', 'Blueberry',
'Boysenberry', 'Blood Orange',
'Cantaloupe', 'Currant', 'Cherry', 'Cherimoya', 'Cloudberry',
'Coconut', 'Cranberry', 'Clementine',
'Damson', 'Date', 'Dragonfruit', 'Durian',
'Elderberry',
'Feijoa', 'Fig',
'Goji berry', 'Gooseberry', 'Grape', 'Grapefruit', 'Guava',
'Honeydew', 'Huckleberry',
'Jabouticaba', 'Jackfruit', 'Jambul', 'Jujube', 'Juniper berry',
'Kiwi fruit', 'Kumquat',
'Lemon', 'Lime', 'Loquat', 'Lychee',
'Nectarine',
'Mango', 'Marion berry', 'Melon', 'Miracle fruit', 'Mulberry', 'Mandarine',
'Olive', 'Orange',
'Papaya', 'Passionfruit', 'Peach', 'Pear', 'Persimmon', 'Physalis', 'Plum', 'Pineapple',
'Pumpkin', 'Pomegranate', 'Pomelo', 'Purple Mangosteen',
'Quince',
'Raspberry', 'Raisin', 'Rambutan', 'Redcurrant',
'Salal berry', 'Satsuma', 'Star fruit', 'Strawberry', 'Squash', 'Salmonberry',
'Tamarillo', 'Tamarind', 'Tomato', 'Tangerine',
'Ugli fruit',
'Watermelon',
];
const AutoCompleteExampleFilters = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Filters</div>
<div className="box-body">
<AutoComplete
floatingLabelText="Type 'r', case insensitive"
filter={AutoComplete.caseInsensitiveFilter}
dataSource={colors}
/>
<br />
<AutoComplete
floatingLabelText="Type 'peah', fuzzy search"
filter={AutoComplete.fuzzyFilter}
dataSource={fruit}
maxSearchResults={5}
/>
</div>
</div>
</div>
);
class AutoCompleteExampleControlled extends Component {
state = {
searchText: '',
};
handleUpdateInput = (searchText) => {
this.setState({
searchText,
});
};
handleNewRequest = () => {
this.setState({
searchText: '',
});
};
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Controlled examples</div>
<div className="box-body">
<AutoComplete
hintText="Type 'r', case insensitive"
searchText={this.state.searchText}
onUpdateInput={this.handleUpdateInput}
onNewRequest={this.handleNewRequest}
dataSource={colors}
filter={(searchText, key) => (key.indexOf(searchText) !== -1)}
openOnFocus
/>
</div>
</div>
</div>
);
}
}
const AutoCompleteSection = () => (
<article className="article">
<h2 className="article-title">Material Auto Complete</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<AutoCompleteExampleSimple />
<AutoCompleteExampleDataSource />
</div>
<div className="divider divider-lg divider-dashed" />
<div className="row">
<AutoCompleteExampleFilters />
<AutoCompleteExampleControlled />
</div>
</div>
</div>
</section>
</article>
);
module.exports = AutoCompleteSection;

View File

@@ -0,0 +1,99 @@
import React from 'react';
import Checkbox from 'material-ui/Checkbox';
import ActionFavorite from 'material-ui/svg-icons/action/favorite';
import ActionFavoriteBorder from 'material-ui/svg-icons/action/favorite-border';
import Visibility from 'material-ui/svg-icons/action/visibility';
import VisibilityOff from 'material-ui/svg-icons/action/visibility-off';
const styles = {
checkbox: {
maxWidth: 250,
marginBottom: 16
}
};
const CheckboxExampleSimple = () => (
<div className="row" >
<div className="col-lg-6">
<Checkbox
label="Simple"
style={styles.checkbox}
/>
<Checkbox
checkedIcon={<ActionFavorite />}
uncheckedIcon={<ActionFavoriteBorder />}
label="Custom icon"
style={styles.checkbox}
/>
<Checkbox
checkedIcon={<Visibility />}
uncheckedIcon={<VisibilityOff />}
label="Custom icon of different shapes"
style={styles.checkbox}
/>
<Checkbox
label="Disabled unchecked"
disabled
style={styles.checkbox}
/>
<Checkbox
label="Disabled checked"
checked
disabled
style={styles.checkbox}
/>
</div>
<div className="col-lg-6">
<Checkbox
label="Label on the left"
labelPosition="left"
style={styles.checkbox}
/>
<Checkbox
checkedIcon={<ActionFavorite />}
uncheckedIcon={<ActionFavoriteBorder />}
label="Custom icon"
labelPosition="left"
style={styles.checkbox}
/>
<Checkbox
checkedIcon={<Visibility />}
uncheckedIcon={<VisibilityOff />}
label="Custom icon of different shapes"
labelPosition="left"
style={styles.checkbox}
/>
<Checkbox
label="Disabled unchecked"
disabled
labelPosition="left"
style={styles.checkbox}
/>
<Checkbox
label="Disabled checked"
checked
disabled
labelPosition="left"
style={styles.checkbox}
/>
</div>
</div>
);
const CheckboxSection = () => (
<article className="article">
<h2 className="article-title">Material Checkbox</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<CheckboxExampleSimple />
</div>
</div>
</section>
</article>
);
module.exports = CheckboxSection;

View File

@@ -0,0 +1,127 @@
import React from 'react';
import Avatar from 'material-ui/Avatar';
import Chip from 'material-ui/Chip';
import FontIcon from 'material-ui/FontIcon';
import SvgIconFace from 'material-ui/svg-icons/action/face';
import {blue300, indigo900} from 'material-ui/styles/colors';
const styles = {
chip: {
margin: 4,
},
wrapper: {
display: 'flex',
flexWrap: 'wrap',
},
};
function handleRequestDelete() {
console.log('You clicked the delete button.');
}
function handleTouchTap() {
console.log('You clicked the Chip.');
}
/**
* Examples of Chips, using an image [Avatar](/#/components/font-icon), [Font Icon](/#/components/font-icon) Avatar,
* [SVG Icon](/#/components/svg-icon) Avatar, "Letter" (string) Avatar, and with custom colors.
*
* Chips with the `onRequestDelete` property defined will display a delete icon.
*/
export default class ChipExampleSimple extends React.Component {
render() {
return (
<div>
<div style={styles.wrapper}>
<Chip
style={styles.chip}
>
Text Chip
</Chip>
<Chip
onRequestDelete={handleRequestDelete}
onTouchTap={handleTouchTap}
style={styles.chip}
>
Deletable Text Chip
</Chip>
<Chip
onTouchTap={handleTouchTap}
style={styles.chip}
>
<Avatar src="assets/images-demo/avatars/1.jpg" />
Image Avatar Chip
</Chip>
<Chip
onRequestDelete={handleRequestDelete}
onTouchTap={handleTouchTap}
style={styles.chip}
>
<Avatar src="assets/images-demo/avatars/2.jpg" />
Deletable Avatar Chip
</Chip>
</div>
<div className="divider divider-sm" />
<div style={styles.wrapper}>
<Chip
onTouchTap={handleTouchTap}
style={styles.chip}
>
<Avatar icon={<FontIcon className="material-icons">perm_identity</FontIcon>} />
FontIcon Avatar Chip
</Chip>
<Chip
onRequestDelete={handleRequestDelete}
onTouchTap={handleTouchTap}
style={styles.chip}
>
<Avatar color="#444" icon={<SvgIconFace />} />
SvgIcon Avatar Chip
</Chip>
<Chip onTouchTap={handleTouchTap} style={styles.chip}>
<Avatar size={32}>A</Avatar>
Text Avatar Chip
</Chip>
<Chip
backgroundColor={blue300}
onRequestDelete={handleRequestDelete}
onTouchTap={handleTouchTap}
style={styles.chip}
>
<Avatar size={32} color={blue300} backgroundColor={indigo900}>
MB
</Avatar>
Colored Chip
</Chip>
</div>
<div className="callout callout-warning no-margin-bottom">
<p>Chips with the onRequestDelete property defined will display a delete icon.</p>
</div>
</div>
);
}
}
const ChipSection = () => (
<article className="article">
<h2 className="article-title">Material Chips</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<ChipExampleSimple />
</div>
</section>
</article>
);
module.exports = ChipSection;

View File

@@ -0,0 +1,35 @@
import React from 'react';
import QueueAnim from 'rc-queue-anim';
import AutoComplete from './AutoComplete';
import Checkbox from './Checkbox';
import Chip from './Chip';
import DatePicker from './DatePicker';
import Dialog from './Dialog';
import RadioButton from './RadioButton';
import SelectField from './SelectField';
import Slider from './Slider';
import TextField from './TextField';
import TimePicker from './TimePicker';
import Toggle from './Toggle';
const Elements = () => (
<div className="container-fluid with-maxwidth chapter">
<QueueAnim type="bottom" className="ui-animate">
<div key="1"><RadioButton /></div>
<div key="2"><Checkbox /></div>
<div key="3"><Toggle /></div>
<div key="4"><TextField /></div>
<div key="5"><SelectField /></div>
<div key="6"><AutoComplete /></div>
<div key="7"><Slider /></div>
<div key="8"><TimePicker /></div>
<div key="9"><DatePicker /></div>
<div key="10"><Dialog /></div>
<div key="11"><Chip /></div>
</QueueAnim>
</div>
);
module.exports = Elements;

View File

@@ -0,0 +1,151 @@
import React from 'react';
import DatePicker from 'material-ui/DatePicker';
import TextField from 'material-ui/TextField';
import Toggle from 'material-ui/Toggle';
//
const DatePickerExampleSimple = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Simple examples</div>
<div className="box-body">
<DatePicker hintText="Portrait Dialog" />
<DatePicker hintText="Landscape Dialog" mode="landscape" />
<DatePicker hintText="Dialog Disabled" disabled />
</div>
</div>
</div>
);
//
const DatePickerExampleInline = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Inline examples</div>
<div className="box-body">
<DatePicker hintText="Portrait Inline Dialog" container="inline" />
<DatePicker hintText="Landscape Inline Dialog" container="inline" mode="landscape" />
</div>
</div>
</div>
);
//
const optionsStyle = {
maxWidth: 300
};
class DatePickerExampleToggle extends React.Component {
constructor(props) {
super(props);
const minDate = new Date();
const maxDate = new Date();
minDate.setFullYear(minDate.getFullYear() - 1);
minDate.setHours(0, 0, 0, 0);
maxDate.setFullYear(maxDate.getFullYear() + 1);
maxDate.setHours(0, 0, 0, 0);
this.state = {
minDate,
maxDate,
autoOk: false,
disableYearSelection: false,
};
}
handleChangeMinDate = (event, date) => {
this.setState({
minDate: date,
});
};
handleChangeMaxDate = (event, date) => {
this.setState({
maxDate: date,
});
};
handleToggle = (event, toggled) => {
this.setState({
[event.target.name]: toggled,
});
};
render() {
return (
<div className="box box-transparent">
<div className="box-header">Ranged example</div>
<div className="box-body">
<div className="row">
<div className="col-lg-6">
<DatePicker
floatingLabelText="Ranged Date Picker"
autoOk={this.state.autoOk}
minDate={this.state.minDate}
maxDate={this.state.maxDate}
disableYearSelection={this.state.disableYearSelection}
/>
</div>
<div className="col-lg-6">
<div style={optionsStyle}>
<DatePicker
onChange={this.handleChangeMinDate}
autoOk={this.state.autoOk}
floatingLabelText="Min Date"
defaultDate={this.state.minDate}
disableYearSelection={this.state.disableYearSelection}
/>
<DatePicker
onChange={this.handleChangeMaxDate}
autoOk={this.state.autoOk}
floatingLabelText="Max Date"
defaultDate={this.state.maxDate}
disableYearSelection={this.state.disableYearSelection}
/>
<div className="divider" />
<Toggle
name="autoOk"
value="autoOk"
label="Auto Ok"
toggled={this.state.autoOk}
onToggle={this.handleToggle}
/>
<div className="divider" />
<Toggle
name="disableYearSelection"
value="disableYearSelection"
label="Disable Year Selection"
toggled={this.state.disableYearSelection}
onToggle={this.handleToggle}
/>
</div>
</div>
</div>
</div>
</div>
);
}
}
const DatePickerSection = () => (
<article className="article">
<h2 className="article-title">Material Date Picker</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<DatePickerExampleSimple />
<DatePickerExampleInline />
</div>
<div className="divider divider-xl divider-dashed" />
<DatePickerExampleToggle />
</div>
</div>
</section>
</article>
);
module.exports = DatePickerSection;

View File

@@ -0,0 +1,369 @@
import React from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import RaisedButton from 'material-ui/RaisedButton';
import {RadioButton, RadioButtonGroup} from 'material-ui/RadioButton';
import DatePicker from 'material-ui/DatePicker';
//
class DialogExampleSimple extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
keyboardFocused
onTouchTap={this.handleClose}
/>,
];
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Simple dialog</div>
<div className="box-body">
<RaisedButton label="Dialog" onTouchTap={this.handleOpen} />
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
The actions in this window were passed in as an array of React objects.
</Dialog>
</div>
</div>
</div>
);
}
}
//
class DialogExampleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
disabled
onTouchTap={this.handleClose}
/>,
];
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Modal dialog</div>
<div className="box-body">
<RaisedButton label="Modal Dialog" onTouchTap={this.handleOpen} />
<Dialog
title="Dialog With Actions"
actions={actions}
modal
open={this.state.open}
>
Only actions can close this dialog.
</Dialog>
</div>
</div>
</div>
);
}
}
//
const customContentStyle = {
width: '100%',
maxWidth: 'none',
};
class DialogExampleCustomWidth extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
onTouchTap={this.handleClose}
/>,
];
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Styled dialog</div>
<div className="box-body">
<RaisedButton label="Dialog With Custom Width" onTouchTap={this.handleOpen} />
<Dialog
title="Dialog With Custom Width"
actions={actions}
modal
contentStyle={customContentStyle}
open={this.state.open}
>
This dialog spans the entire width of the screen.
</Dialog>
</div>
</div>
</div>
);
}
}
//
class DialogExampleDialogDatePicker extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Ok"
primary
keyboardFocused
onTouchTap={this.handleClose}
/>,
];
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Nested dialogs</div>
<div className="box-body">
<RaisedButton label="Dialog With Date Picker" onTouchTap={this.handleOpen} />
<Dialog
title="Dialog With Date Picker"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
Open a Date Picker dialog from within a dialog.
<DatePicker hintText="Date Picker" />
</Dialog>
</div>
</div>
</div>
);
}
}
//
const styles = {
radioButton: {
marginTop: 16,
},
};
class DialogExampleScrollable extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
keyboardFocused
onTouchTap={this.handleClose}
/>,
];
const radios = [];
for (let i = 0; i < 30; i++) {
radios.push(
<RadioButton
key={i}
value={`value${i + 1}`}
label={`Option ${i + 1}`}
style={styles.radioButton}
/>
);
}
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Scrollable dialog</div>
<div className="box-body">
<RaisedButton label="Scrollable Dialog" onTouchTap={this.handleOpen} />
<Dialog
title="Scrollable Dialog"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
autoScrollBodyContent
>
<RadioButtonGroup name="shipSpeed" defaultSelected="not_light">
{radios}
</RadioButtonGroup>
</Dialog>
</div>
</div>
</div>
);
}
}
//
class DialogExampleAlert extends React.Component {
state = {
open: false,
};
handleOpen = () => {
this.setState({open: true});
};
handleClose = () => {
this.setState({open: false});
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Discard"
primary
onTouchTap={this.handleClose}
/>,
];
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Alert dialog</div>
<div className="box-body">
<RaisedButton label="Alert" onTouchTap={this.handleOpen} />
<Dialog
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
Discard draft?
</Dialog>
</div>
</div>
</div>
);
}
}
const DialogSection = () => (
<article className="article">
<h2 className="article-title">Material Dialog</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<DialogExampleSimple />
<DialogExampleModal />
</div>
<div className="divider divider-lg divider-dashed" />
<div className="row">
<DialogExampleCustomWidth />
<DialogExampleDialogDatePicker />
</div>
<div className="divider divider-lg divider-dashed" />
<div className="row">
<DialogExampleScrollable />
<DialogExampleAlert />
</div>
</div>
</div>
</section>
</article>
);
module.exports = DialogSection;

View File

@@ -0,0 +1,104 @@
import React from 'react';
import {RadioButton, RadioButtonGroup} from 'material-ui/RadioButton';
import ActionFavorite from 'material-ui/svg-icons/action/favorite';
import ActionFavoriteBorder from 'material-ui/svg-icons/action/favorite-border';
const styles = {
block: {
maxWidth: 250,
},
radioButton: {
marginBottom: 16,
},
};
const RadioButtonExampleSimple = () => (
<div className="row">
<div className="col-lg-6">
<RadioButtonGroup name="shipSpeed" defaultSelected="not_light">
<RadioButton
value="light"
label="Simple"
style={styles.radioButton}
/>
<RadioButton
value="not_light"
label="Selected by default"
style={styles.radioButton}
/>
<RadioButton
value="ludicrous"
label="Custom icon"
checkedIcon={<ActionFavorite />}
uncheckedIcon={<ActionFavoriteBorder />}
style={styles.radioButton}
/>
</RadioButtonGroup>
<RadioButtonGroup name="shipName" defaultSelected="community">
<RadioButton
value="enterprise"
label="Disabled unchecked"
disabled
style={styles.radioButton}
/>
<RadioButton
value="community"
label="Disabled checked"
disabled
style={styles.radioButton}
/>
</RadioButtonGroup>
</div>
<div className="col-lg-6">
<RadioButtonGroup name="notRight" labelPosition="left" defaultSelected="not_light" style={styles.block}>
<RadioButton
value="reverse"
label="Label on the left"
style={styles.radioButton}
/>
<RadioButton
value="not_light"
label="Selected by default"
style={styles.radioButton}
/>
<RadioButton
value="ludicrous"
label="Custom icon"
checkedIcon={<ActionFavorite />}
uncheckedIcon={<ActionFavoriteBorder />}
style={styles.radioButton}
/>
</RadioButtonGroup>
<RadioButtonGroup name="shipName2" labelPosition="left" defaultSelected="community" style={styles.block}>
<RadioButton
value="enterprise"
label="Disabled unchecked"
disabled
style={styles.radioButton}
/>
<RadioButton
value="community"
label="Disabled checked"
disabled
style={styles.radioButton}
/>
</RadioButtonGroup>
</div>
</div>
);
const RadioButtonSection = () => (
<article className="article">
<h2 className="article-title">Material Radio Button</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<RadioButtonExampleSimple />
</div>
</div>
</section>
</article>
);
module.exports = RadioButtonSection;

View File

@@ -0,0 +1,155 @@
import React from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
class SelectFieldExampleSimple extends React.Component {
state = {
value: 1,
};
handleChange = (event, index, value) => this.setState({value});
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Simple examples</div>
<div className="box-body">
<SelectField
floatingLabelText="Frequency"
value={this.state.value}
onChange={this.handleChange}
>
<MenuItem value={1} primaryText="Never" />
<MenuItem value={2} primaryText="Every Night" />
<MenuItem value={3} primaryText="Weeknights" />
<MenuItem value={4} primaryText="Weekends" />
<MenuItem value={5} primaryText="Weekly" />
</SelectField>
<br />
<SelectField floatingLabelText="Frequency" value={1} disabled>
<MenuItem value={1} primaryText="Disabled" />
<MenuItem value={2} primaryText="Every Night" />
</SelectField>
</div>
</div>
</div>
);
}
}
class SelectFieldExampleNullable extends React.Component {
state = {
value: null,
};
handleChange = (event, index, value) => this.setState({value});
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Nullable select</div>
<div className="box-body">
<SelectField
floatingLabelText="Ready?"
value={this.state.value}
onChange={this.handleChange}
>
<MenuItem value={null} primaryText="" />
<MenuItem value={false} primaryText="No" />
<MenuItem value primaryText="Yes" />
</SelectField>
</div>
</div>
</div>
);
}
}
//
const longItems = [];
for (let i = 0; i < 100; i++) {
longItems.push(<MenuItem value={i} key={i} primaryText={`Item ${i}`} />);
}
class DropDownMenuLongMenuExample extends React.Component {
constructor(props) {
super(props);
this.state = {value: 10};
}
handleChange = (event, index, value) => this.setState({value});
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Long examples</div>
<div className="box-body">
<SelectField
onChange={this.handleChange}
value={this.state.value}
maxHeight={200}
>
{longItems}
</SelectField>
</div>
</div>
</div>
);
}
}
//
class SelectFieldExampleCustomLabel extends React.Component {
state = {
value: 1,
};
handleChange = (event, index, value) => this.setState({value});
render() {
return (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Label examples</div>
<div className="box-body">
<SelectField value={this.state.value} onChange={this.handleChange}>
<MenuItem value={1} label="5 am - 12 pm" primaryText="Morning" />
<MenuItem value={2} label="12 pm - 5 pm" primaryText="Afternoon" />
<MenuItem value={3} label="5 pm - 9 pm" primaryText="Evening" />
<MenuItem value={4} label="9 pm - 5 am" primaryText="Night" />
</SelectField>
</div>
</div>
</div>
);
}
}
const SelectFieldSection = () => (
<article className="article">
<h2 className="article-title">Material Select Field</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<SelectFieldExampleSimple />
<SelectFieldExampleNullable />
</div>
<div className="row">
<DropDownMenuLongMenuExample />
<SelectFieldExampleCustomLabel />
</div>
</div>
</div>
</section>
</article>
);
module.exports = SelectFieldSection;

View File

@@ -0,0 +1,120 @@
import React from 'react';
import Slider from 'material-ui/Slider';
//
const SliderExampleSimple = () => (
<div className="box box-default">
<div className="box-header">Simple examples</div>
<div className="box-body">
<Slider />
<Slider defaultValue={0.5} />
<Slider defaultValue={1} />
</div>
</div>
);
//
const SliderExampleDisabled = () => (
<div className="box box-default">
<div className="box-header">Disabled examples</div>
<div className="box-body">
<Slider disabled />
<Slider disabled value={0.5} />
<Slider disabled value={1} />
</div>
</div>
);
//
const SliderExampleStep = () => (
<div className="box box-default">
<div className="box-header">Stepped examples</div>
<div className="box-body">
<Slider step={0.10} value={1} />
<Slider step={0.20} value={1} />
</div>
</div>
);
class SliderExampleControlled extends React.Component {
state = {
secondSlider: 50,
};
handleSecondSlider = (event, value) => {
this.setState({secondSlider: value});
};
render() {
return (
<div className="box box-default">
<div className="box-header">Controlled examples</div>
<div className="box-body">
<Slider
min={0}
max={100}
step={1}
defaultValue={50}
value={this.state.secondSlider}
onChange={this.handleSecondSlider}
/>
<div className="callout callout-info no-margin-bottom">
<p>
<span>{'The value of this slider is: '}</span>
<span>{this.state.secondSlider}</span>
<span>{' from a range of 0 to 100 inclusive'}</span>
</p>
</div>
</div>
</div>
);
}
}
const styles = {
root: {
display: 'flex',
height: 124,
flexDirection: 'row',
justifyContent: 'space-around',
},
};
const SliderExampleAxis = () => (
<div className="box box-default">
<div className="box-header">Alternative Axis Examples</div>
<div className="box-body">
<div style={styles.root}>
<Slider style={{height: 100}} axis="y" defaultValue={0.5} />
<Slider style={{width: 200}} axis="x-reverse" />
<Slider style={{height: 100}} axis="y-reverse" defaultValue={1} />
</div>
</div>
</div>
);
const SliderSection = () => (
<article className="article">
<h2 className="article-title">Material Slider</h2>
<div className="row">
<div className="col-xl-6">
<SliderExampleSimple />
</div>
<div className="col-xl-6">
<SliderExampleDisabled />
</div>
</div>
<div className="row">
<div className="col-xl-6">
<SliderExampleStep />
</div>
<div className="col-xl-6">
<SliderExampleControlled />
</div>
</div>
<SliderExampleAxis />
</article>
);
module.exports = SliderSection;

View File

@@ -0,0 +1,117 @@
import React from 'react';
import TextField from 'material-ui/TextField';
const style = {
width: '100%'
};
//
const TextFieldExampleSimple = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Simple examples</div>
<div className="box-body">
<TextField
hintText="Hint Text"
/><br />
<br />
<TextField
hintText="The hint text can be as long as you want, it will wrap."
/><br />
<TextField
id="text-field-default"
defaultValue="Default Value"
/><br />
<TextField
hintText="Hint Text"
floatingLabelText="Floating Label Text"
/><br />
<TextField
defaultValue="Default Value"
floatingLabelText="Floating Label Text"
/><br />
<TextField
hintText="Hint Text"
floatingLabelText="Fixed Floating Label Text"
floatingLabelFixed
/><br />
<TextField
hintText="Password Field"
floatingLabelText="Password"
type="password"
/><br />
<TextField
hintText="MultiLine with rows: 2 and rowsMax: 4"
multiLine
rows={2}
rowsMax={4}
/><br />
<TextField
hintText="Message Field"
floatingLabelText="MultiLine and FloatingLabel"
multiLine
rows={2}
/><br />
<TextField
hintText="Full width"
fullWidth
/>
</div>
</div>
</div>
);
//
const TextFieldExampleDisabled = () => (
<div className="col-lg-6">
<div className="box box-transparent">
<div className="box-header">Disabled examples</div>
<div className="box-body">
<TextField
disabled
hintText="Disabled Hint Text"
/><br />
<br />
<TextField
disabled
id="text-field-disabled"
defaultValue="Disabled Value"
/><br />
<TextField
disabled
hintText="Disabled Hint Text"
floatingLabelText="Floating Label Text"
/><br />
<TextField
disabled
hintText="Disabled Hint Text"
defaultValue="Disabled With Floating Label"
floatingLabelText="Floating Label Text"
/>
</div>
</div>
</div>
);
const TextFieldSection = () => (
<article className="article">
<h2 className="article-title">Material Text Field</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<TextFieldExampleSimple />
<TextFieldExampleDisabled />
</div>
</div>
</div>
</section>
</article>
);
module.exports = TextFieldSection;

View File

@@ -0,0 +1,89 @@
import React from 'react';
import TimePicker from 'material-ui/TimePicker';
const SimpleExamples = () => (
<div className="box box-transparent">
<div className="box-header">Simple examples</div>
<div className="box-body">
<TimePicker
hintText="12hr Format"
/>
<TimePicker
hintText="12hr Format with auto ok"
autoOk
/>
<TimePicker
format="24hr"
hintText="24hr Format"
/>
<TimePicker
disabled
format="24hr"
hintText="Disabled TimePicker"
/>
</div>
</div>
);
class ControlledExamples extends React.Component {
constructor(props) {
super(props);
this.state = {value24: null, value12: null};
}
handleChangeTimePicker24 = (event, date) => {
this.setState({value24: date});
};
handleChangeTimePicker12 = (event, date) => {
this.setState({value12: date});
};
render() {
return (
<div className="box box-transparent">
<div className="box-header">Controlled examples</div>
<div className="box-body">
<TimePicker
format="ampm"
hintText="12hr Format"
value={this.state.value12}
onChange={this.handleChangeTimePicker12}
/>
<TimePicker
format="24hr"
hintText="24hr Format"
value={this.state.value24}
onChange={this.handleChangeTimePicker24}
/>
</div>
</div>
);
}
}
const TimePickerSection = () => (
<article className="article">
<h2 className="article-title">Material Time Picker</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<div className="row">
<div className="col-lg-6">
<SimpleExamples />
</div>
<div className="col-md-6">
<ControlledExamples />
</div>
</div>
</div>
</div>
</section>
</article>
);
module.exports = TimePickerSection;

View File

@@ -0,0 +1,80 @@
import React from 'react';
import Toggle from 'material-ui/Toggle';
const styles = {
toggle: {
maxWidth: 250,
marginBottom: 16
},
};
const ToggleExampleSimple = () => (
<div className="row">
<div className="col-md-6">
<Toggle
label="Simple"
style={styles.toggle}
/>
<Toggle
label="Toggled by default"
defaultToggled
style={styles.toggle}
/>
<Toggle
label="Disabled"
disabled
style={styles.toggle}
/>
<Toggle
label="Disabled"
disabled
defaultToggled
style={styles.toggle}
/>
</div>
<div className="col-md-6">
<Toggle
label="Label on the right"
labelPosition="right"
style={styles.toggle}
/>
<Toggle
label="Toggled by default"
labelPosition="right"
defaultToggled
style={styles.toggle}
/>
<Toggle
label="Disabled"
labelPosition="right"
disabled
style={styles.toggle}
/>
<Toggle
label="Disabled"
labelPosition="right"
disabled
defaultToggled
style={styles.toggle}
/>
</div>
</div>
);
const ToggleSection = () => (
<article className="article">
<h2 className="article-title">Material Toggle</h2>
<section className="box box-default">
<div className="box-body padding-xl">
<div className="col-xl-10">
<ToggleExampleSimple />
</div>
</div>
</section>
</article>
);
module.exports = ToggleSection;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'components',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Components'));
});
}
};

View File

@@ -0,0 +1,250 @@
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import QueueAnim from 'rc-queue-anim';
const BasicForm = () => (
<article className="article">
<h2 className="article-title">Basic Form</h2>
<div className="box box-default">
<div className="box-body padding-xl">
<form role="form">
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="exampleInputEmail1" placeholder="Enter email" />
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input type="password" className="form-control" id="exampleInputPassword1" placeholder="Password" />
</div>
<div className="checkbox">
<label>
<input type="checkbox" /> Check me out
</label>
</div>
<RaisedButton label="Submit" primary className="btn-w-md" />
<div className="divider" />
</form>
</div>
</div>
</article>
);
const HorizontalForm = () => (
<article className="article">
<h2 className="article-title">Horizontal Form</h2>
<div className="box box-default">
<div className="box-body padding-xl">
<form role="form">
<div className="form-group row">
<label htmlFor="inputEmail3" className="col-md-2 control-label">Email</label>
<div className="col-md-10">
<input type="email" className="form-control" id="inputEmail3" placeholder="Email" />
</div>
</div>
<div className="form-group row">
<label htmlFor="inputPassword3" className="col-md-2 control-label">Password</label>
<div className="col-md-10">
<input type="password" className="form-control" id="inputPassword3" placeholder="Password" />
</div>
</div>
<div className="form-group row">
<div className="offset-md-2 col-md-10">
<div className="form-checkbox">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" /> Remember me
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="offset-md-2 col-md-10">
<RaisedButton label="Login" className="btn-w-md" />
</div>
</div>
</form>
</div>
</div>
</article>
);
const InlineForm = () => (
<article className="article">
<h2 className="article-title">Inline Form</h2>
<div className="box box-default">
<div className="box-body padding-xl">
<form className="form-inline" role="form">
<label className="sr-only" htmlFor="inlineFormInput">Name</label>
<input type="text" className="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput" placeholder="Jane Doe" />
<label className="sr-only" htmlFor="inlineFormInputGroup">Username</label>
<div className="input-group mb-2 mr-sm-2 mb-sm-0">
<div className="input-group-addon">@</div>
<input type="text" className="form-control" id="inlineFormInputGroup" placeholder="Username" />
</div>
<div className="form-check mb-2 mr-sm-2 mb-sm-0">
<label className="form-check-label">
<input className="form-check-input" type="checkbox" /> Remember me
</label>
</div>
<RaisedButton label="Login" secondary className="btn-w-md" />
</form>
</div>
</div>
</article>
);
const ColumnSizing = () => (
<article className="article">
<h2 className="article-title">ColumnSizing</h2>
<div className="box box-default">
<div className="box-body">
<div className="form-group">
<div className="row">
<div className="col-md-1">
<input type="text" className="form-control" placeholder="col-md-1" />
</div>
<div className="col-md-11">
<input type="text" className="form-control" placeholder="col-md-11" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-2">
<input type="text" className="form-control" placeholder="col-md-2" />
</div>
<div className="col-md-10">
<input type="text" className="form-control" placeholder="col-md-10" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-3">
<input type="text" className="form-control" placeholder="col-md-3" />
</div>
<div className="col-md-9">
<input type="text" className="form-control" placeholder="col-md-9" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-4">
<input type="text" className="form-control" placeholder="col-md-4" />
</div>
<div className="col-md-8">
<input type="text" className="form-control" placeholder="col-md-8" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-5">
<input type="text" className="form-control" placeholder="col-md-5" />
</div>
<div className="col-md-7">
<input type="text" className="form-control" placeholder="col-md-7" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-6">
<input type="text" className="form-control" placeholder="col-md-6" />
</div>
<div className="col-md-6">
<input type="text" className="form-control" placeholder="col-md-6" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-7">
<input type="text" className="form-control" placeholder="col-md-7" />
</div>
<div className="col-md-5">
<input type="text" className="form-control" placeholder="col-md-5" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-8">
<input type="text" className="form-control" placeholder="col-md-8" />
</div>
<div className="col-md-4">
<input type="text" className="form-control" placeholder="col-md-4" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-9">
<input type="text" className="form-control" placeholder="col-md-9" />
</div>
<div className="col-md-3">
<input type="text" className="form-control" placeholder="col-md-3" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-10">
<input type="text" className="form-control" placeholder="col-md-10" />
</div>
<div className="col-md-2">
<input type="text" className="form-control" placeholder="col-md-2" />
</div>
</div>
<div className="divider" />
<div className="row">
<div className="col-md-11">
<input type="text" className="form-control" placeholder="col-md-11" />
</div>
<div className="col-md-1">
<input type="text" className="form-control" placeholder="col-md-1" />
</div>
</div>
<div className="divider" />
</div>
</div>
</div>
</article>
);
const Page = () => (
<section className="container-fluid with-maxwidth chapter">
<QueueAnim type="bottom" className="ui-animate">
<div key="1"><BasicForm /></div>
<div key="2"><HorizontalForm /></div>
<div key="3"><InlineForm /></div>
<div key="4"><ColumnSizing /></div>
</QueueAnim>
</section>
);
module.exports = Page;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'layouts',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Layouts'));
});
}
};

View File

@@ -0,0 +1,14 @@
import React from 'react';
import QueueAnim from 'rc-queue-anim';
import VerticalNonLinear from './VerticalNonLinear';
const Stepper = (props) => {
return (
<div className="container-fluid with-maxwidth chapter">
<QueueAnim type="bottom" className="ui-animate">
<div key="1"><VerticalNonLinear params={props.params} /></div>
</QueueAnim>
</div>
);
};
module.exports = Stepper;

View File

@@ -0,0 +1,993 @@
import React, { Component } from 'react';
import {
Step,
Stepper,
StepButton,
StepContent,
} from 'material-ui/Stepper';
import RaisedButton from 'material-ui/RaisedButton';
import FlatButton from 'material-ui/FlatButton';
import QueueAnim from 'rc-queue-anim';
import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton';
import ActionFavorite from 'material-ui/svg-icons/action/favorite';
import ActionFavoriteBorder from 'material-ui/svg-icons/action/favorite-border';
import AutoComplete from 'material-ui/AutoComplete';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import { Tabs, Tab } from 'material-ui/Tabs';
// import Slider from 'material-ui/Slider';
import TimePicker from 'material-ui/TimePicker';
import DatePicker from 'material-ui/DatePicker';
import TextField from 'material-ui/TextField';
// import Toggle from 'material-ui/Toggle';
import Snackbar from 'material-ui/Snackbar';
import { NEMTLocation } from '../../../../../components/NEMTLocation';
import { request } from 'https';
import Divider from 'material-ui/Divider';
import Paper from 'material-ui/Paper';
import Dialog from 'material-ui/Dialog';
import Close from 'material-ui/svg-icons/navigation/close'
import CommunicationCall from 'material-ui/svg-icons/communication/call'
import Message from 'material-ui/svg-icons/communication/message'
import Instance from '../../../../../../../components/Connection';
import Checkbox from 'material-ui/Checkbox';
import Popover from 'material-ui/Popover';
let DateTimeFormat;
DateTimeFormat = global.Intl.DateTimeFormat;
export class DialogExampleSimple extends React.Component {
state = {
open: true,
};
handleOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const actions = [
<FlatButton
label="Cancel"
primary={true}
onClick={this.handleClose}
/>,
<FlatButton
label="Submit"
primary={true}
keyboardFocused={true}
onClick={this.handleClose}
/>,
];
return (
<div>
<Dialog
title="Dialog With Actions"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
The actions in this window were passed in as an array of React objects.
</Dialog>
</div>
);
}
}
/**
* Dialogs can be nested. This example opens a Date Picker from within a Dialog.
*/
export class DialogExampleDialogDatePicker extends React.Component {
state = {
open: false,
additionalPassenger:
{
passengerType: '',
seatType: '',
}
};
handleOpen = () => {
this.setState({ open: true });
};
handlePassengerTypeChange = (e, i, v, state) => {
this.setState({ additionalPassenger: { passengerType: v } });
};
handleSeatTypeChange = (e, i, v, state) => {
this.setState({ additionalPassenger: { seatType: v } });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const actions = [
<FlatButton
label="Add"
primary={true}
keyboardFocused={true}
onClick={this.handleClose}
/>,
<FlatButton
label="Cancel"
primary={false}
keyboardFocused={false}
onClick={this.handleClose}
/>,
];
return (
<div>
<RaisedButton style={{ fontSize: 5 }} label="+ Passenger" onClick={this.handleOpen} />
<Dialog
title="Add Passenger"
actions={actions}
modal={false}
open={this.state.open}
onRequestClose={this.handleClose}
>
<SelectField
floatingLabelText="Passenger Type"
value={this.state.additionalPassenger.passengerType}
onChange={(e, i, v) => this.handlePassengerTypeChange(e, i, v, this)}
autoWidth={true}
>
<MenuItem value={'Caregiver'} primaryText="Caregiver" />
<MenuItem value={'Companion'} primaryText="Companion" />
<MenuItem value={'Additional Patient'} primaryText="Additional Patient" />
</SelectField>
<SelectField
floatingLabelText="Seat Type"
value={this.state.additionalPassenger.seatType}
onChange={(e, i, v) => this.handleSeatTypeChange(e, i, v, this)}
autoWidth={true}
>
<MenuItem value={'Ambulatory'} primaryText="Ambulatory" />
<MenuItem value={'Stretcher'} primaryText="Stretcher" />
<MenuItem value={'Wheelchair'} primaryText="Wheelchair" />
</SelectField>
</Dialog>
</div>
);
}
}
const names = [
'Service Animal',
'Cane / Quad Cane',
'Electric Wheelchair',
'Oxygen Tank',
'Sign Language',
'White Cane',
'Leg Braces',
'Crutches',
'Manual Wheelchair',
'Prothesis',
'Walker',
];
/**
* `SelectField` can handle multiple selections. It is enabled with the `multiple` property.
*/
export class SelectFieldExampleMultiSelect extends Component {
state = {
values: [],
};
handleChange = (event, index, values) => this.setState({ values });
menuItems(values) {
return names.map((name) => (
<MenuItem
key={name}
insetChildren={true}
checked={values && values.indexOf(name) > -1}
value={name}
primaryText={name}
autoWidth={false}
style={{ width: 215 }}
/>
));
}
render() {
const { values } = this.state;
return (
<SelectField
autoWidth={false}
style={{ width: 215 }}
multiple={true}
value={values}
floatingLabelText="Mobility Aids"
label="Mobility Aids"
onChange={this.handleChange}
>
{this.menuItems(values)}
</SelectField>
);
}
}
const axios = require('axios');
const selectStyles = {
customWidth: {
width: 35,
},
};
var tripType = 'To Visit';
var pickupTimeReturnDisplayMode = "none";
/**
* `SelectField` is implemented as a controlled component,
* with the current selection set through the `value` property.
* The `SelectField` can be disabled with the `disabled` property.
*/
export class SelectFieldExampleSimple extends Component {
constructor(props) {
super(props);
this.props = props;
this.state = {
value: 'to_visit',
pickupTimeReturnDisplayMode: 'none',
pickupTimeHide: false,
};
}
componentDidMount() {
this.setState(Object.assign(this.state, { value: this.props.value }));
}
handleChange(event, index, value, state) {
let self = state
tripType = value;
switch (tripType) {
case 'from_visit':
pickupTimeReturnDisplayMode = "none"
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit', pickupTimeHide: false }));
break;
case 'from_visit_call':
pickupTimeReturnDisplayMode = "none"
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'from_visit_call', pickupTimeHide: true }));
break;
case 'to_visit':
pickupTimeReturnDisplayMode = "none"
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'to_visit', pickupTimeHide: false }));
break;
case 'roundtrip':
pickupTimeReturnDisplayMode = "block"
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false }));
break;
case 'roundtrip_call':
pickupTimeReturnDisplayMode = "none";
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'none', value: 'roundtrip_call', pickupTimeHide: false }));
break;
default:
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: 'block', value: 'roundtrip', pickupTimeHide: false }));
break;
}
if (this.props.handleChange) {
this.props.handleChange(event, index, { pickupTimeReturnDisplayMode: self.state.pickupTimeReturnDisplayMode, selectField: this.state.value, pickupTimeHide: this.state.pickupTimeHide });
}
}
render() {
return (
<div >
<SelectField
floatingLabelText="Trip Type"
value={this.state.value}
onChange={(e, i, v) => this.handleChange(e, i, v, this)}
autoWidth={false}
style={{ width: 230 }}
>
<MenuItem value={'to_visit'} primaryText="To Visit" />
<MenuItem value={'from_visit'} primaryText="From Visit" />
<MenuItem value={'from_visit_call'} primaryText="From Visit / Will Call" />
<MenuItem value={'roundtrip'} primaryText="Round Trip" />
<MenuItem value={'roundtrip_call'} primaryText="Round Trip / Will Call" />
</SelectField>
</div>
);
}
}
function disableWeekends(date) {
return date.getDay() === 0 || date.getDay() === 6;
}
const styles = {
padding: '12px 18px',
marginBottom: 12,
fontWeight: 400,
maxWidth: 250,
radioButton: {
marginTop: 6
},
checkbox: {
marginTop: 16, fontWeight: 100, fontSize: 10
},
};
// const styles = {
// block: {
// maxWidth: 250,
// },
// checkbox: {
// marginBottom: 16,fontWeight:'regular'
// },
// };
function handleActive(tab) {
console.log(`A tab with this route property ${tab.props.route} was activated.`);
}
const
dataConfig = { text: 'text', value: 'value' };
/**
* A basic vertical non-linear implementation
*/
class VerticalNonLinear extends React.Component {
constructor(props) {
super(props);
this.state = {
stepIndex: 0,
rideTypeValue: 0,
providerID: 0,
providerName: '',
visitDate: new Date(),
visitTime: new Date(),
pickupLocation: null,
pickupTime: new Date(),
pickupTimeReturn: new Date(),
pickupTimeReturnDisplayMode: 'none',
open: false,
message: 'Booking Ride',
origin: {},
destination: {},
buttonPickupText: 'Member Address',
buttodDropOffText: 'Choose Drop-Off location',
buttonProviderText: 'Choose Provider',
user: null,
showUserSelection: true,
userSelectionText: '',
users: [],
visit_external_id: "",
notes: "",
pickupTimeReturnDisplayMode: "none",
eta: {
distance_miles: 0,
duration_seconds: 0,
formatted_time: 0,
showed: false,
},
trip_type: {
key: "to_visit",
value: ""
},
return_time: new Date(),
pickupTimeHide: false,
};
}
componentDidMount() {
const loggedUser = JSON.parse(localStorage.getItem("loggedUser"));
let state = this;
let user = {
useruuid: this.props.params.uuid
}
if (user.useruuid !== loggedUser.useruuid) {
Instance.getRawConn().get(`/v1/nemt/users/member/${user.useruuid}`)
.then(function (res) {
state.setState(Object.assign(state.state, { user: res.data, showUserSelection: true, userSelectionText: `${res.data.member} - ${res.data.name}` }));
})
.catch(err => {
if (err.response.status !== 422) {
console.error(err);
}
});
}
Instance.getRawConn().get(`/v1/nemt/users/member`)
.then(function (res) {
let users = res.data.map(u => { return Object.assign(u, { userdata: `${u.member} - ${u.name}` }) });
state.setState(Object.assign(state.state, { users: users, showUserSelection: true, stepIndex: 0 }));
})
.catch(err => {
if (err.response.status !== 422) {
console.error(err);
}
});
let visitTime = new Date(new Date().getTime() + (1 * 60 * 60 * 1000));
let visitDate = visitTime;
let pickupTime = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000));
let pickupTimeReturn = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000));
this.setState(Object.assign(this.state, {
visitDate: visitDate,
visitTime: visitTime,
pickupTime: pickupTime,
pickupTimeReturn: pickupTimeReturn,
}));
}
//for snackbar
handleTouchTap() {
this.setState(Object.assign(this.state, {
open: true,
}));
};
handleRequestClose(state) {
let self = state;
self.setState(Object.assign(self.state, {
open: false,
}));
};
handleNext(state) {
let self = state;
const { stepIndex } = self.state;
if (stepIndex < 4) {
self.setState(Object.assign(self.state, { stepIndex: stepIndex + 1 }));
if (stepIndex === 3) {
self.handleTouchTap();
var requestRide = {
user_uuid: state.state.user.useruuid,
ride_type: "lyft",
origin: state.state.origin,
destination: state.state.destination,
external_note: state.state.notes,
visit_date: state.state.visitDate,
visit_time: state.state.visitTime,
pickup_time: state.state.pickupTime,
visit_external_id: state.state.visit_external_id,
distance: 0,
duration: 0,
eta: 0,
trip_type: state.state.trip_type,
return_time: state.state.return_time,
};
if (self.state.eta.distance_miles) requestRide.distance = self.state.eta.distance_miles;
if (self.state.eta.duration_seconds) requestRide.duration = self.state.eta.duration_seconds;
requestRide.origin.name = self.state.pickupLocation
requestRide.destination.name = self.state.providerName
if (self.diffMinutes(state.state.pickupTime, new Date()) > 10) {
requestRide.scheduled_pickup_range = {
range_ms: null,
timestamp_ms: new Date(self.state.pickupTime).getTime()
}
}
Instance.getRawConn().post('/v1/nemt/rides', requestRide).then(function (res) {
self.handleRequestClose(self);
window.location.href = '/#/app/page/map/' + res.data.ride_uuid;
}).catch(console.error);
}
}
};
diffMinutes(dt2, dt1) {
var diff = (dt2.getTime() - dt1.getTime()) / 1000;
diff /= 60;
return Math.abs(Math.round(diff));
}
handlePrev(state) {
let self = state;
const { stepIndex } = self.state;
if (stepIndex > 0) {
self.setState(Object.assign(self.state, { stepIndex: stepIndex - 1 }));
}
};
handleChange(value, state) {
let self = state
self.setState(Object.assign(self.state, {
rideTypeValue: parseInt(value.target.defaultValue)
}));
};
handleProvider(value, state) {
let self = state;
console.log(value);
self.setState(Object.assign(self.state, {
providerID: value.value,
providerName: value.text
}));
};
handleDate(event, date, state) {
let self = state
let visitTime = new Date(date.getTime() + (1 * 60 * 60 * 1000));
let visitDate = date;
let pickupTime = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000));
let pickupTimeReturn = new Date(visitTime.getTime() - (0.5 * 60 * 60 * 1000));
self.setState(Object.assign(self.state, {
visitDate: visitDate,
visitTime: visitTime,
pickupTime: pickupTime,
pickupTimeReturn: pickupTimeReturn,
}));
}
handleTime(value, date, state) {
let self = state;
self.setState(Object.assign(self.state, {
visitDate: date,
visitTime: date,
pickupTime: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)),
pickupTimeReturn: new Date(date.getTime() - (0.5 * 60 * 60 * 1000)),
}));
}
handlePickupTime(value, date, state) {
let self = state;
console.log('Pickup Time', date);
self.setState(Object.assign(self.state, {
pickupTime: date,
pickupTimeReturn: date
}));
}
handlePickupTimeReturn(value, date, state) {
let self = state;
self.setState(Object.assign(self.state, {
return_time: date,
pickupTimeReturn: date,
pickupTimeReturnDisplayMode: 'block'
}));
}
handlePickup(value) {
console.log(value);
this.setState(Object.assign(this.state, {
pickupLocation: value.text
}));
};
handleExternalID(e, value, state) {
let self = state;
self.setState(Object.assign(self.state, {
visit_external_id: value
}));
}
handleNotes(e, value, state) {
let self = state
self.setState(Object.assign(self.state, {
notes: value
}));
}
handleChangeVisitType(event, index, value, state) {
let self = state;
let trip_type = {
key: value.selectField,
}
// console.log(event, index, value, state);
// console.log(trip_type);
self.setState(Object.assign(self.state, { pickupTimeReturnDisplayMode: value.pickupTimeReturnDisplayMode, trip_type: trip_type, pickupTimeHide: value.pickupTimeHide }));
}
renderStepActions(step, state) {
let self = state;
return (
<div style={{ margin: '12px 0' }}>
{step !== 2 && (
<RaisedButton
label="Next"
disableTouchRipple
disableFocusRipple
primary
onTouchTap={() => self.handleNext(self)}
style={{ marginRight: 12 }}
/>
)}
{step === 2 && (
<RaisedButton
label="Confirm"
disableTouchRipple
disableFocusRipple
primary
onTouchTap={() => self.handleNext(self)}
style={{ marginRight: 12 }}
href=""
/>
)}
{step > 0 && (
<FlatButton
label="Back"
disableTouchRipple
disableFocusRipple
onTouchTap={() => self.handlePrev(self)}
/>
)}
</div>
);
}
// checkValue = (value) => {
// return value === this.state.rideTypeValue;
// }
updateCheck() {
this.setState((oldState) => {
return {
checked: !oldState.checked,
};
});
}
getLocation() {
var defaultPlace = {
coords: {
latitude: 41.851382,
longitude: -87.675980
}
}
if (navigator.geolocation) {
// this.setPosition(defaultPlace);
navigator.geolocation.getCurrentPosition(this.setPosition);
} else {
this.setPosition(defaultPlace);
}
}
setPosition(position) {
localStorage.setItem('position', JSON.stringify({ latitude: position.coords.latitude, longitude: position.coords.longitude }));
}
handleProviderChanged(res, state) {
let self = state;
let destination = {
id: res.id,
name: res.name,
lat: res.lat,
lng: res.lng,
address: res.address
}
const name = res.name;
if (self.state.origin && self.state.origin.lat && self.state.origin.lng) {
let url = self.state.origin.lat + '/' + self.state.origin.lng + '/' + destination.lat + '/' + destination.lng
Instance.getRawConn().get('/v1/nemt/rides/eta/' + url).then(function (res) {
let obj = {
distance_miles: res.data.cost_estimates[0].estimated_distance_miles,
duration_seconds: res.data.cost_estimates[0].estimated_duration_seconds,
formatted_time: self.formatTime(res.data.cost_estimates[0].estimated_duration_seconds),
showed: true,
}
localStorage.setItem('eta', JSON.stringify(obj));
console.log('ETA Info', obj);
if (!self.state.eta.showed) {
self.setState(Object.assign(self.state, {
message: ('BOOKING...Estimated Distance: ' + obj.distance_miles + ' miles\nEstimated Time: ' + obj.formatted_time),
open: true,
}));
}
self.setState(Object.assign(self.state, {
eta: obj,
buttonProviderText: name,
providerName: name,
destination: destination
}));
});
} else {
self.setState(Object.assign(self.state, {
buttonProviderText: name,
providerName: name,
destination: destination
}));
}
}
formatTime(sec_num) {
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) { hours = "0" + hours; }
if (minutes < 10) { minutes = "0" + minutes; }
if (seconds < 10) { seconds = "0" + seconds; }
return hours + ':' + minutes + ':' + seconds;
}
handlePickupChanged = (res, state) => {
let origin = {
id: res.id,
name: res.name,
lat: res.lat,
lng: res.lng,
address: res.address
}
const name = res.name;
if (state.state.destination && state.state.destination.lat && state.state.destination.lng) {
let url = origin.lat + '/' + origin.lng + '/' + state.state.destination.lat + '/' + state.state.destination.lng
Instance.getRawConn().get('/v1/nemt/rides/eta/' + url).then(function (res) {
let obj = {
distance_miles: res.data.cost_estimates[0].estimated_distance_miles,
duration_seconds: res.data.cost_estimates[0].estimated_duration_seconds,
formatted_time: state.formatTime(res.data.cost_estimates[0].estimated_duration_seconds),
showed: true,
}
localStorage.setItem('eta', JSON.stringify(obj));
if (!state.state.eta.showed) {
state.setState(Object.assign(state.state, {
message: ('BOOKING...Estimated Distance: ' + obj.distance_miles + ' miles\nEstimated Time: ' + obj.formatted_time),
open: true,
}));
}
state.setState(Object.assign(state.state, {
eta: obj,
buttonPickupText: name,
pickupLocation: name,
origin: origin,
}));
});
} else {
state.setState(Object.assign(state.state, {
buttonPickupText: name,
pickupLocation: name,
origin: origin
}));
}
}
render() {
// const { stepIndex } = this.state;
this.getLocation();
const state = this;
let userSelection;
let pickupTimeSelector;
if (this.state.pickupTimeReturnDisplayMode !== 'none') {
pickupTimeSelector = (
<TimePicker
autoWidth={false}
style={{ width: 80, display: pickupTimeReturnDisplayMode }}
format="ampm"
underlineShow={true}
hintText="Choose Return Time"
floatingLabelText="Return Time"
value={this.state.pickupTimeReturn}
onChange={(e, d) => this.handlePickupTimeReturn(e, d, this)}
minutesStep={5}
/>)
}
let pickupTime = (<TimePicker
autoWidth={false}
style={{ width: 80 }}
format="ampm"
underlineShow={true}
hintText="Choose Pickup Time"
floatingLabelText="Pickup Time"
value={this.state.pickupTime}
onChange={(e, d) => this.handlePickupTime(e, d, this)}
minutesStep={5}
/>);
if (this.state.pickupTimeHide) pickupTime = null;
if (this.state.showUserSelection && this.state.users.length > 0) {
const handleAutocomplete = (u) => {
state.setState(Object.assign(state.state, { user: u, userSelectionText: u.userdata }));
}
const datasourceConfig = { text: 'userdata', value: 'useruuid' }
userSelection = (
<div>
<AutoComplete style={{ fontSize: '10' }} dataSourceConfig={datasourceConfig} dataSource={this.state.users} floatingLabelText="Choose Member" filter={(searchText, key) => (key.toLowerCase().indexOf(searchText.toLowerCase()) !== -1)} maxSearchResults={5} onNewRequest={handleAutocomplete} searchText={this.state.userSelectionText} />
</div>
);
} else if (this.state.showUserSelection && this.state.users.length === 0) {
userSelection = (<div style={{ fontSize: '10' }} >
<strong>Loading...</strong>
</div>);
} else {
userSelection = (<div >
<strong>{this.state.user.member}</strong> - {this.state.user.name}
</div>);
}
return (
<article className="article padding-sm-v">
<h2 className="article-title" style={{ paddingTop: 10, margin: 0 }} >Book Ride</h2>
<div className="box box-default">
<div className="box-body padding-xs">
<div style={{ maxWidth: 380, margin: 'auto' }}>
<Stepper
activeStep={this.state.stepIndex}
linear={false}
orientation="vertical"
>
<Step>
<StepButton onClick={() => this.setState({ stepIndex: 0 })}>
Member
</StepButton>
<StepContent>
<form role="form">
<a href="/#/app/page/eligibility" target="_new" >Verify Eligibility</a>
<div className="divider" />
<strong>OR</strong>
{userSelection}
<div className="divider" />
<NEMTLocation type="flat" floatingLabelText='Choose Member Location' hintText="Choose Member Location" data={this.state} title={"Member Address"} value={""} buttonvalue={this.state.buttonPickupText} onPlaceChanged={(provider) => this.handlePickupChanged(provider, this)} fontSize={12} loadSuggestion={true} address={this.state.origin} />
<Checkbox
label="Member has consented to terms of use"
checked={this.state.checked}
onCheck={this.updateCheck.bind(this)}
style={styles.checkbox}
/>
<div className="divider" />
</form>
{this.renderStepActions(0, this)}
</StepContent>
</Step>
<Step>
<StepButton onClick={() => this.setState({ stepIndex: 1 })}>
Provider
</StepButton>
<StepContent>
<form role="form">
<NEMTLocation type="flat" data={this.state} title={"Provider"} value={""} buttonvalue={this.state.buttonProviderText} onPlaceChanged={(provider) => this.handleProviderChanged(provider, this)} fontSize={12} locationType="provider" loadSuggestion={true} address={this.state.destination} />
{/* <div className="divider" /> */}
</form>
{this.renderStepActions(1, this)}
</StepContent>
</Step>
<Step>
<StepButton onClick={() => this.setState({ stepIndex: 2 })}>
Visit Details
</StepButton>
<StepContent>
<form role="form">
<div className="form-group">
<DatePicker formatDate={new DateTimeFormat('en-US', {
weekday: 'short',
day: 'numeric',
month: 'long',
year: 'numeric',
}).format} style={{ maxWidth: 80 }} hintText="Visit Date" floatingLabelText="Date" container="inline" onChange={(e, d) => this.handleDate(e, d, this)} shouldDisableDate={disableWeekends} value={this.state.visitDate} />
<TimePicker
style={{ maxWidth: 80 }}
format="ampm"
hintText="Visit Time"
floatingLabelText="Time"
value={this.state.visitTime}
onChange={(e, d) => this.handleTime(e, d, this)}
minutesStep={5}
/>
</div>
<div className="divider" />
<div className="form-group">
<TextField hintText="Visit External ID" floatingLabelText="External ID" onChange={(e, v) => this.handleExternalID(e, v, this)} value={this.state.visit_external_id} />
</div>
</form>
{/* <TabsSection /> */}
{this.renderStepActions(1, this)}
</StepContent>
</Step>
<Step>
<StepButton onClick={() => this.setState({ stepIndex: 3 })}>
Trip Details
</StepButton>
<StepContent>
{/* <Paper zDepth={7}> */}
<form>
<SelectFieldExampleSimple handleChange={(e, i, v) => this.handleChangeVisitType(e, i, v, this)} value={this.state.trip_type.key} />
{pickupTime}
{pickupTimeSelector}
<SelectFieldExampleMultiSelect />
<DialogExampleDialogDatePicker />
<TextField
underlineShow={true}
hintText="Notes for Driver"
floatingLabelText="Notes for Driver"
onChange={(e, v) => this.handleNotes(e, v, this)}
value={this.state.notes} multiLine={true}
maxlength={250}
rows={1}
/>
{/* <Divider /> */}
</form>
{/* </Paper> */}
{this.renderStepActions(2, this)}
</StepContent>
</Step>
</Stepper>
</div>
<div style={{ maxWidth: 380, margin: 'auto' }}>
<div className="divider divider-xl" />
<div className="callout callout-info">
<p>Complete steps <strong>1 - 4</strong> to schedule your ride!</p>
</div>
</div>
</div>
</div>
<div>
<Snackbar
style={{ fontSize: '7' }}
open={this.state.open}
message={this.state.message}
// message="Booking Ride"
autoHideDuration={50000}
onRequestClose={() => this.handleRequestClose(this)}
/>
</div>
</article>
);
}
}
export default VerticalNonLinear;

View File

@@ -0,0 +1,8 @@
module.exports = {
path: 'steppers/:uuid',
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./components/Steppers'));
});
}
};

Some files were not shown because too many files have changed in this diff Show More