Commit 14c40379 by HaOuiha

migrate all api to redux

parent 45ee557e
......@@ -17,8 +17,7 @@ class App extends Component {
if (user) {
this.props.fireStoreGetConfig && (await this.props.fireStoreGetConfig());
this.props.fireStoreGetCurrentUser && (await this.props.fireStoreGetCurrentUser());
const { uid } = this.props.fireStoreCurrentUser;
this.props.getAllDevicesInfo && (await this.props.getAllDevicesInfo(uid));
this.props.getAllDevicesInfo && (await this.props.getAllDevicesInfo());
this.setState({
authenticated: true,
loading: false,
......@@ -32,26 +31,25 @@ class App extends Component {
});
};
renderLoading = () => (
<div
style={{
flex: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
}}
>
<PulseLoader size={20} color={'#49b9ff'} />
</div>
);
render() {
const { authenticated, loading } = this.state;
if (loading) {
return (
<div
style={{
flex: 1,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '100vh',
}}
>
<PulseLoader size={20} color={'#49b9ff'} />
</div>
);
}
return (
return loading ? (
this.renderLoading()
) : (
<Router>
<PrivateRoute exact path="/" component={Home} authenticated={authenticated} />
<Route exact path="/login" component={LogIn} />
......@@ -60,12 +58,6 @@ class App extends Component {
}
}
const mapStateToProps = state => {
return {
fireStoreCurrentUser: state.fireStoreReducer.fireStoreCurrentUser,
};
};
const mapDispatchToProps = {
fireStoreGetConfig,
fireStoreGetCurrentUser,
......@@ -73,6 +65,6 @@ const mapDispatchToProps = {
};
export default connect(
mapStateToProps,
null,
mapDispatchToProps
)(App);
......@@ -3,14 +3,12 @@ import { Row, Container } from 'react-bootstrap';
import DataTable from '../components/DataTable';
import NavBar from '../components/NavBar';
import DataCard from '../components/DataCard';
import GetDataSelection from '../components/GetDataSelection/GetDataSelection';
import GetDataSelection from '../components/GetDataSelection';
import Mapbox from '../components/Mapbox';
import AlertBox from '../components/AlertBox';
import axios from 'axios';
import moment from 'moment';
import { connect } from 'react-redux';
import { toggleAlert } from '../redux/actions/alertAction';
import { getAllDevicesInfo } from '../redux/actions/allDevicesInfoAction';
import { getFeedData } from '../redux/actions/feedDataAction';
const Data = [
{
......@@ -82,14 +80,6 @@ const Data = [
class Home extends Component {
state = {
currentUser: null,
currentFeed: null,
currentDetail: null,
revenueFeed: null,
peopleFeed: null,
remoteFeed: null,
fingerPrintFeed: null,
keycardFeed: null,
currentLast: null,
revenueTotal: null,
revenueMax: null,
......@@ -114,185 +104,37 @@ class Home extends Component {
table: null,
isLoading: true,
};
looper = null;
componentDidMount = () => {
const { uid } = this.props.fireStoreCurrentUser;
this.props.getAllDevicesInfo(uid);
this.props.getAllDevicesInfo();
};
looper = null;
componentDidUpdate = (prevProps, prevState) => {
const { device, range, breakdown } = this.props.selectedFeed;
if (prevProps.selectedFeed !== this.props.selectedFeed) {
this.loopFeedData(device, range, breakdown);
this.setState({ isLoading: true });
this.loopFeedData();
}
if (prevProps.feedData !== this.props.feedData) {
this.setDataToCharts();
this.setState({ isLoading: false });
}
};
loopFeedData = async (deviceId, selectedRange, breakdown) => {
loopFeedData = () => {
clearInterval(this.looper);
await this.getFeedData(deviceId, selectedRange, breakdown);
this.looper = setInterval(async () => await this.getFeedData(deviceId, selectedRange, breakdown), 300000);
this.props.getFeedData();
this.looper = setInterval(() => this.props.getFeedData(), 300000);
};
getFeedData = async (deviceId, selectedRange, breakdown) => {
const { fireStoreConfig } = this.props;
const { kairosUrl, userToken } = fireStoreConfig;
const { startDate, endDate } = selectedRange;
const q_data = {
start_absolute: startDate,
end_absolute: endDate,
metrics: [
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ["['Current Cash']"],
},
aggregators: [
{
name: 'last',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Revenue'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
setDataToCharts = () => {
const { currentFeed, revenueFeed, remoteFeed, peopleFeed, fingerPrintFeed, keycardFeed } = this.props.feedData;
const { device } = this.props.selectedFeed;
const selectedSiteName = this.props.allDeviceInfo[
this.props.allDeviceInfo.findIndex(element => element.deviceid === device)
].name;
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Remote'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['People'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Fingerprint'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Keycard'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
],
};
this.setState({ isLoading: true });
try {
console.log('getFeedData');
axios.defaults.headers.common['Authorization'] = `Bearer ${userToken}`;
const response = await axios.post(kairosUrl, q_data);
await this.setState({
currentFeed: response.data.queries[0].results[0].values || [],
revenueFeed: response.data.queries[1].results[0].values || [],
remoteFeed: response.data.queries[2].results[0].values || [],
peopleFeed: response.data.queries[3].results[0].values || [],
fingerPrintFeed: response.data.queries[4].results[0].values || [],
keycardFeed: response.data.queries[5].results[0].values || [],
});
} catch (error) {
console.error(error);
this.props.toggleAlert();
}
const { currentFeed, revenueFeed, remoteFeed, peopleFeed, fingerPrintFeed, keycardFeed } = this.state;
await this.setState({
this.setState({
currentLast: currentFeed.length > 0 ? Math.round(currentFeed[currentFeed.length - 1][1] * 100) / 100 : '-',
revenueTotal: revenueFeed.length > 0 ? Math.round(this.getTotal(revenueFeed) * 100) / 100 : '-',
revenueMax: revenueFeed.length > 0 ? Math.round(this.getMax(revenueFeed) * 100) / 100 : '-',
......@@ -314,7 +156,7 @@ class Home extends Component {
keycardMax: keycardFeed.length > 0 ? Math.round(this.getMax(keycardFeed) * 100) / 100 : '-',
keycardMin: keycardFeed.length > 0 ? Math.round(this.getMin(keycardFeed) * 100) / 100 : '-',
keycardAvg: keycardFeed.length > 0 ? Math.round(this.getAvg(keycardFeed) * 100) / 100 : '-',
table: this.getTable(this.props.allDeviceInfo[this.props.allDeviceId.indexOf(deviceId)].name, [
table: this.getTable(selectedSiteName, [
peopleFeed,
revenueFeed,
remoteFeed,
......@@ -323,7 +165,6 @@ class Home extends Component {
currentFeed,
]),
});
this.setState({ isLoading: false });
};
getMax = data => {
......@@ -385,12 +226,12 @@ class Home extends Component {
};
render() {
const { currentFeed, revenueFeed, peopleFeed, remoteFeed, fingerPrintFeed, keycardFeed } = this.state;
const { currentFeed, revenueFeed, peopleFeed, remoteFeed, fingerPrintFeed, keycardFeed } = this.props.feedData;
return (
<>
<NavBar />
<AlertBox />
<Container style={{ padding: '30px', maxWidth: '990px' }}>
<Row>
<GetDataSelection loading={this.state.isLoading} />
......@@ -466,17 +307,15 @@ class Home extends Component {
const mapStateToProps = state => {
return {
fireStoreConfig: state.fireStoreReducer.fireStoreConfig,
fireStoreCurrentUser: state.fireStoreReducer.fireStoreCurrentUser,
selectedFeed: state.selectedFeedReducer.selectedFeed,
allDeviceInfo: state.allDevicesInfoReducer.allDeviceInfo,
allDeviceId: state.allDevicesInfoReducer.allDeviceId,
feedData: state.feedDataReducer,
};
};
const mapDispatchToProps = {
toggleAlert,
getAllDevicesInfo,
getFeedData,
};
export default connect(
......
import React from 'react';
import { Card, Form, Button, Container } from 'react-bootstrap';
const LogInView = ({ onSubmit }) => {
return (
<Container
......
......@@ -4,15 +4,11 @@ import { withRouter } from 'react-router';
import app from '../../firebase';
class LogInContainer extends Component {
state = {
membership: null,
};
handleSignUp = async event => {
event.preventDefault();
const { email, password } = event.target.elements;
try {
await app.auth().signInWithEmailAndPassword(email.value, password.value);
this.props.history.push('/');
} catch (error) {
alert(error);
......
import React from 'react';
import { Toast } from 'react-bootstrap';
import { connect } from 'react-redux';
import { toggleAlert } from '../redux/actions/alertAction';
const AlertBox = props => {
return (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
}}
>
<Toast
style={{ marginLeft: 'auto', marginRight: 'auto' }}
onClose={() => props.toggleAlert()}
show={props.isShow}
delay={3000}
autohide
>
<Toast.Header>
<strong className="mr-auto">Sorry, something went wrong.</strong>
</Toast.Header>
<Toast.Body>Could not get data from the server.</Toast.Body>
</Toast>
</div>
);
};
const mapStateToProps = state => {
return { isShow: state.alertReducer.isShow };
};
const mapDispatchToProps = {
toggleAlert,
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(AlertBox);
......@@ -5,20 +5,14 @@ import DateRangePicker from 'react-bootstrap-daterangepicker';
import { FaRegCalendarAlt } from 'react-icons/fa';
import 'bootstrap-daterangepicker/daterangepicker.css';
import { connect } from 'react-redux';
import { getSelectedFeed } from '../../redux/actions/selectedFeedAction';
import { getSelectedFeed } from '../redux/actions/selectedFeedAction';
class GetDataSelection extends Component {
state = {
device: this.props.allDeviceId[0],
// range: {
// startDate: moment()
// .startOf('day')
// .valueOf(),
// endDate: moment().valueOf(),
// },
breakdown: 'minutes',
startDate: moment().startOf('day'),
endDate: moment(),
endDate: moment().endOf('day'),
ranges: {
Today: [moment(), moment()],
Yesterday: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
......@@ -62,13 +56,13 @@ class GetDataSelection extends Component {
this.submitSelectedRange();
};
componentDidUpdate = (prevProps, prevState) => {
if (prevProps) {
if (prevState !== this.state) {
this.submitSelectedRange();
}
}
};
// componentDidUpdate = (prevProps, prevState) => {
// if (prevProps) {
// if (prevState !== this.state) {
// this.submitSelectedRange();
// }
// }
// };
render() {
const { allDeviceId, allDeviceInfo } = this.props;
......
......@@ -16,25 +16,21 @@ class Mapbox extends Component {
};
componentDidUpdate = (prevProps, prevState) => {
if (prevProps.allDeviceInfo !== this.props.allDeviceInfo) {
let data1 = this.props.allDeviceInfo;
this.setState({
data: data1,
center: data1[0].position,
active: data1[0],
});
if (this.props.allDeviceInfo) {
if (prevProps.selectedFeed !== this.props.selectedFeed) {
const data1 = this.props.allDeviceInfo;
const { device } = this.props.selectedFeed;
const currentIndex = data1.findIndex(element => element.deviceid === device);
this.setState({
data: data1,
center: data1[currentIndex].position,
active: data1[currentIndex],
});
}
}
};
// componentDidMount = () => {
// let data1 = this.props.allDeviceInfo;
// this.setState({
// data: data1,
// center: data1[0].position,
// active: data1[0],
// });
// };
render() {
const { center, active, zoom } = this.state;
return (
......
......@@ -8,7 +8,7 @@ import logger from 'redux-logger';
import App from './App';
import './styles.scss';
const middleware = process.env.NODE_ENV === `development` ? applyMiddleware(thunk, logger) : applyMiddleware(thunk);
let middleware = process.env.NODE_ENV === `development` ? applyMiddleware(thunk, logger) : applyMiddleware(thunk);
const store = createStore(rootReducer, middleware);
......
export const TOGGLE_ALERT = 'TOGGLE_ALERT';
export const alert = () => ({
type: TOGGLE_ALERT,
});
export const toggleAlert = () => dispatch => {
return dispatch(alert());
};
......@@ -8,10 +8,12 @@ export const getAllDevicesInfoAction = (allDeviceInfo, allDeviceId) => ({
allDeviceId,
});
export const getAllDevicesInfo = uid => async dispatch => {
export const getAllDevicesInfo = () => async (dispatch, getState) => {
const { fireStoreReducer } = getState();
const currentUid = fireStoreReducer.fireStoreCurrentUser.uid;
const DeviceId = await db
.collection('membership')
.doc(uid)
.doc(currentUid)
.get();
let allDeviceId = Object.keys(DeviceId.data());
let allDeviceInfo = [];
......
import axios from 'axios';
export const GET_FEED_DATA = 'GET_FEED_DATA';
export const getFeedDataAction = ({
currentFeed,
revenueFeed,
remoteFeed,
peopleFeed,
fingerPrintFeed,
keycardFeed,
}) => ({
type: GET_FEED_DATA,
currentFeed,
revenueFeed,
remoteFeed,
peopleFeed,
fingerPrintFeed,
keycardFeed,
});
export const getFeedData = () => async (dispatch, getState) => {
const { fireStoreReducer, selectedFeedReducer } = getState();
const { kairosUrl, userToken } = fireStoreReducer.fireStoreConfig;
const { device, range, breakdown } = selectedFeedReducer.selectedFeed;
const q_data = {
start_absolute: range.startDate,
end_absolute: range.endDate,
metrics: [
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ["['Current Cash']"],
},
aggregators: [
{
name: 'last',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Revenue'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Remote'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['People'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Fingerprint'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: device,
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Keycard'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
],
};
try {
// axios.defaults.headers.common['Authorization'] = `Bearer ${userToken}`;
// const response = await axios.post(kairosUrl, q_data);
const request = {
url: kairosUrl,
method: 'post',
headers: { Authorization: `Bearer ${userToken}` },
data: q_data,
};
const response = await axios(request);
dispatch(
getFeedDataAction({
currentFeed: response.data.queries[0].results[0].values || [],
revenueFeed: response.data.queries[1].results[0].values || [],
remoteFeed: response.data.queries[2].results[0].values || [],
peopleFeed: response.data.queries[3].results[0].values || [],
fingerPrintFeed: response.data.queries[4].results[0].values || [],
keycardFeed: response.data.queries[5].results[0].values || [],
})
);
} catch (error) {
console.error(error);
}
};
......@@ -5,6 +5,6 @@ export const getSelectedFeedAction = (device, range, breakdown) => ({
selectedFeed: { device, range, breakdown },
});
export const getSelectedFeed = (device, range, breakdown) => async dispatch => {
export const getSelectedFeed = (device, range, breakdown) => dispatch => {
return dispatch(getSelectedFeedAction(device, range, breakdown));
};
import { TOGGLE_ALERT } from '../actions/alertAction';
const initState = {
isShow: false,
};
const alertReducer = (state = initState, action) => {
switch (action.type) {
case TOGGLE_ALERT:
return { ...state, isShow: !state.isShow };
default:
return state;
}
};
export default alertReducer;
import { GET_FEED_DATA } from '../actions/feedDataAction';
const initState = {
currentFeed: null,
revenueFeed: null,
remoteFeed: null,
peopleFeed: null,
fingerPrintFeed: null,
keycardFeed: null,
};
const feedDataReducer = (state = initState, action) => {
switch (action.type) {
case GET_FEED_DATA:
return {
...state,
...{
currentFeed: action.currentFeed,
revenueFeed: action.revenueFeed,
remoteFeed: action.remoteFeed,
peopleFeed: action.peopleFeed,
fingerPrintFeed: action.fingerPrintFeed,
keycardFeed: action.keycardFeed,
},
};
default:
return state;
}
};
export default feedDataReducer;
import { combineReducers } from 'redux';
import alertReducer from './alertReducer';
import fireStoreReducer from './fireStoreReducer';
import selectedFeedReducer from './selectedFeedReducer';
import allDevicesInfoReducer from './allDevicesInfoReducer';
import feedDataReducer from './feedDataReducer';
export default combineReducers({
alertReducer,
fireStoreReducer,
selectedFeedReducer,
allDevicesInfoReducer,
feedDataReducer,
});
// Override default variables before the import
// $body-bg: #000;
body {
background: linear-gradient(45deg, #f7f7f7, #e3e3e3);
}
......@@ -17,18 +14,6 @@ body {
cursor: pointer;
}
}
// .myStyleGutters {
// > .col,
// > [class*='col-'] {
// padding-right: 0;
// padding-left: 0.8rem;
// &:last-child {
// padding-right: 1rem;
// padding-left: 1rem;
// }
// }
// }
// Import Bootstrap and its default variables
@import '~bootstrap/scss/bootstrap.scss';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment