Make lock charges calculation functional for happy path
This commit is contained in:
59
client/src/scenes/UploadDLockData/components/FileUpload.js
Normal file
59
client/src/scenes/UploadDLockData/components/FileUpload.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {Form} from "semantic-ui-react";
|
||||
|
||||
import { uploadDoorLockData } from "../../../store/actions";
|
||||
|
||||
class FileUpload extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
file: null,
|
||||
};
|
||||
|
||||
this.onFileChange = this.onFileChange.bind(this);
|
||||
this.onUploadClick = this.onUploadClick.bind(this);
|
||||
}
|
||||
|
||||
onFileChange(event) {
|
||||
const file = event.target.files[0];
|
||||
this.setState({file});
|
||||
};
|
||||
|
||||
onUploadClick() {
|
||||
const { uploadDoorLockData } = this.props;
|
||||
const { file } = this.state;
|
||||
|
||||
if (file) {
|
||||
uploadDoorLockData(file);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { pending } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Form.Input
|
||||
fluid
|
||||
required
|
||||
label="Select DLock file"
|
||||
type="file"
|
||||
accept=".csv"
|
||||
onChange={this.onFileChange}
|
||||
/>
|
||||
<Form.Button onClick={this.onUploadClick} disabled={pending} >Upload</Form.Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
pending: state.doorLockData.pending,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
uploadDoorLockData: (doorLockDataFile) => uploadDoorLockData(dispatch, doorLockDataFile)
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(FileUpload);
|
||||
@@ -0,0 +1,86 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Loader, Message, Tab, Label, Menu } from 'semantic-ui-react';
|
||||
|
||||
class UploadResults extends Component {
|
||||
render(){
|
||||
const {pending, result, error} = this.props;
|
||||
|
||||
const parsedEntries = result && result.parsedData ? result.parsedData : [];
|
||||
const errorEntries = result && result.parserErrors ? result.parserErrors : [];
|
||||
const unknownMembers = result && result.unknownMembers ? result.unknownMembers : [];
|
||||
|
||||
const renderParsedEntriesTab = () => {
|
||||
return (
|
||||
<div>
|
||||
<br/>
|
||||
<Message positive>
|
||||
<p>{parsedEntries.length} entries successfully parsed</p>
|
||||
</Message>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderErrorTabResults = (results) => {
|
||||
return (
|
||||
<div>
|
||||
<br/>
|
||||
{
|
||||
results.map((entry, index) => {
|
||||
return (
|
||||
<div key={`error-${entry.error}-${index}`}>
|
||||
<br/>
|
||||
<Message negative>
|
||||
<Message.Header>{entry.error}</Message.Header>
|
||||
<p>{JSON.stringify(entry.details)}</p>
|
||||
<p>File : {entry.file}</p>
|
||||
</Message>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const parsedEntriesTabTitle = (<Menu.Item key="parsed-entries">Parsed Entries<Label>{parsedEntries.length}</Label></Menu.Item>);
|
||||
const errorEntriesTabTitle = (<Menu.Item key="error-entries">Error Entries<Label>{errorEntries.length}</Label></Menu.Item>);
|
||||
const unknownMembersTabTitle = (<Menu.Item key="unknown-members">Unknown Members<Label>{unknownMembers.length}</Label></Menu.Item>);
|
||||
|
||||
const panes = [
|
||||
{menuItem: parsedEntriesTabTitle, render: renderParsedEntriesTab},
|
||||
{menuItem: errorEntriesTabTitle, render: () => renderErrorTabResults(errorEntries)},
|
||||
{menuItem: unknownMembersTabTitle, render: () => renderErrorTabResults(unknownMembers)}
|
||||
];
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
pending && <Loader active />
|
||||
}
|
||||
<br/>
|
||||
{
|
||||
!pending && !error && result &&
|
||||
<Tab panes={panes}/>
|
||||
}
|
||||
{
|
||||
!pending && error &&
|
||||
<Message>
|
||||
<Message.Header>Upload Failed</Message.Header>
|
||||
<p>{error.data}</p>
|
||||
</Message>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
pending: state.doorLockData.pending,
|
||||
result: state.doorLockData.result,
|
||||
error: state.doorLockData.error,
|
||||
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(UploadResults);
|
||||
@@ -1,39 +1,22 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import React from 'react';
|
||||
import { Container, Form } from "semantic-ui-react";
|
||||
|
||||
import MainMenu from '../../components/MainMenu';
|
||||
import { uploadDoorLockData } from "../../store/actions";
|
||||
import FileUpload from './components/FileUpload';
|
||||
import UploadResults from './components/UploadResults';
|
||||
|
||||
class UploadDLockData extends Component {
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Container>
|
||||
<MainMenu/>
|
||||
<h3>DLock Data</h3>
|
||||
<hr/>
|
||||
<Form>
|
||||
<Form.Input
|
||||
fluid
|
||||
required
|
||||
label="Select DLock file"
|
||||
type="file"
|
||||
/>
|
||||
<Form.Button onClick={this.props.uploadDoorLockData}>Upload</Form.Button>
|
||||
</Form>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
function UploadDLockData() {
|
||||
return (
|
||||
<Container>
|
||||
<MainMenu/>
|
||||
<h3>DLock Data</h3>
|
||||
<hr/>
|
||||
<Form>
|
||||
<FileUpload/>
|
||||
</Form>
|
||||
<UploadResults/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
uploadDoorLockData: () => uploadDoorLockData(dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(UploadDLockData);
|
||||
export default UploadDLockData;
|
||||
|
||||
@@ -4,14 +4,21 @@ import {
|
||||
UPLOAD_DOOR_LOCK_DATA_FAILED
|
||||
} from "../constants";
|
||||
|
||||
export const uploadDoorLockData = (dispatch) => {
|
||||
import API from '../../utilities/api';
|
||||
|
||||
export const uploadDoorLockData = (dispatch, doorLockDataFile) => {
|
||||
const formData = new FormData();
|
||||
formData.append('doorLockDataFile', doorLockDataFile);
|
||||
const additionalConfig = {
|
||||
headers: {'content-type': 'multipart/form-data'}
|
||||
};
|
||||
|
||||
dispatch({type: UPLOAD_DOOR_LOCK_DATA_PENDING});
|
||||
fetch('/api/doorLockData')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
dispatch({type: UPLOAD_DOOR_LOCK_DATA_SUCCESS, payload: data})
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch({type: UPLOAD_DOOR_LOCK_DATA_FAILED, payload: err})
|
||||
API.post('doorLock/upload', formData, additionalConfig)
|
||||
.then(response => {
|
||||
dispatch({type: UPLOAD_DOOR_LOCK_DATA_SUCCESS, payload: response.data})
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch({type: UPLOAD_DOOR_LOCK_DATA_FAILED, payload: error.response})
|
||||
});
|
||||
};
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
|
||||
const initialState = {
|
||||
pending: false,
|
||||
result: {},
|
||||
error: '',
|
||||
result: null,
|
||||
error: null,
|
||||
};
|
||||
|
||||
export const doorLockData = (state, action) => {
|
||||
@@ -18,15 +18,18 @@ export const doorLockData = (state, action) => {
|
||||
case UPLOAD_DOOR_LOCK_DATA_PENDING:
|
||||
return Object.assign({}, state, {
|
||||
pending: true,
|
||||
error: null,
|
||||
});
|
||||
case UPLOAD_DOOR_LOCK_DATA_SUCCESS:
|
||||
return Object.assign({}, state, {
|
||||
pending: false,
|
||||
result: action.payload,
|
||||
error: null,
|
||||
});
|
||||
case UPLOAD_DOOR_LOCK_DATA_FAILED:
|
||||
return Object.assign({}, state, {
|
||||
pending: false,
|
||||
result: {},
|
||||
error: action.payload,
|
||||
});
|
||||
default:
|
||||
|
||||
5
client/src/utilities/api.js
Normal file
5
client/src/utilities/api.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export default axios.create({
|
||||
baseURL: '/api/'
|
||||
});
|
||||
Reference in New Issue
Block a user