Commit 7662e6f1 by OuiAtichat

update redux

parent c0b81ba0
......@@ -21,10 +21,14 @@
"react-icons": "^3.7.0",
"react-mapbox-gl": "^4.6.0",
"react-paginate": "^6.3.0",
"react-redux": "^7.1.0",
"react-router-dom": "^5.0.1",
"react-scripts": "3.0.1",
"react-spinners": "^0.5.13",
"recharts": "^1.6.2"
"recharts": "^1.6.2",
"redux": "^4.0.4",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "react-scripts start",
......
......@@ -5,13 +5,17 @@ import app from './firebase';
import Home from './Pages/Home';
import LogIn from './Pages/LogIn';
import PulseLoader from 'react-spinners/PulseLoader';
import { connect } from 'react-redux';
import { fireStoreGetConfig, fireStoreGetCurrentUser } from './redux/actions/fireStoreAction';
class App extends Component {
state = { loading: true, authenticated: false };
componentDidMount() {
app.auth().onAuthStateChanged(user => {
componentDidMount = () => {
app.auth().onAuthStateChanged(async user => {
if (user) {
this.props.fireStoreGetConfig && (await this.props.fireStoreGetConfig());
this.props.fireStoreGetCurrentUser && (await this.props.fireStoreGetCurrentUser());
this.setState({
authenticated: true,
loading: false,
......@@ -23,7 +27,7 @@ class App extends Component {
});
}
});
}
};
render() {
const { authenticated, loading } = this.state;
......@@ -53,4 +57,12 @@ class App extends Component {
}
}
export default App;
const mapDispatchToProps = {
fireStoreGetConfig,
fireStoreGetCurrentUser,
};
export default connect(
null,
mapDispatchToProps
)(App);
import React, { Component } from 'react';
import app, { db } from '../firebase';
import { db } from '../firebase';
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 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 { fireStoreGetConfig, fireStoreGetCurrentUser } from '../redux/actions/fireStoreAction';
const Data = [
{
......@@ -59,20 +63,20 @@ const Data = [
title: 'Keycard chart',
backgroundColor: '#5E73F6',
detail: [
{ smtitle: 'Total Keycard', smValue: 0 },
{ smtitle: 'Avg. Keycard', smValue: 0 },
{ smtitle: 'Max. Keycard', smValue: 0, iconType: 'max' },
{ smtitle: 'Min. Keycard', smValue: 0, iconType: 'min' },
{ smtitle: 'Total Keycard' },
{ smtitle: 'Avg. Keycard' },
{ smtitle: 'Max. Keycard', iconType: 'max' },
{ smtitle: 'Min. Keycard', iconType: 'min' },
],
},
{
title: 'Fingerprint chart',
backgroundColor: '#5E73F6',
detail: [
{ smtitle: 'Total Fingerprint', smValue: 0 },
{ smtitle: 'Avg. Fingerprint', smValue: 0 },
{ smtitle: 'Max. Fingerprint', smValue: 0, iconType: 'max' },
{ smtitle: 'Min. Fingerprint', smValue: 0, iconType: 'min' },
{ smtitle: 'Total Fingerprint' },
{ smtitle: 'Avg. Fingerprint' },
{ smtitle: 'Max. Fingerprint', iconType: 'max' },
{ smtitle: 'Min. Fingerprint', iconType: 'min' },
],
},
];
......@@ -115,6 +119,7 @@ class Home extends Component {
keycardAvg: null,
table: null,
isLoading: true,
showAlert: false,
};
looper = null;
startDate = moment()
......@@ -123,9 +128,7 @@ class Home extends Component {
endDate = moment().valueOf();
componentDidMount = async () => {
await this.getConfig();
await this.getCurrentUser();
this.getAllDevicesInfo();
await this.getAllDevicesInfo();
};
componentDidUpdate = async (prevProps, prevState) => {
......@@ -135,30 +138,11 @@ class Home extends Component {
}
};
getConfig = async () => {
const configData = await db.collection('config').get();
//get all data from collection 'config'
configData.forEach(doc => {
this.setState({
kairosUrl: doc.data().kairosUrl,
userToken: doc.data().userToken,
});
});
};
getCurrentUser = async () => {
const { displayName, email, uid } = await app.auth().currentUser;
this.setState({
currentUser: displayName || email,
currentUid: uid,
});
};
getAllDevicesInfo = async () => {
const { currentUid } = this.state;
const { uid } = this.props.fireStoreCurrentUser;
const DevicesId = await db
.collection('membership')
.doc(currentUid)
.doc(uid)
.get();
let allDevicesId = Object.keys(DevicesId.data());
......@@ -191,7 +175,8 @@ class Home extends Component {
selectedRange = { startDate: this.startDate, endDate: this.endDate },
breakdown = 'minutes'
) => {
const { kairosUrl, userToken } = this.state;
const { fireStoreConfig } = this.props;
const { kairosUrl, userToken } = fireStoreConfig;
const { startDate, endDate } = selectedRange;
// const now = moment().valueOf();
......@@ -229,7 +214,92 @@ class Home extends Component {
},
],
tags: {
attr: ['Revenue', 'Reset', 'Remote', 'People', 'Fingerprint'],
attr: ['Revenue'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId || this.state.allDevicesId[0],
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Remote'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId || this.state.allDevicesId[0],
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['People'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId || this.state.allDevicesId[0],
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Fingerprint'],
},
aggregators: [
{
name: 'sum',
sampling: {
value: 1,
unit: breakdown,
},
},
],
},
{
name: deviceId || this.state.allDevicesId[0],
group_by: [
{
name: 'tag',
tags: ['attr'],
},
],
tags: {
attr: ['Keycards'],
},
aggregators: [
{
......@@ -245,18 +315,18 @@ class Home extends Component {
};
this.setState({ isLoading: true });
try {
console.log('getFeedData');
// console.log('getFeedData');
axios.defaults.headers.common['Authorization'] = `Bearer ${userToken}`;
const response = await axios.post(kairosUrl, q_data);
const [currentFeed, fingerPrintFeed, peopleFeed, remoteFeed, keycardFeed, revenueFeed] = [
const [currentFeed, revenueFeed, remoteFeed, peopleFeed, fingerPrintFeed, keycardFeed] = [
response.data.queries[0].results[0].values,
response.data.queries[1].results[0].values,
response.data.queries[1].results[1].values,
response.data.queries[1].results[2].values,
response.data.queries[1].results[3].values,
response.data.queries[1].results[4].values,
response.data.queries[2].results[0].values,
response.data.queries[3].results[0].values,
response.data.queries[4].results[0].values,
response.data.queries[4].results[0].values,
];
console.log(response);
this.setState({
currentFeed,
fingerPrintFeed,
......@@ -293,6 +363,7 @@ class Home extends Component {
});
} catch (error) {
console.error(error);
this.props.toggleAlert();
}
this.setState({ isLoading: false });
};
......@@ -339,7 +410,6 @@ class Home extends Component {
};
getTable = (site, data) => {
console.log(data);
let table = [];
for (let i = 0, len = data[1].length; i < len; i++) {
let v = {
......@@ -361,7 +431,6 @@ class Home extends Component {
const {
allDevicesId,
allDeviceInfo,
currentUser,
currentFeed,
revenueFeed,
peopleFeed,
......@@ -372,7 +441,8 @@ class Home extends Component {
return (
<>
<NavBar user={currentUser} />
<NavBar />
<AlertBox />
<Container style={{ padding: '30px', maxWidth: '990px' }}>
<Row>
<GetDataSelection
......@@ -451,4 +521,20 @@ class Home extends Component {
}
}
export default Home;
const mapStateToProps = state => {
return {
fireStoreConfig: state.fireStoreReducer.fireStoreConfig,
fireStoreCurrentUser: state.fireStoreReducer.fireStoreCurrentUser,
};
};
const mapDispatchToProps = {
toggleAlert,
// fireStoreGetConfig,
// fireStoreGetCurrentUser,
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
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={2500}
autohide
>
<Toast.Header>
<strong className="mr-auto">Sorry, something went wrong.</strong>
</Toast.Header>
<Toast.Body>Data source is not valid.</Toast.Body>
</Toast>
</div>
);
};
const mapStateToProps = state => {
return { isShow: state.alertReducer.isShow };
};
const mapDispatchToProps = {
toggleAlert,
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(AlertBox);
import React from 'react';
import { Card, Col, Row, Button } from 'react-bootstrap';
import { FaMoneyBillAlt, FaArrowUp, FaArrowDown, FaUserFriends, FaFileCsv } from 'react-icons/fa';
import { Card, Col, Row } from 'react-bootstrap';
import { FaMoneyBillAlt, FaArrowUp, FaArrowDown, FaUserFriends } from 'react-icons/fa';
import { AreaChart, Area, XAxis, YAxis, ResponsiveContainer, Tooltip } from 'recharts';
import withWindowDimensions from '../utils/withWindowDimensions';
import { CSVLink } from 'react-csv';
// import { CSVLink } from 'react-csv';
import moment from 'moment';
export const SmCard = props => {
......@@ -42,7 +42,7 @@ const DataCard = props => {
yAxis: value[1],
}));
}
console.log(props.datavalue);
return (
<Col md={6}>
<Card
......@@ -115,14 +115,14 @@ const DataCard = props => {
)
)}
</Row>
<Row style={{ justifyContent: 'flex-end', marginRight: 1 }}>
{/* <Row style={{ justifyContent: 'flex-end', marginRight: 1 }}>
<CSVLink data={props.datavalue} filename={data.title}>
<Button variant="outline-dark" style={{ marginTop: '.5em' }}>
<FaFileCsv style={{ margin: '0 2px 2px 0' }} />
Export to CSV
</Button>
</CSVLink>
</Row>
</Row> */}
</Col>
);
};
......
......@@ -22,7 +22,6 @@ export default class DataTable extends React.PureComponent {
this.setState({
data: data1,
});
console.log(data1);
}
};
......
......@@ -2,8 +2,10 @@ import React from 'react';
import { Navbar, Button } from 'react-bootstrap';
import app from '../firebase';
import withWindowDimensions from '../utils/withWindowDimensions';
import { connect } from 'react-redux';
const NavbarComponent = ({ user, isMobileSized }) => {
const NavbarComponent = ({ isMobileSized, fireStoreCurrentUser }) => {
const { username } = fireStoreCurrentUser;
const signOut = async () => {
await app.auth().signOut();
};
......@@ -12,7 +14,7 @@ const NavbarComponent = ({ user, isMobileSized }) => {
<Navbar.Brand style={{ color: '#fff' }}>ToiletCoin Dashboard</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse className="justify-content-end">
{!isMobileSized && <Navbar.Text style={{ color: '#fff' }}>user: {user} </Navbar.Text>}
{!isMobileSized && <Navbar.Text style={{ color: '#fff' }}>user: {username} </Navbar.Text>}
<Button variant="link" onClick={signOut} style={{ color: '#fff' }}>
Log Out
</Button>
......@@ -24,4 +26,12 @@ const NavbarComponent = ({ user, isMobileSized }) => {
);
};
export default withWindowDimensions(NavbarComponent);
const mapStateToProps = state => {
return {
fireStoreCurrentUser: state.fireStoreReducer.fireStoreCurrentUser,
};
};
const wrappedNavbar = withWindowDimensions(NavbarComponent);
export default connect(mapStateToProps)(wrappedNavbar);
import React from 'react';
import ReactDOM from 'react-dom';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './redux/reducers';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import App from './App';
import './styles.scss';
ReactDOM.render(<App />, document.getElementById('root'));
const middleware = process.env.NODE_ENV === `development` ? applyMiddleware(thunk, logger) : applyMiddleware(thunk);
const store = createStore(rootReducer, middleware);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
export const TOGGLE_ALERT = 'TOGGLE_ALERT';
export const alert = () => ({
type: TOGGLE_ALERT,
});
export const toggleAlert = () => dispatch => {
return dispatch(alert());
};
import app, { db } from '../../firebase';
export const GET_CONFIG = 'GET_CONFIG';
export const GET_CURRENT_USER = 'GET_CURRENT_USER';
export const fireStoreGetConfigAction = ({ kairosUrl, userToken }) => ({
type: GET_CONFIG,
fireStoreConfig: { kairosUrl, userToken },
});
export const fireStoreGetCurrentUserAction = ({ username, uid }) => ({
type: GET_CURRENT_USER,
fireStoreCurrentUser: { username, uid },
});
export const fireStoreGetConfig = () => async dispatch => {
const configData = await db.collection('config').get();
//get all data from collection 'config'
return configData.forEach(doc => {
return dispatch(
fireStoreGetConfigAction({
kairosUrl: doc.data().kairosUrl,
userToken: doc.data().userToken,
})
);
});
};
export const fireStoreGetCurrentUser = () => async dispatch => {
const { displayName, email, uid } = await app.auth().currentUser;
return dispatch(
fireStoreGetCurrentUserAction({
username: displayName || email,
uid,
})
);
};
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_CONFIG, GET_CURRENT_USER } from '../actions/fireStoreAction';
const initState = {
fireStoreConfig: null,
fireStoreCurrentUser: null,
};
const fireStoreReducer = (state = initState, action) => {
switch (action.type) {
case GET_CONFIG:
return { ...state, fireStoreConfig: action.fireStoreConfig };
case GET_CURRENT_USER:
return { ...state, fireStoreCurrentUser: action.fireStoreCurrentUser };
default:
return state;
}
};
export default fireStoreReducer;
import { combineReducers } from 'redux';
import alertReducer from './alertReducer';
import fireStoreReducer from './fireStoreReducer';
export default combineReducers({
alertReducer,
fireStoreReducer,
});
......@@ -3771,6 +3771,11 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
deep-diff@^0.3.5:
version "0.3.8"
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ=
deep-equal@1.0.1, deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
......@@ -5273,7 +5278,7 @@ hoist-non-react-statics@^2.3.1:
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==
hoist-non-react-statics@^3.1.0:
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
......@@ -9192,6 +9197,11 @@ react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-is@^16.8.6:
version "16.9.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.9.0.tgz#21ca9561399aad0ff1a7701c01683e8ca981edcb"
integrity sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==
react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
......@@ -9240,6 +9250,18 @@ react-popper@^1.3.2:
typed-styles "^0.0.7"
warning "^4.0.2"
react-redux@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.0.tgz#72af7cf490a74acdc516ea9c1dd80e25af9ea0b2"
integrity sha512-hyu/PoFK3vZgdLTg9ozbt7WF3GgX5+Yn3pZm5/96/o4UueXA+zj08aiSC9Mfj2WtD1bvpIb3C5yvskzZySzzaw==
dependencies:
"@babel/runtime" "^7.4.5"
hoist-non-react-statics "^3.3.0"
invariant "^2.2.4"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.8.6"
react-resize-detector@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c"
......@@ -9551,6 +9573,26 @@ reduce-function-call@^1.0.1:
dependencies:
balanced-match "^0.4.2"
redux-logger@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8=
dependencies:
deep-diff "^0.3.5"
redux-thunk@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
redux@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.4.tgz#4ee1aeb164b63d6a1bcc57ae4aa0b6e6fa7a3796"
integrity sha512-vKv4WdiJxOWKxK0yRoaK3Y4pxxB0ilzVx6dszU2W8wLxlb2yikRph4iV/ymtdJ6ZxpBLFbyrxklnT5yBbQSl3Q==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
regenerate-unicode-properties@^8.0.2:
version "8.1.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e"
......@@ -10610,7 +10652,7 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"
symbol-observable@^1.0.4:
symbol-observable@^1.0.4, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
......
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