From 1e280ea7be56ea3fbb2dc693a1385791ddd3853e Mon Sep 17 00:00:00 2001 From: Rohan Vazarkar Date: Wed, 24 Aug 2016 18:35:57 -0400 Subject: [PATCH] Add progress bar for upload + cancel --- src/AppContainer.jsx | 2 + src/components/Menu/MenuContainer.jsx | 74 +++++++++++++++---- src/components/Menu/ProgressBarMenuButton.jsx | 70 ++++++++++++++++++ src/components/Modals/CancelUploadModal.jsx | 57 ++++++++++++++ 4 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 src/components/Menu/ProgressBarMenuButton.jsx create mode 100644 src/components/Modals/CancelUploadModal.jsx 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 ( + + + + + ); + } +}