Make lock charges calculation functional for happy path

This commit is contained in:
Senad Uka
2019-06-03 18:04:42 +02:00
parent d850aef0b8
commit 8e4eb0cf1f
22 changed files with 820 additions and 61 deletions

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

View File

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

View File

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

View File

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

View File

@@ -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:

View File

@@ -0,0 +1,5 @@
import axios from 'axios';
export default axios.create({
baseURL: '/api/'
});