Refactor project structure

This commit is contained in:
Thomas Nordquist
2019-04-07 20:16:48 +02:00
parent 16c72fa9be
commit e2c60cca64
44 changed files with 306 additions and 529 deletions

View File

@@ -7,7 +7,7 @@ import { Dispatch } from 'redux'
import { globalActions } from '.'
import { showError } from './Global'
import { showTree } from './Tree'
import { TopicViewModel } from '../TopicViewModel'
import { TopicViewModel } from '../model/TopicViewModel'
import {
addMqttConnectionEvent,
makeConnectionStateEvent,
@@ -60,18 +60,18 @@ const updateHealth = (dataSourceState: DataSourceState) => (dispatch: Dispatch<a
})
}
export const connected: (tree: q.Tree<TopicViewModel>, host: string) => Action = (tree: q.Tree<TopicViewModel>, host: string) => ({
export const connected: (tree: q.Tree<TopicViewModel>, host: string) => Action = (tree: q.Tree<TopicViewModel>, host: string) => ({
tree,
host,
type: ActionTypes.CONNECTION_SET_CONNECTED,
})
export const connecting: (connectionId: string) => Action = (connectionId: string) => ({
export const connecting: (connectionId: string) => Action = (connectionId: string) => ({
connectionId,
type: ActionTypes.CONNECTION_SET_CONNECTING,
})
export const disconnect = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const disconnect = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
const { connectionId, tree } = getState().connection
if (connectionId) {
rendererEvents.emit(removeConnection, connectionId)

View File

@@ -1,7 +1,7 @@
import { AppState } from '../reducers'
import { clearLegacyConnectionOptions, loadLegacyConnectionOptions } from '../model/LegacyConnectionSettings'
import { ConnectionOptions, createEmptyConnection, makeDefaultConnections, CertificateParameters } from '../model/ConnectionOptions'
import { default as persistentStorage, StorageIdentifier } from '../PersistentStorage'
import { default as persistentStorage, StorageIdentifier } from '../utils/PersistentStorage'
import { Dispatch } from 'redux'
import { showError } from './Global'
import { remote } from 'electron'

View File

@@ -2,11 +2,11 @@ import * as q from '../../../backend/src/Model'
import { AppState } from '../reducers'
import { autoExpandLimitSet } from '../components/SettingsDrawer/Settings'
import { batchActions } from 'redux-batched-actions'
import { default as persistentStorage, StorageIdentifier } from '../PersistentStorage'
import { default as persistentStorage, StorageIdentifier } from '../utils/PersistentStorage'
import { Dispatch } from 'redux'
import { showError } from './Global'
import { showTree } from './Tree'
import { TopicViewModel } from '../TopicViewModel'
import { TopicViewModel } from '../model/TopicViewModel'
import {
ActionTypes,
SettingsState,
@@ -19,7 +19,7 @@ const settingsIdentifier: StorageIdentifier<Partial<SettingsState>> = {
id: 'Settings',
}
export const loadSettings = () => async (dispatch: Dispatch<any>, _getState: () => AppState) => {
export const loadSettings = () => async (dispatch: Dispatch<any>) => {
try {
const settings = await persistentStorage.load(settingsIdentifier)
dispatch({
@@ -32,7 +32,7 @@ export const loadSettings = () => async (dispatch: Dispatch<any>, _getState: ()
dispatch(globalActions.didLaunch())
}
export const storeSettings = () => async (dispatch: Dispatch<any>, getState: () => AppState) => {
export const storeSettings = () => async (dispatch: Dispatch<any>, getState: () => AppState) => {
const settings = {
...getState().settings,
topicFilter: undefined,
@@ -46,7 +46,7 @@ export const storeSettings = () => async (dispatch: Dispatch<any>, getState: ()
}
}
export const setAutoExpandLimit = (autoExpandLimit: number = 0) => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const setAutoExpandLimit = (autoExpandLimit: number = 0) => (dispatch: Dispatch<any>) => {
dispatch({
autoExpandLimit,
type: ActionTypes.SETTINGS_SET_AUTO_EXPAND_LIMIT,
@@ -54,15 +54,15 @@ export const setAutoExpandLimit = (autoExpandLimit: number = 0) => (dispatch: Di
dispatch(storeSettings())
}
export const selectTopicWithMouseOver = (selectTopicWithMouseOver: boolean) => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const selectTopicWithMouseOver = (doSelect: boolean) => (dispatch: Dispatch<any>) => {
dispatch({
selectTopicWithMouseOver,
selectTopicWithMouseOver: doSelect,
type: ActionTypes.SETTINGS_SET_SELECT_TOPIC_WITH_MOUSE_OVER,
})
dispatch(storeSettings())
}
export const setValueDisplayMode = (valueRendererDisplayMode: 'diff' | 'raw') => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const setValueDisplayMode = (valueRendererDisplayMode: 'diff' | 'raw') => (dispatch: Dispatch<any>) => {
dispatch({
valueRendererDisplayMode,
type: ActionTypes.SETTINGS_SET_VALUE_RENDERER_DISPLAY_MODE,
@@ -70,21 +70,21 @@ export const setValueDisplayMode = (valueRendererDisplayMode: 'diff' | 'raw') =>
dispatch(storeSettings())
}
export const toggleSettingsVisibility = () => (dispatch: Dispatch<any>, _getState: () => AppState) => {
export const toggleSettingsVisibility = () => (dispatch: Dispatch<any>) => {
dispatch({
type: ActionTypes.SETTINGS_TOGGLE_VISIBILITY,
})
dispatch(storeSettings())
}
export const toggleHighlightTopicUpdates = () => (dispatch: Dispatch<any>, _getState: () => AppState) => {
export const toggleHighlightTopicUpdates = () => (dispatch: Dispatch<any>) => {
dispatch({
type: ActionTypes.SETTINGS_TOGGLE_HIGHLIGHT_ACTIVITY,
})
dispatch(storeSettings())
}
export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none) => (dispatch: Dispatch<any>, _getState: () => AppState) => {
export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none) => (dispatch: Dispatch<any>) => {
dispatch({
topicOrder,
type: ActionTypes.SETTINGS_SET_TOPIC_ORDER,
@@ -92,7 +92,7 @@ export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none) => (disp
dispatch(storeSettings())
}
export const filterTopics = (filterStr: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const filterTopics = (filterStr: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
const { tree } = getState().connection
dispatch({

View File

@@ -4,14 +4,14 @@ import { AnyAction, Dispatch } from 'redux'
import { AppState } from '../reducers'
import { batchActions } from 'redux-batched-actions'
import { setTopic } from './Publish'
import { TopicViewModel } from '../TopicViewModel'
import { TopicViewModel } from '../model/TopicViewModel'
const debounce = require('lodash.debounce')
export const selectTopic = (topic: q.TreeNode<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState) => {
export const selectTopic = (topic: q.TreeNode<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState) => {
debouncedSelectTopic(topic, dispatch, getState)
}
const debouncedSelectTopic = debounce((topic: q.TreeNode<TopicViewModel>, dispatch: Dispatch<any>, getState: () => AppState) => {
const debouncedSelectTopic = debounce((topic: q.TreeNode<TopicViewModel>, dispatch: Dispatch<any>, getState: () => AppState) => {
const { selectedTopic } = getState().tree
if (selectedTopic === topic) {
return
@@ -43,7 +43,7 @@ const debouncedSelectTopic = debounce((topic: q.TreeNode<TopicViewModel>, dispat
}
}, 70)
export const showTree = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
export const showTree = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
const visibleTree = getState().tree.tree
const connectionTree = getState().connection.tree
@@ -58,10 +58,8 @@ export const showTree = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<a
})
}
export const togglePause = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
export const togglePause = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
const paused = getState().tree.paused
const tree = getState().tree.tree
// tree && tree.applyUnmergedChanges()
return dispatch({
type: paused ? ActionTypes.TREE_RESUME_UPDATES : ActionTypes.TREE_PAUSE_UPDATES,

View File

@@ -1,21 +1,18 @@
import * as React from 'react'
import ConnectionSetup from './components/ConnectionSetup/ConnectionSetup'
import ConnectionSetup from './ConnectionSetup/ConnectionSetup'
import CssBaseline from '@material-ui/core/CssBaseline'
import ErrorBoundary from './ErrorBoundary'
import Notification from './components/Notification'
import Sidebar from './components/Sidebar/Sidebar'
import TitleBar from './components/TitleBar'
import Tree from './components/Tree/Tree'
import UpdateNotifier from './UpdateNotifier'
import { AppState } from './reducers'
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 { default as SplitPane } from 'react-split-pane'
import { globalActions, settingsActions } from './actions'
import { globalActions, settingsActions } from '../actions'
import { Theme, withStyles } from '@material-ui/core/styles'
const Settings = React.lazy(() => import('./components/SettingsDrawer/Settings'))
const ContentView = React.lazy(() => import('./components/ContentView'))
const Settings = React.lazy(() => import('./SettingsDrawer/Settings'))
const ContentView = React.lazy(() => import('./Layout/ContentView'))
interface Props {
connectionId: string

View File

@@ -1,5 +1,5 @@
import * as React from 'react'
import PersistentStorage from './PersistentStorage'
import PersistentStorage from '../utils/PersistentStorage'
import SentimentDissatisfied from '@material-ui/icons/SentimentDissatisfied'
import Warning from '@material-ui/icons/Warning'
import { electronRendererTelementry } from 'electron-telemetry'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,18 +1,18 @@
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import amber from '@material-ui/core/colors/amber'
import App from './App'
import App from './components/App'
import Demo from './components/Demo'
import reducers, { AppState } from './reducers'
import reduxThunk from 'redux-thunk'
import brown from '@material-ui/core/colors/brown'
import teal from '@material-ui/core/colors/teal'
import { applyMiddleware, compose, createStore } from 'redux'
import { batchDispatchMiddleware } from 'redux-batched-actions'
import { connect, Provider } from 'react-redux'
import { createMuiTheme, Theme } from '@material-ui/core/styles'
import { ThemeProvider } from '@material-ui/styles'
import './tracking'
import './utils/tracking'
const composeEnhancers = /*(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || */ compose
const store = createStore(
@@ -42,6 +42,7 @@ function createTheme(type: 'light' | 'dark') {
primary: {
main: '#931e2e',
},
// primary: brown,
secondary: amber,
// error: red,
action: {

View File

@@ -1,4 +1,4 @@
import { EventDispatcher } from '../../events'
import { EventDispatcher } from '../../../events'
export class TopicViewModel {
private selected: boolean

View File

@@ -2,7 +2,7 @@ import * as q from '../../../backend/src/Model'
import { Action } from 'redux'
import { createReducer } from './lib'
import { MqttOptions } from '../../../backend/src/DataSource'
import { TopicViewModel } from '../TopicViewModel'
import { TopicViewModel } from '../model/TopicViewModel'
export type ConnectionHealth = 'offline' | 'online' | 'connecting'
export interface ConnectionState {

View File

@@ -1,7 +1,7 @@
import * as q from '../../../backend/src/Model'
import { Action } from 'redux'
import { createReducer } from './lib'
import { TopicViewModel } from '../TopicViewModel'
import { TopicViewModel } from '../model/TopicViewModel'
export interface TreeState {
tree?: q.Tree<TopicViewModel>

View File

@@ -3,7 +3,7 @@ import { connectionManagerReducer, ConnectionManagerState } from './ConnectionMa
import { connectionReducer, ConnectionState } from './Connection'
import { publishReducer, PublishState } from './Publish'
import { settingsReducer, SettingsState } from './Settings'
import { trackEvent } from '../tracking'
import { trackEvent } from '../utils/tracking'
import { treeReducer, TreeState } from './Tree'
export enum ActionTypes {
@@ -50,30 +50,30 @@ const globalState: Reducer<GlobalState | undefined, CustomAction> = (state = ini
switch (action.type) {
case ActionTypes.showUpdateNotification:
return {
...state,
showUpdateNotification: action.showUpdateNotification,
}
...state,
showUpdateNotification: action.showUpdateNotification,
}
case ActionTypes.showError:
return {
...state,
error: action.error,
}
...state,
error: action.error,
}
case ActionTypes.didLaunch:
return {
...state,
launching: false,
}
...state,
launching: false,
}
case ActionTypes.showUpdateDetails:
if (action.showUpdateDetails === undefined) {
return state
}
return state
}
return {
...state,
showUpdateDetails: action.showUpdateDetails,
}
...state,
showUpdateDetails: action.showUpdateDetails,
}
default:
return state

View File

@@ -1,25 +0,0 @@
let userId = window.localStorage.getItem('userId')
const sha1 = require('sha1')
import { electronRendererTelementry } from 'electron-telemetry'
if (!userId) {
userId = sha1(sha1(Math.random()) + sha1(performance.now()) + sha1(Date.now())).slice(0, 8) as string
window.localStorage.setItem('userId', userId)
}
setInterval(() => {
try {
electronRendererTelementry.trackCustomEvent({ name: 'heapStatistics', payload: process.getHeapStatistics() })
electronRendererTelementry.trackCustomEvent({ name: 'cpuUsage', payload: process.getCPUUsage() })
electronRendererTelementry.trackCustomEvent({ name: 'runningSince', payload: performance.now() })
} catch (error) {
console.error(error)
}
}, 60 * 1000)
export function trackEvent(name: string) {
if (name.match(/^@@redux/)) {
return
}
electronRendererTelementry.trackEvent(name)
}

View File

@@ -1,4 +1,4 @@
import { rendererEvents } from '../../events'
import { rendererEvents } from '../../../events'
import { v4 } from 'uuid'
import {
@@ -7,7 +7,7 @@ import {
storageLoadEvent,
storageClearEvent,
makeStorageAcknowledgementEvent,
} from '../../events/StorageEvents'
} from '../../../events/StorageEvents'
export interface StorageIdentifier<Model> {
id: string

View File

@@ -1,4 +1,4 @@
import { electronRendererTelementry } from 'electron-telemetry'
const spareMeFromGc = electronRendererTelementry
const telemetry = electronRendererTelementry
electronRendererTelementry.registerErrorHandler()

23
app/src/utils/tracking.ts Normal file
View File

@@ -0,0 +1,23 @@
import { electronRendererTelementry } from 'electron-telemetry'
// Used to determine long-time-stability and memory leaks
function trackProcessStatistics() {
setInterval(() => {
try {
electronRendererTelementry.trackCustomEvent({ name: 'heapStatistics', payload: process.getHeapStatistics() })
electronRendererTelementry.trackCustomEvent({ name: 'cpuUsage', payload: process.getCPUUsage() })
electronRendererTelementry.trackCustomEvent({ name: 'runningSince', payload: performance.now() })
} catch (error) {
console.error(error)
}
}, 60 * 1000)
}
trackProcessStatistics()
// Log reducer event names to determine what functionality is used and how to reproduce reported errors
export function trackEvent(name: string) {
if (name.match(/^@@redux/)) {
return
}
electronRendererTelementry.trackEvent(name)
}