Refactor project structure
This commit is contained in:
142
app/src/components/App.tsx
Normal file
142
app/src/components/App.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import * as React from 'react'
|
||||
import ConnectionSetup from './ConnectionSetup/ConnectionSetup'
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import ErrorBoundary from './ErrorBoundary'
|
||||
import Notification from './Layout/Notification'
|
||||
import TitleBar from './Layout/TitleBar'
|
||||
import UpdateNotifier from '../UpdateNotifier'
|
||||
import { AppState } from '../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { globalActions, settingsActions } from '../actions'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
|
||||
const Settings = React.lazy(() => import('./SettingsDrawer/Settings'))
|
||||
const ContentView = React.lazy(() => import('./Layout/ContentView'))
|
||||
|
||||
interface Props {
|
||||
connectionId: string
|
||||
classes: any
|
||||
settingsVisible: boolean
|
||||
error?: string
|
||||
actions: typeof globalActions
|
||||
settingsActions: typeof settingsActions
|
||||
launching: boolean
|
||||
}
|
||||
|
||||
class App extends React.PureComponent<Props, {}> {
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.state = { }
|
||||
}
|
||||
|
||||
private renderError() {
|
||||
if (this.props.error) {
|
||||
const error = typeof this.props.error === 'string' ? this.props.error : JSON.stringify(this.props.error)
|
||||
return (
|
||||
<Notification
|
||||
message={error}
|
||||
onClose={() => { this.props.actions.showError(undefined) }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
this.props.settingsActions.loadSettings()
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { settingsVisible } = this.props
|
||||
const { content, contentShift, centerContent, paneDefaults, heightProperty } = this.props.classes
|
||||
|
||||
if (this.props.launching) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={centerContent}>
|
||||
<CssBaseline />
|
||||
<ErrorBoundary>
|
||||
{this.renderError()}
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<Settings />
|
||||
</React.Suspense>
|
||||
<div className={centerContent}>
|
||||
<div className={`${settingsVisible ? contentShift : content}`}>
|
||||
<TitleBar />
|
||||
</div>
|
||||
<div className={settingsVisible ? contentShift : content}>
|
||||
<React.Suspense fallback={<div>Loading...</div>}>
|
||||
<ContentView heightProperty={heightProperty} connectionId={this.props.connectionId} paneDefaults={paneDefaults} />
|
||||
</React.Suspense>
|
||||
</div>
|
||||
</div>
|
||||
<UpdateNotifier />
|
||||
<ConnectionSetup />
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => {
|
||||
const drawerWidth = 300
|
||||
return {
|
||||
heightProperty: {
|
||||
height: 'calc(100vh - 64px) !important',
|
||||
},
|
||||
paneDefaults: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
color: theme.palette.text.primary,
|
||||
overflowY: 'scroll' as 'scroll',
|
||||
overflowX: 'hidden' as 'hidden',
|
||||
display: 'block' as 'block',
|
||||
height: 'calc(100vh - 64px)',
|
||||
},
|
||||
centerContent: {
|
||||
width: '100vw',
|
||||
overflow: 'hidden' as 'hidden',
|
||||
},
|
||||
content: {
|
||||
width: '100vw',
|
||||
overflowX: 'hidden' as 'hidden',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
transition: theme.transitions.create('transform', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
transform: 'translateX(0px)',
|
||||
},
|
||||
contentShift: {
|
||||
overflowX: 'hidden' as 'hidden',
|
||||
width: '100vw',
|
||||
padding: 0,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
transition: theme.transitions.create('transform', {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
transform: `translateX(${drawerWidth}px)`,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: any) => {
|
||||
return {
|
||||
actions: bindActionCreators(globalActions, dispatch),
|
||||
settingsActions: bindActionCreators(settingsActions, dispatch),
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
settingsVisible: state.settings.visible,
|
||||
connectionId: state.connection.connectionId,
|
||||
error: state.globalState.error,
|
||||
highlightTopicUpdates: state.settings.highlightTopicUpdates,
|
||||
launching: state.globalState.launching,
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(App))
|
||||
111
app/src/components/ErrorBoundary.tsx
Normal file
111
app/src/components/ErrorBoundary.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import * as React from 'react'
|
||||
import PersistentStorage from '../utils/PersistentStorage'
|
||||
import SentimentDissatisfied from '@material-ui/icons/SentimentDissatisfied'
|
||||
import Warning from '@material-ui/icons/Warning'
|
||||
import { electronRendererTelementry } from 'electron-telemetry'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
Paper,
|
||||
Toolbar,
|
||||
Typography,
|
||||
} from '@material-ui/core'
|
||||
|
||||
interface State {
|
||||
error?: Error
|
||||
}
|
||||
|
||||
interface Props {
|
||||
classes: any
|
||||
}
|
||||
|
||||
class ErrorBoundary extends React.Component<Props, State> {
|
||||
|
||||
public static getDerivedStateFromError(error: Error) {
|
||||
return { error }
|
||||
}
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
private restart = () => {
|
||||
window.location = window.location
|
||||
}
|
||||
|
||||
private clearStorage = () => {
|
||||
PersistentStorage.clear()
|
||||
window.location = window.location
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: any) {
|
||||
electronRendererTelementry.trackError(error)
|
||||
console.log('did catch', error)
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (!this.state.error) {
|
||||
return this.props.children
|
||||
}
|
||||
|
||||
const { classes } = this.props
|
||||
return (
|
||||
<Modal open={true} disableAutoFocus={true}>
|
||||
<Paper className={classes.root}>
|
||||
<Toolbar style={{ padding: '0' }}>
|
||||
<Typography className={classes.title} variant="h6" color="inherit"><Warning /> Oooooops!</Typography>
|
||||
</Toolbar>
|
||||
<Typography className={classes.centered}>I hoped that you would never see this window, but MQTT-Explorer had an unexpected error.</Typography>
|
||||
<Typography className={classes.centered}><SentimentDissatisfied /></Typography>
|
||||
<pre className={classes.textColor} style={{ maxHeight: '35vh', overflow: 'scroll' }}>
|
||||
<code className={classes.textColor}>
|
||||
{this.state.error.stack}
|
||||
</code>
|
||||
</pre>
|
||||
<Typography>
|
||||
Please report this issue with a short description of what happened to
|
||||
<span> <a className={classes.textColor} href="https://github.com/thomasnordquist/MQTT-Explorer/issues">https://github.com/thomasnordquist/MQTT-Explorer/issues</a></span>
|
||||
</Typography>
|
||||
<div>
|
||||
<div className={classes.buttonPositioning}>
|
||||
<Button className={classes.button} variant="contained" color="secondary" onClick={this.clearStorage}>Start Fresh</Button>
|
||||
<Button className={classes.button} variant="contained" color="primary" onClick={this.restart}>Restart</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Paper>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => ({
|
||||
button: {
|
||||
margin: '0 8px 0 8px',
|
||||
},
|
||||
root: {
|
||||
minWidth: 550,
|
||||
maxWidth: 650,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
margin: '10vh auto auto auto',
|
||||
padding: theme.spacing(2),
|
||||
outline: 'none',
|
||||
},
|
||||
title: {
|
||||
color: theme.palette.text.primary,
|
||||
margin: '0',
|
||||
textAlign: 'center' as 'center',
|
||||
},
|
||||
textColor: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
centered: {
|
||||
textAlign: 'center' as 'center',
|
||||
},
|
||||
buttonPositioning: {
|
||||
textAlign: 'center' as 'center',
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
})
|
||||
|
||||
export default withStyles(styles)(ErrorBoundary)
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react'
|
||||
import ReactSplitPane from 'react-split-pane'
|
||||
import { Sidebar } from './Sidebar'
|
||||
import Tree from './Tree/Tree'
|
||||
import { Sidebar } from '../Sidebar'
|
||||
import Tree from '../Tree/Tree'
|
||||
|
||||
export default function ContentView(props: {heightProperty: any, paneDefaults: any, connectionId: any}) {
|
||||
return (
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import CustomIconButton from './CustomIconButton'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import CustomIconButton from '../helper/CustomIconButton'
|
||||
import Pause from '@material-ui/icons/PauseCircleFilled'
|
||||
import Resume from '@material-ui/icons/PlayCircleFilled'
|
||||
import { AppState } from '../reducers'
|
||||
import { AppState } from '../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { treeActions } from '../actions'
|
||||
import { treeActions } from '../../actions'
|
||||
import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
|
||||
import { Tooltip } from '@material-ui/core'
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import * as React from 'react'
|
||||
import ClearAdornment from './helper/ClearAdornment'
|
||||
import ClearAdornment from '../helper/ClearAdornment'
|
||||
import CloudOff from '@material-ui/icons/CloudOff'
|
||||
import ConnectionHealthIndicator from './helper/ConnectionHealthIndicator'
|
||||
import ConnectionHealthIndicator from '../helper/ConnectionHealthIndicator'
|
||||
import Menu from '@material-ui/icons/Menu'
|
||||
import Search from '@material-ui/icons/Search'
|
||||
import { AppState } from '../reducers'
|
||||
import { AppState } from '../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { connectionActions, settingsActions, treeActions } from '../actions'
|
||||
import { connectionActions, settingsActions, treeActions } from '../../actions'
|
||||
import { fade } from '@material-ui/core/styles/colorManipulator'
|
||||
import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
|
||||
import {
|
||||
@@ -3,7 +3,7 @@ import * as React from 'react'
|
||||
import { AppState } from '../../reducers'
|
||||
import { connect } from 'react-redux'
|
||||
import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { Base64Message } from '../../../../backend/src/Model/Base64Message'
|
||||
import teal from '@material-ui/core/colors/teal'
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as React from 'react'
|
||||
import { Theme, withStyles } from '@material-ui/core'
|
||||
import 'prismjs/components/prism-json'
|
||||
import 'prismjs/themes/prism-tomorrow.css'
|
||||
import { CodeBlockColors } from '../CodeBlockColors'
|
||||
import { CodeBlockColors } from './CodeBlockColors'
|
||||
|
||||
interface Props {
|
||||
previous: string
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as React from 'react'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { Typography } from '@material-ui/core'
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -36,7 +36,7 @@ import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { publishActions, globalActions } from '../../../actions'
|
||||
import ClearAdornment from '../../helper/ClearAdornment'
|
||||
import { TopicViewModel } from '../../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../../model/TopicViewModel'
|
||||
|
||||
interface Props {
|
||||
node?: q.TreeNode<TopicViewModel>
|
||||
@@ -345,4 +345,4 @@ const mapStateToProps = (state: AppState) => {
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme(connect(mapStateToProps, mapDispatchToProps)(Publish))
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(Publish))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as React from 'react'
|
||||
import Copy from '../helper/Copy'
|
||||
import CustomIconButton from '../CustomIconButton'
|
||||
import CustomIconButton from '../helper/CustomIconButton'
|
||||
import Delete from '@material-ui/icons/Delete'
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore'
|
||||
import NodeStats from './NodeStats'
|
||||
@@ -12,7 +12,7 @@ import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { settingsActions, sidebarActions } from '../../actions'
|
||||
import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
|
||||
import {
|
||||
ExpansionPanel,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
import { treeActions } from '../../actions'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
|
||||
interface Props {
|
||||
classes: any
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as React from 'react'
|
||||
import BarChart from '@material-ui/icons/BarChart'
|
||||
import DateFormatter from '../../helper/DateFormatter'
|
||||
import History from '../History'
|
||||
import { TopicViewModel } from '../../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../../model/TopicViewModel'
|
||||
import { Base64Message } from '../../../../../backend/src/Model/Base64Message'
|
||||
|
||||
const PlotHistory = React.lazy(() => import('./PlotHistory'))
|
||||
|
||||
@@ -5,7 +5,7 @@ import { AppState } from '../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { TopicOrder } from '../../reducers/Settings'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { treeActions } from '../../actions'
|
||||
|
||||
const MovingAverage = require('moving-average')
|
||||
|
||||
@@ -4,7 +4,7 @@ import TreeNodeSubnodes from './TreeNodeSubnodes'
|
||||
import TreeNodeTitle from './TreeNodeTitle'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { TopicOrder } from '../../reducers/Settings'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
|
||||
const debounce = require('lodash.debounce')
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as q from '../../../../backend/src/Model'
|
||||
import TreeNode from './TreeNode'
|
||||
import { TopicOrder } from '../../reducers/Settings'
|
||||
import { Theme, withStyles } from '@material-ui/core'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
|
||||
export interface Props {
|
||||
animateChanges: boolean
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { withStyles, Theme } from '@material-ui/core'
|
||||
import { TopicViewModel } from '../../TopicViewModel'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { Base64Message } from '../../../../backend/src/Model/Base64Message'
|
||||
const debounce = require('lodash.debounce')
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import Check from '@material-ui/icons/Check'
|
||||
import CustomIconButton from '../CustomIconButton'
|
||||
import CustomIconButton from './CustomIconButton'
|
||||
import FileCopy from '@material-ui/icons/FileCopy'
|
||||
import green from '@material-ui/core/colors/green'
|
||||
import { Snackbar, SnackbarContent, Tooltip } from '@material-ui/core'
|
||||
|
||||
Reference in New Issue
Block a user