From e5729baa785c3a85d02d8315817e3a57f7c5fcb9 Mon Sep 17 00:00:00 2001 From: Determinant Date: Sun, 10 Feb 2019 01:39:31 -0500 Subject: popup works --- src/Analyze.js | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 src/Analyze.js (limited to 'src/Analyze.js') diff --git a/src/Analyze.js b/src/Analyze.js new file mode 100644 index 0000000..0d01210 --- /dev/null +++ b/src/Analyze.js @@ -0,0 +1,255 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import 'react-dates/initialize'; +import 'react-dates/lib/css/_datepicker.css'; +import { DateRangePicker } from 'react-dates'; +import { withStyles } from '@material-ui/core/styles'; +import cyan from '@material-ui/core/colors/cyan'; +import CssBaseline from '@material-ui/core/CssBaseline'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; +import FormControl from '@material-ui/core/FormControl'; +import FormGroup from '@material-ui/core/FormGroup'; +import Grid from '@material-ui/core/Grid'; +import AddCircleIcon from '@material-ui/icons/AddCircle'; +import IconButton from '@material-ui/core/IconButton'; +import * as gapi from './gapi'; +import { msgType, MsgClient } from './msg'; +import { Pattern, PatternEntry } from './pattern'; +import { AnalyzePieChart, getChartData } from './Chart'; +import PatternTable from './PatternTable'; +import Snackbar from './Snackbar'; +import AlertDialog from './Dialog'; + +const default_chart_data = [ + {name: 'Work', value: 10, color: cyan[300]}, + {name: 'Wasted', value: 10, color: cyan[300]}]; + +const styles = theme => ({ + buttonSpacer: { + marginBottom: theme.spacing.unit * 4, + }, +}); + +class Analyze extends React.Component { + state = { + patterns: [], + calendars: {}, + startDate: null, + endDate: null, + patternGraphData: default_chart_data, + calendarGraphData: default_chart_data, + snackBarOpen: false, + snackBarMsg: 'unknown', + snackBarVariant: 'error', + dialogOpen: false, + dialogMsg: {title: '', message: ''}, + }; + + constructor(props) { + super(props); + this.msgClient = new MsgClient('main'); + + this.msgClient.sendMsg({ + type: msgType.getPatterns, + data: { id: 'analyze' } + }).then(msg => { + this.setState({ patterns: msg.data.map(p => PatternEntry.inflate(p)) }); + }); + + this.msgClient.sendMsg({ + type: msgType.getCalendars, + data: { enabledOnly: true } + }).then(msg => { + this.setState({ calendars: msg.data }); + }); + + gapi.getLoggedIn().then(b => !b && + this.handleSnackbarOpen('Not logged in. Operating in offline mode.', 'warning')); + + this.dialogPromiseResolver = null; + } + + loadPatterns = patterns => { + this.msgClient.sendMsg({ + type: msgType.updatePatterns, + data: { id: 'analyze', patterns: patterns.map(p => p.deflate()) } + }).then(() => this.setState({ patterns })); + }; + + updatePattern = (field, idx, value) => { + let patterns = this.state.patterns; + patterns[idx][field] = value; + this.loadPatterns(patterns); + }; + + removePattern = idx => { + let patterns = this.state.patterns; + patterns.splice(idx, 1); + for (let i = 0; i < patterns.length; i++) + patterns[i].idx = i; + this.loadPatterns(patterns); + }; + + newPattern = () => { + let patterns = [PatternEntry.defaultPatternEntry(0), ...this.state.patterns]; + for (let i = 1; i < patterns.length; i++) + patterns[i].idx = i; + this.loadPatterns(patterns); + }; + + getCalEvents = (id, start, end) => { + return this.msgClient.sendMsg({ type: msgType.getCalEvents, data: { id, + start: start.getTime(), + end: end.getTime() } }) + .then(({ data }) => data.map(e => { + return { + id: e.id, + start: new Date(e.start), + end: new Date(e.end) } + })); + } + + analyze = () => { + if (!(this.state.startDate && this.state.endDate)) { + this.handleSnackbarOpen('Please choose a valid time range.', 'error'); + return; + } + let start = this.state.startDate.startOf('day').toDate(); + let end = this.state.endDate.startOf('day').toDate(); + getChartData(start, end, + this.state.patterns, + this.state.calendars, + this.getCalEvents).then(results => { + this.setState(results); + }); + } + + reset = () => { + this.handleDialogOpen("Reset", "Are you sure to reset the patterns?").then(ans => { + if (!ans) return; + this.loadPatterns([]); + this.setState({ startDate: null, endDate: null }); + }); + } + + default = () => { + this.handleDialogOpen("Load Default", "Load the calendars as patterns?").then(ans => { + if (!ans) return; + this.loadPatterns(Object.keys(this.state.calendars).map((id, idx) => { + let item = this.state.calendars[id]; + return new PatternEntry(item.name, idx, + new Pattern(id, false, item.name, item.name), + Pattern.anyPattern()); + })); + }); + } + + handleSnackbarClose = (event, reason) => { + if (reason === 'clickaway') return; + this.setState({ snackBarOpen: false }); + } + + handleSnackbarOpen = (msg, variant) => { + this.setState({ snackBarOpen: true, snackBarMsg: msg, snackBarVariant: variant }); + } + + handleDialogOpen = (title, message) => { + let pm = new Promise(resolver => { + this.dialogPromiseResolver = resolver + }); + this.setState({ dialogOpen: true, dialogMsg: {title, message} }); + return pm; + } + + handleDialogClose = result => { + this.dialogPromiseResolver(result); + this.setState({ dialogOpen: false }); + } + + render() { + const { classes } = this.props; + + return ( + + + + + + + + Analyzed Events + this.newPattern()}> + + + + + + Time Range + +
+ { + this.setState({ startDate, endDate }); + }} + focusedInput={this.state.focusedInput} + onFocusChange={focusedInput => this.setState({ focusedInput })} + isOutsideRange={() => false} /> +
+
+
+ + + + + + + + + + + + + + + + + + + + + + Results + + + + + ); + } +} + +Analyze.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Analyze); -- cgit v1.2.3