diff --git a/src/AppContainer.jsx b/src/AppContainer.jsx
index e5afd2ccd..a43e350d9 100644
--- a/src/AppContainer.jsx
+++ b/src/AppContainer.jsx
@@ -3,6 +3,7 @@ import GraphContainer from './components/Graph';
import SearchContainer from './components/SearchContainer/SearchContainer';
import SpotlightContainer from './components/Spotlight/SpotlightContainer';
import LogoutModal from './components/Modals/LogoutModal';
+import CancelUploadModal from './components/Modals/CancelUploadModal';
import ClearWarnModal from './components/Modals/ClearWarnModal'
import ClearConfirmModal from './components/Modals/ClearConfirmModal'
import ClearingModal from './components/Modals/ClearingModal'
@@ -39,6 +40,7 @@ export default class AppContainer extends Component {
+
diff --git a/src/components/Menu/MenuContainer.jsx b/src/components/Menu/MenuContainer.jsx
index af02fef80..961261e98 100644
--- a/src/components/Menu/MenuContainer.jsx
+++ b/src/components/Menu/MenuContainer.jsx
@@ -1,6 +1,8 @@
import React, { Component } from 'react';
import MenuButton from './MenuButton';
+import ProgressBarMenuButton from './ProgressBarMenuButton';
import { buildMergeQuery, defaultAjaxSettings } from 'utils';
+import { If, Then, Else } from 'react-if';
const { dialog } = require('electron').remote
var fs = require('fs')
@@ -9,8 +11,22 @@ export default class MenuContainer extends Component {
super()
this.state = {
- refreshHover: false
+ refreshHover: false,
+ uploading: false,
+ progress: 0,
+ parser: null,
+ currentAjax: null
}
+
+ emitter.on('cancelUpload', this.cancelUpload.bind(this))
+ }
+
+ cancelUpload(){
+ this.state.parser.abort()
+ this.state.currentAjax.abort()
+ setTimeout(function(){
+ this.setState({uploading: false})
+ }.bind(this), 1000)
}
_refreshClick(){
@@ -44,7 +60,10 @@ export default class MenuContainer extends Component {
properties: ['openFile']
})[0]
+ var i;
+
fs.readFile(filename, 'utf8', function(err, data){
+ var count = data.split('\n').length;
var header = data.split('\n')[0]
var filetype;
if (header.includes('UserName') && header.includes('ComputerName') && header.includes('Weight')){
@@ -62,31 +81,53 @@ export default class MenuContainer extends Component {
return;
}
+ this.setState({
+ uploading: true,
+ progress: 0
+ })
+ var completed = -1;
Papa.parse(data,{
- worker: true,
header: true,
dynamicTyping: true,
+ chunkSize: 131072,
chunk: function(rows, parser){
+ parser.pause()
+ this.setState({parser: parser})
var options = defaultAjaxSettings()
options.url = appStore.databaseInfo.url + '/db/data/batch'
- var data = JSON.stringify(buildMergeQuery(rows.data, filetype), null, 2)
+ //var data = JSON.stringify(buildMergeQuery(rows.data, filetype), null, 2)
options.data = JSON.stringify(buildMergeQuery(rows.data, filetype))
- options.complete = function(){
+ options.success = function(){
+ completed += rows.data.length
+ this.setState({progress: Math.floor((completed / count) * 100)})
+ if (completed === count){
+ setTimeout(function(){
+ this.setState({uploading: false})
+ }.bind(this), 3000)
+ }
+ parser.resume()
emitter.emit('refreshDBData')
- }
+ }.bind(this)
options.error = function(xhr, status, error){
- console.log(xhr)
- console.log(status)
- console.log(error)
+ if (xhr.statusText !== 'abort'){
+ console.log(xhr)
+ console.log(status)
+ console.log(error)
+ }
}
- $.ajax(options);
- }
+ var a = $.ajax(options);
+ this.setState({currentAjax: a})
+ }.bind(this)
})
- })
+ }.bind(this))
}
_settingsClick(){
- emitter.emit('openSettings')
+ emitter.emit('openSettings')
+ }
+
+ _cancelUploadClick(){
+ emitter.emit('showCancelUpload')
}
render() {
@@ -102,7 +143,14 @@ export default class MenuContainer extends Component {
-
+
+
+
+
+ { () =>
+
+ }
+
diff --git a/src/components/Menu/ProgressBarMenuButton.jsx b/src/components/Menu/ProgressBarMenuButton.jsx
new file mode 100644
index 000000000..ef4ee6fe2
--- /dev/null
+++ b/src/components/Menu/ProgressBarMenuButton.jsx
@@ -0,0 +1,70 @@
+import React, { Component } from 'react';
+
+export default class ProgressBarMenuButton extends Component {
+ propTypes: {
+ progress : React.PropTypes.number.isRequired,
+ click : React.PropTypes.func.isRequired
+ }
+
+ constructor(){
+ super()
+
+ this.state = {
+ expanded: false
+ }
+ }
+
+ _leave(e){
+ this.setState({expanded: false})
+ var target = $(e.target)
+ var oldWidth = target.width()
+ target.html('{}%'.format(this.props.progress))
+ target.animate({
+ width: '41px'
+ }, 100)
+ }
+
+ _enter(e){
+ this.setState({expanded: true})
+ var target = $(e.target)
+ var oldWidth = target.width()
+ var template = `
`.formatAll(this.props.progress)
+ target.html(template)
+ target.animate({
+ width: '150px'
+ }, 100)
+ }
+
+ componentWillReceiveProps(nextProps){
+ if (this.state.expanded){
+ var template = `
`.formatAll(nextProps.progress)
+ $(this.refs.btn).html(template)
+ }else{
+ $(this.refs.btn).html('{}%'.format(nextProps.progress))
+ }
+
+ this.forceUpdate()
+ }
+
+ shouldComponentUpdate(nextProps, nextState){
+ return true
+ }
+
+ componentDidMount(){
+ $(this.refs.btn).html('{}%'.format(this.props.progress))
+ $(this.refs.btn).css('padding','6px 0px 6px 0px')
+ $(this.refs.btn).css('width','41px')
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/components/Modals/CancelUploadModal.jsx b/src/components/Modals/CancelUploadModal.jsx
new file mode 100644
index 000000000..89a9ab88f
--- /dev/null
+++ b/src/components/Modals/CancelUploadModal.jsx
@@ -0,0 +1,57 @@
+import React, { Component } from 'react';
+
+var Modal = require('react-bootstrap').Modal;
+
+export default class CancelUploadModal extends Component {
+
+ constructor(){
+ super();
+ this.state = {
+ open: false
+ }
+ }
+
+ closeModal(){
+ this.setState({ open: false })
+ }
+
+ closeAndCancel(){
+ this.setState({ open: false })
+ emitter.emit('cancelUpload');
+ }
+
+ openModal(){
+ this.setState({open: true})
+ }
+
+ componentDidMount() {
+ emitter.on('showCancelUpload', this.openModal.bind(this))
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+
+ Are you sure you want to cancel the upload?
+
+
+
+
+
+
+
+ );
+ }
+}