first commit
23
src/actions/index.js
Normal 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
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/images/5_min.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
29
src/assets/images/audio.svg
Normal 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 |
BIN
src/assets/images/background/1.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
src/assets/images/background/2.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
src/assets/images/bg-pattern/bg-pattern1.png
Executable file
|
After Width: | Height: | Size: 932 B |
BIN
src/assets/images/bg-pattern/bg-pattern10.png
Executable file
|
After Width: | Height: | Size: 193 B |
BIN
src/assets/images/bg-pattern/bg-pattern11.png
Executable file
|
After Width: | Height: | Size: 166 B |
BIN
src/assets/images/bg-pattern/bg-pattern12.png
Executable file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/images/bg-pattern/bg-pattern2.png
Executable file
|
After Width: | Height: | Size: 257 B |
BIN
src/assets/images/bg-pattern/bg-pattern3.png
Executable file
|
After Width: | Height: | Size: 179 B |
BIN
src/assets/images/bg-pattern/bg-pattern4.png
Executable file
|
After Width: | Height: | Size: 213 B |
BIN
src/assets/images/bg-pattern/bg-pattern5.png
Executable file
|
After Width: | Height: | Size: 160 B |
BIN
src/assets/images/bg-pattern/bg-pattern6.png
Executable file
|
After Width: | Height: | Size: 163 B |
BIN
src/assets/images/bg-pattern/bg-pattern7.png
Executable file
|
After Width: | Height: | Size: 161 B |
BIN
src/assets/images/bg-pattern/bg-pattern8.png
Executable file
|
After Width: | Height: | Size: 237 B |
BIN
src/assets/images/bg-pattern/bg-pattern9.png
Executable file
|
After Width: | Height: | Size: 189 B |
BIN
src/assets/images/bg-pattern/logo_x_pattern.png
Normal file
|
After Width: | Height: | Size: 964 B |
BIN
src/assets/images/g1.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
src/assets/images/home.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
src/assets/images/ic_account_circle_white_48dp_1x.png
Normal file
|
After Width: | Height: | Size: 632 B |
BIN
src/assets/images/prius.jpg
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/assets/images/prius1.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
src/assets/images/prius2.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/images/provider_pin.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
8
src/assets/react.svg
Normal 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
@@ -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'),
|
||||
);
|
||||
86
src/components/Connection/index.js
Normal 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();
|
||||
22
src/components/Footer/index.js
Normal 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;
|
||||
33
src/components/Header/NavLeftList.js
Normal 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;
|
||||
80
src/components/Header/NavRightList.js
Normal 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;
|
||||
70
src/components/Header/index.js
Normal 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);
|
||||
|
||||
245
src/components/Notifications/index.js
Normal 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;
|
||||
106
src/components/ReactECharts/index.js
Normal 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;
|
||||
297
src/components/Shared/Notification.js
Normal 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,
|
||||
}
|
||||
0
src/components/Shared/index.js
Normal file
155
src/components/Sidenav/SidenavContent.js
Normal 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;
|
||||
107
src/components/Sidenav/index.js
Normal 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);
|
||||
|
||||
7
src/constants/ActionTypes.js
Normal 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';
|
||||
16
src/constants/ChartConfig.js
Normal 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
@@ -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
@@ -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);
|
||||
33
src/containers/themes/darkTheme.js
Normal 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),
|
||||
},
|
||||
};
|
||||
33
src/containers/themes/grayTheme.js
Normal 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),
|
||||
},
|
||||
};
|
||||
36
src/containers/themes/lightTheme.js
Normal 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
@@ -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
@@ -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;
|
||||
29
src/routes/404/components/404.js
Normal 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
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: '404',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/404'));
|
||||
});
|
||||
}
|
||||
};
|
||||
29
src/routes/500/components/500.js
Normal 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
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: '500',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/500'));
|
||||
});
|
||||
}
|
||||
};
|
||||
245
src/routes/app/components/ContactList.js
Normal 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,
|
||||
}
|
||||
105
src/routes/app/components/ContactOption.js
Normal 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;
|
||||
65
src/routes/app/components/Geolocation.js
Normal 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;
|
||||
63
src/routes/app/components/MainApp.js
Normal 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;
|
||||
1196
src/routes/app/components/NEMTLocation.js
Normal file
70
src/routes/app/components/RoadtripLink.js
Normal 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
@@ -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'));
|
||||
});
|
||||
}
|
||||
};
|
||||
16
src/routes/app/routes/charts/index.js
Normal 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'),
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
546
src/routes/app/routes/charts/routes/bar/components/Bar.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/bar/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'bar',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Bar'));
|
||||
});
|
||||
}
|
||||
};
|
||||
261
src/routes/app/routes/charts/routes/funnel/components/Funnel.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/funnel/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'funnel',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Funnel'));
|
||||
});
|
||||
}
|
||||
};
|
||||
419
src/routes/app/routes/charts/routes/line/components/Line.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/line/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'line',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Line'));
|
||||
});
|
||||
}
|
||||
};
|
||||
189
src/routes/app/routes/charts/routes/more/components/More.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/more/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'more',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/More'));
|
||||
});
|
||||
}
|
||||
};
|
||||
232
src/routes/app/routes/charts/routes/pie/components/Pie.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/pie/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'pie',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Pie'));
|
||||
});
|
||||
}
|
||||
};
|
||||
333
src/routes/app/routes/charts/routes/radar/components/Radar.js
Normal 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;
|
||||
8
src/routes/app/routes/charts/routes/radar/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'radar',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Radar'));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
8
src/routes/app/routes/charts/routes/scatter/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'Scatter',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Scatter'));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
83
src/routes/app/routes/dashboard/components/BenchmarkChart.js
Normal 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;
|
||||
84
src/routes/app/routes/dashboard/components/Dashboard.js
Normal 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;
|
||||
133
src/routes/app/routes/dashboard/components/EngagementStats.js
Normal 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;
|
||||
108
src/routes/app/routes/dashboard/components/KPIsChart.js
Normal 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;
|
||||
62
src/routes/app/routes/dashboard/components/StatBoxes.js
Normal 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;
|
||||
8
src/routes/app/routes/dashboard/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'dashboard',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Dashboard'));
|
||||
});
|
||||
}
|
||||
};
|
||||
12
src/routes/app/routes/forms/index.js
Normal 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'),
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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="☺"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
text: 'text-value2',
|
||||
value: (
|
||||
<MenuItem
|
||||
primaryText="text-value2"
|
||||
secondaryText="☺"
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
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;
|
||||
@@ -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;
|
||||
127
src/routes/app/routes/forms/routes/components/components/Chip.js
Normal 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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
8
src/routes/app/routes/forms/routes/components/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'components',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Components'));
|
||||
});
|
||||
}
|
||||
};
|
||||
250
src/routes/app/routes/forms/routes/layouts/components/Layouts.js
Normal 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;
|
||||
8
src/routes/app/routes/forms/routes/layouts/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'layouts',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Layouts'));
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
8
src/routes/app/routes/forms/routes/steppers/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
path: 'steppers/:uuid',
|
||||
getComponent(nextState, cb) {
|
||||
require.ensure([], (require) => {
|
||||
cb(null, require('./components/Steppers'));
|
||||
});
|
||||
}
|
||||
};
|
||||