Adapt redux
Add hover-effect on nodes Add Setting drawer Ass auto expansion setting
This commit is contained in:
57
app/package-lock.json
generated
57
app/package-lock.json
generated
@@ -87,6 +87,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@material-ui/lab": {
|
||||||
|
"version": "3.0.0-alpha.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-3.0.0-alpha.27.tgz",
|
||||||
|
"integrity": "sha512-VwUCXEJEo1QkSTDoAg5g8K51f6Re7Fh5d7m5IO9W95B9iEYVJhSGy+WY1/ZQdpJl1F1gPzL9u2asCg6LIazBLA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "7.2.0",
|
||||||
|
"@material-ui/utils": "^3.0.0-alpha.2",
|
||||||
|
"classnames": "^2.2.5",
|
||||||
|
"keycode": "^2.1.9",
|
||||||
|
"prop-types": "^15.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@material-ui/utils": {
|
"@material-ui/utils": {
|
||||||
"version": "3.0.0-alpha.2",
|
"version": "3.0.0-alpha.2",
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.2.tgz",
|
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.2.tgz",
|
||||||
@@ -129,10 +142,21 @@
|
|||||||
"version": "16.0.11",
|
"version": "16.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.11.tgz",
|
||||||
"integrity": "sha512-x6zUx9/42B5Kl2Vl9HlopV8JF64wLpX3c+Pst9kc1HgzrsH+mkehe/zmHMQTplIrR48H2gpU7ZqurQolYu8XBA==",
|
"integrity": "sha512-x6zUx9/42B5Kl2Vl9HlopV8JF64wLpX3c+Pst9kc1HgzrsH+mkehe/zmHMQTplIrR48H2gpU7ZqurQolYu8XBA==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-redux": {
|
||||||
|
"version": "6.0.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-6.0.12.tgz",
|
||||||
|
"integrity": "sha512-fvcpm7cfW/JMflRdZgegCVbSGYt/hyEWQKriesaLZDRDjBGKQsAiui08VCQg5lBpocPmulVGKFhICtOAcMUPOQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*",
|
||||||
|
"redux": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-transition-group": {
|
"@types/react-transition-group": {
|
||||||
"version": "2.0.15",
|
"version": "2.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.15.tgz",
|
||||||
@@ -2892,6 +2916,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
|
||||||
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw=="
|
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw=="
|
||||||
},
|
},
|
||||||
|
"invariant": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||||
|
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"invert-kv": {
|
"invert-kv": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
||||||
@@ -4202,6 +4235,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||||
},
|
},
|
||||||
|
"react-redux": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-EmbC3uLl60pw2VqSSkj6HpZ6jTk12RMrwXMBdYtM6niq0MdEaRq9KYCwpJflkOZj349BLGQm1MI/JO1W96kLWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.2.0",
|
||||||
|
"hoist-non-react-statics": "^3.2.1",
|
||||||
|
"invariant": "^2.2.4",
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
|
"react-is": "^16.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-textarea-autosize": {
|
"react-textarea-autosize": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz",
|
"resolved": "http://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-6.1.0.tgz",
|
||||||
@@ -4265,6 +4312,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redux": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"symbol-observable": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.12.1",
|
"version": "0.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
|
||||||
|
|||||||
@@ -11,13 +11,18 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@material-ui/icons": "^3.0.1",
|
"@material-ui/icons": "^3.0.1",
|
||||||
|
"@material-ui/lab": "^3.0.0-alpha.27",
|
||||||
|
"@types/react": "^16.7.18",
|
||||||
|
"@types/react-dom": "^16.0.11",
|
||||||
|
"@types/react-redux": "^6.0.12",
|
||||||
|
"react-redux": "^6.0.0",
|
||||||
|
"react-transition-group": "^2.5.2",
|
||||||
|
"redux": "^4.0.1",
|
||||||
"webpack-livereload-plugin": "^2.2.0"
|
"webpack-livereload-plugin": "^2.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/core": "^3.7.1",
|
"@material-ui/core": "^3.7.1",
|
||||||
"@types/node": "^10.12.18",
|
"@types/node": "^10.12.18",
|
||||||
"@types/react": "^16.7.18",
|
|
||||||
"@types/react-dom": "^16.0.11",
|
|
||||||
"@types/sha1": "^1.1.1",
|
"@types/sha1": "^1.1.1",
|
||||||
"@types/socket.io-client": "^1.4.32",
|
"@types/socket.io-client": "^1.4.32",
|
||||||
"@types/vis": "^4.21.9",
|
"@types/vis": "^4.21.9",
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { AppState } from './reducers'
|
||||||
|
|
||||||
|
import { withStyles, Theme } from '@material-ui/core/styles'
|
||||||
|
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||||
|
|
||||||
import * as q from '../../backend/src/Model'
|
import * as q from '../../backend/src/Model'
|
||||||
|
|
||||||
import { Tree } from './components/Tree/Tree'
|
import Tree from './components/Tree/Tree'
|
||||||
import TitleBar from './components/TitleBar'
|
import TitleBar from './components/TitleBar'
|
||||||
import Sidebar from './components/Sidebar/Sidebar'
|
import Sidebar from './components/Sidebar/Sidebar'
|
||||||
import Connection from './components/ConnectionSetup/Connection'
|
import Connection from './components/ConnectionSetup/Connection'
|
||||||
// import { default as EventBus } from '../../events'
|
import Settings from './components/Settings'
|
||||||
|
|
||||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
selectedNode?: q.TreeNode,
|
selectedNode?: q.TreeNode,
|
||||||
@@ -17,6 +21,7 @@ interface State {
|
|||||||
interface Props {
|
interface Props {
|
||||||
name: string
|
name: string
|
||||||
theme: Theme
|
theme: Theme
|
||||||
|
settingsVisible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class App extends React.Component<Props, State> {
|
class App extends React.Component<Props, State> {
|
||||||
@@ -29,33 +34,60 @@ class App extends React.Component<Props, State> {
|
|||||||
|
|
||||||
private getStyles(): {[s: string]: React.CSSProperties} {
|
private getStyles(): {[s: string]: React.CSSProperties} {
|
||||||
const { theme } = this.props
|
const { theme } = this.props
|
||||||
|
const drawerWidth = 300
|
||||||
return {
|
return {
|
||||||
left: {
|
left: {
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
color: theme.palette.text.primary,
|
color: theme.palette.text.primary,
|
||||||
height: 'calc(100vh - 64px)',
|
height: 'calc(100vh - 64px)',
|
||||||
float: 'left',
|
float: 'left',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
display: 'block',
|
||||||
width: '60vw',
|
width: '60vw',
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
height: 'calc(100vh - 64px)',
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
float: 'left',
|
||||||
|
width: '40vw',
|
||||||
overflowY: 'scroll',
|
overflowY: 'scroll',
|
||||||
overflowX: 'hidden',
|
overflowX: 'hidden',
|
||||||
display: 'block',
|
display: 'block',
|
||||||
},
|
},
|
||||||
right: {
|
centerContent: {
|
||||||
height: 'calc(100vh - 64px)',
|
width: '100vw',
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
content: {
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
color: theme.palette.text.primary,
|
transition: theme.transitions.create('margin', {
|
||||||
float: 'right', width: '40vw',
|
easing: theme.transitions.easing.sharp,
|
||||||
overflowY: 'scroll',
|
duration: theme.transitions.duration.leavingScreen,
|
||||||
overflowX: 'hidden',
|
}),
|
||||||
display: 'block',
|
marginLeft: 0,
|
||||||
|
},
|
||||||
|
contentShift: {
|
||||||
|
padding: 0,
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
transition: theme.transitions.create('margin', {
|
||||||
|
easing: theme.transitions.easing.easeOut,
|
||||||
|
duration: theme.transitions.duration.enteringScreen,
|
||||||
|
}),
|
||||||
|
marginLeft: drawerWidth,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return <div>
|
const { settingsVisible } = this.props
|
||||||
|
const { content, contentShift, settings, centerContent } = this.getStyles()
|
||||||
|
return <div style={centerContent}>
|
||||||
|
<CssBaseline />
|
||||||
|
<Settings />
|
||||||
|
<div style={settingsVisible ? contentShift : content}>
|
||||||
<TitleBar />
|
<TitleBar />
|
||||||
<div>
|
<div style={centerContent}>
|
||||||
<div style={this.getStyles().left}>
|
<div style={this.getStyles().left}>
|
||||||
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
<Tree connectionId={this.state.connectionId} didSelectNode={(node: q.TreeNode) => {
|
||||||
this.setState({ selectedNode: node })
|
this.setState({ selectedNode: node })
|
||||||
@@ -65,9 +97,16 @@ class App extends React.Component<Props, State> {
|
|||||||
<Sidebar node={this.state.selectedNode} />
|
<Sidebar node={this.state.selectedNode} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
<Connection onConnection={(connectionId: string) => this.setState({ connectionId })}/>
|
||||||
</div >
|
</div >
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme()(App)
|
const mapStateToProps = (state: AppState) => {
|
||||||
|
return {
|
||||||
|
settingsVisible: state.settings.visible,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles({}, { withTheme: true })(connect(mapStateToProps)(App))
|
||||||
|
|||||||
15
app/src/actions/Settings.ts
Normal file
15
app/src/actions/Settings.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { Action } from 'redux'
|
||||||
|
import { ActionTypes } from '../reducers'
|
||||||
|
|
||||||
|
export const setAutoExpandLimit = (autoExpandLimit: number = 0) => {
|
||||||
|
return {
|
||||||
|
autoExpandLimit,
|
||||||
|
type: ActionTypes.setAutoExpandLimit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toggleSettingsVisibility = () => {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.toggleSettingsVisibility,
|
||||||
|
}
|
||||||
|
}
|
||||||
3
app/src/actions/index.ts
Normal file
3
app/src/actions/index.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import * as settingsActions from './Settings'
|
||||||
|
|
||||||
|
export { settingsActions }
|
||||||
@@ -85,6 +85,7 @@ class Connection extends React.Component<Props, State> {
|
|||||||
this.props.onConnection(connectionId)
|
this.props.onConnection(connectionId)
|
||||||
this.setState({ visible: false })
|
this.setState({ visible: false })
|
||||||
} else if (state.error) {
|
} else if (state.error) {
|
||||||
|
console.log('error', state.error)
|
||||||
this.setState({ error: state.error })
|
this.setState({ error: state.error })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
121
app/src/components/Settings.tsx
Normal file
121
app/src/components/Settings.tsx
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import * as q from '../../../backend/src/Model'
|
||||||
|
|
||||||
|
import Drawer from '@material-ui/core/Drawer'
|
||||||
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
|
import Paper from '@material-ui/core/Paper'
|
||||||
|
import Divider from '@material-ui/core/Divider'
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem'
|
||||||
|
import Select from '@material-ui/core/Select'
|
||||||
|
|
||||||
|
import ChevronRight from '@material-ui/icons/ChevronRight'
|
||||||
|
|
||||||
|
import { Typography, InputBase, Input, InputLabel } from '@material-ui/core'
|
||||||
|
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
import { settingsActions } from '../actions'
|
||||||
|
import { AppState } from '../reducers'
|
||||||
|
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
|
||||||
|
const styles: StyleRulesCallback = theme => ({
|
||||||
|
drawer: {
|
||||||
|
backgroundColor: theme.palette.background.default,
|
||||||
|
flexShrink: 0,
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
width: '300px',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
paddingTop: `${theme.spacing.unit}px`,
|
||||||
|
...theme.mixins.toolbar,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
margin: `auto ${theme.spacing.unit}px auto ${theme.spacing.unit}px`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
actions?: any
|
||||||
|
autoExpandLimit: number,
|
||||||
|
visible: boolean,
|
||||||
|
store?: any,
|
||||||
|
classes: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Settings extends React.Component<Props, State> {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props)
|
||||||
|
this.state = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { classes, actions, visible } = this.props
|
||||||
|
return <Drawer
|
||||||
|
anchor = "left"
|
||||||
|
className = { classes.drawer }
|
||||||
|
open = { visible }
|
||||||
|
variant = "persistent"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className = { classes.paper }
|
||||||
|
tabIndex = { 0 }
|
||||||
|
role = "button"
|
||||||
|
onClick = {(e: React.MouseEvent) => e.stopPropagation()}
|
||||||
|
onKeyDown = {(e: React.KeyboardEvent) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
|
||||||
|
<Typography className = { classes.title } variant = "h6" color = "inherit">
|
||||||
|
<IconButton onClick = {actions.toggleSettingsVisibility}>
|
||||||
|
<ChevronRight />
|
||||||
|
</IconButton>
|
||||||
|
Settings
|
||||||
|
</Typography>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{this.renderAutoExpand()}
|
||||||
|
</div>
|
||||||
|
</Drawer>
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderAutoExpand() {
|
||||||
|
const { classes, actions, autoExpandLimit } = this.props
|
||||||
|
|
||||||
|
return <span>
|
||||||
|
<InputLabel htmlFor="auto-expand">Auto Expand</InputLabel>
|
||||||
|
<Select
|
||||||
|
value = { autoExpandLimit }
|
||||||
|
onChange = { (e: React.ChangeEvent<HTMLSelectElement>) => actions.setAutoExpandLimit(e.target.value) }
|
||||||
|
input = {<Input name="auto-expand" id="auto-expand-label-placeholder" />}
|
||||||
|
displayEmpty
|
||||||
|
name = "auto-expand"
|
||||||
|
className = {classes.input}
|
||||||
|
>
|
||||||
|
<MenuItem value = {0}><em>Disabled</em></MenuItem>
|
||||||
|
<MenuItem value = {3}>Some</MenuItem>
|
||||||
|
<MenuItem value = {10}>Most</MenuItem>
|
||||||
|
<MenuItem value = {1E6}>All</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: AppState) => {
|
||||||
|
return {
|
||||||
|
autoExpandLimit: state.settings.autoExpandLimit,
|
||||||
|
visible: state.settings.visible,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
|
return {
|
||||||
|
actions: bindActionCreators(settingsActions, dispatch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(connect(mapStateToProps, mapDispatchToProps)(Settings))
|
||||||
@@ -13,13 +13,13 @@ import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
|||||||
import Copy from '../Copy'
|
import Copy from '../Copy'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: q.TreeNode | undefined,
|
node?: q.TreeNode,
|
||||||
classes: any,
|
classes: any,
|
||||||
theme: Theme
|
theme: Theme,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
node?: q.TreeNode | undefined
|
node?: q.TreeNode
|
||||||
}
|
}
|
||||||
|
|
||||||
class Sidebar extends React.Component<Props, State> {
|
class Sidebar extends React.Component<Props, State> {
|
||||||
|
|||||||
@@ -2,6 +2,22 @@ import * as React from 'react'
|
|||||||
import * as q from '../../../backend/src/Model'
|
import * as q from '../../../backend/src/Model'
|
||||||
|
|
||||||
import Search from '@material-ui/icons/Search'
|
import Search from '@material-ui/icons/Search'
|
||||||
|
import Drawer from '@material-ui/core/Drawer'
|
||||||
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
|
import Menu from '@material-ui/icons/Menu'
|
||||||
|
|
||||||
|
import List from '@material-ui/core/List'
|
||||||
|
import Divider from '@material-ui/core/Divider'
|
||||||
|
import ListItem from '@material-ui/core/ListItem'
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||||
|
import ListItemText from '@material-ui/core/ListItemText'
|
||||||
|
import Slider from '@material-ui/lab/Slider'
|
||||||
|
|
||||||
|
import { settingsActions } from '../actions'
|
||||||
|
import { AppState, SettingsModel } from '../reducers'
|
||||||
|
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
|
||||||
import { AppBar, Toolbar, Typography, InputBase } from '@material-ui/core'
|
import { AppBar, Toolbar, Typography, InputBase } from '@material-ui/core'
|
||||||
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles'
|
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles'
|
||||||
@@ -53,17 +69,30 @@ const styles: StyleRulesCallback = theme => ({
|
|||||||
width: 200,
|
width: 200,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
menuButton: {
|
||||||
|
marginLeft: -12,
|
||||||
|
marginRight: 20,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
classes: any
|
classes: any
|
||||||
|
actions: any
|
||||||
}
|
}
|
||||||
|
|
||||||
class TitleBar extends React.Component<Props, {}> {
|
interface State {
|
||||||
|
selectedNode?: q.TreeNode
|
||||||
|
settingsVisible: boolean
|
||||||
|
autoExpandLimit: number
|
||||||
|
}
|
||||||
|
|
||||||
|
class TitleBar extends React.Component<Props, State> {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
selectedNode: undefined,
|
selectedNode: undefined,
|
||||||
|
settingsVisible: false,
|
||||||
|
autoExpandLimit: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +101,9 @@ class TitleBar extends React.Component<Props, {}> {
|
|||||||
|
|
||||||
return <AppBar position="static">
|
return <AppBar position="static">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.props.actions.toggleSettingsVisibility}>
|
||||||
|
<Menu />
|
||||||
|
</IconButton>
|
||||||
<Typography className={classes.title} variant="h6" color="inherit">MQTT-Xplorer</Typography>
|
<Typography className={classes.title} variant="h6" color="inherit">MQTT-Xplorer</Typography>
|
||||||
<div className={classes.search}>
|
<div className={classes.search}>
|
||||||
<div className={classes.searchIcon}>
|
<div className={classes.searchIcon}>
|
||||||
@@ -90,4 +122,10 @@ class TitleBar extends React.Component<Props, {}> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withStyles(styles)(TitleBar)
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
|
return {
|
||||||
|
actions: bindActionCreators(settingsActions, dispatch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(connect(null, mapDispatchToProps)(TitleBar))
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { Typography } from '@material-ui/core'
|
|||||||
import { makeConnectionMessageEvent, rendererEvents } from '../../../../events'
|
import { makeConnectionMessageEvent, rendererEvents } from '../../../../events'
|
||||||
import { } from '../../../../events/Events'
|
import { } from '../../../../events/Events'
|
||||||
const MovingAvaerage = require('moving-average')
|
const MovingAvaerage = require('moving-average')
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { AppState } from '../../reducers'
|
||||||
|
|
||||||
declare const performance: any
|
declare const performance: any
|
||||||
|
|
||||||
@@ -12,6 +14,7 @@ const timeInterval = 10 * 1000
|
|||||||
const average = MovingAvaerage(timeInterval)
|
const average = MovingAvaerage(timeInterval)
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
autoExpandLimit: number
|
||||||
didSelectNode?: (node: q.TreeNode) => void
|
didSelectNode?: (node: q.TreeNode) => void
|
||||||
connectionId?: string
|
connectionId?: string
|
||||||
}
|
}
|
||||||
@@ -21,7 +24,7 @@ interface TreeState {
|
|||||||
msg: any
|
msg: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Tree extends React.Component<Props, TreeState> {
|
class Tree extends React.Component<Props, TreeState> {
|
||||||
private renderDuration: number = 300
|
private renderDuration: number = 300
|
||||||
private updateTimer?: any
|
private updateTimer?: any
|
||||||
private lastUpdate: number = 0
|
private lastUpdate: number = 0
|
||||||
@@ -99,11 +102,12 @@ export class Tree extends React.Component<Props, TreeState> {
|
|||||||
return <Typography style={ style }>
|
return <Typography style={ style }>
|
||||||
<TreeNode
|
<TreeNode
|
||||||
animateChages = { true }
|
animateChages = { true }
|
||||||
autoExpandLimit={3000}
|
autoExpandLimit = { this.props.autoExpandLimit }
|
||||||
isRoot = { true }
|
isRoot = { true }
|
||||||
didSelectNode = { this.props.didSelectNode }
|
didSelectNode = { this.props.didSelectNode }
|
||||||
treeNode = { this.state.tree }
|
treeNode = { this.state.tree }
|
||||||
name="/" collapsed={false}
|
name = "/"
|
||||||
|
collapsed = { false }
|
||||||
key="rootNode"
|
key="rootNode"
|
||||||
performanceCallback={(ms: number) => {
|
performanceCallback={(ms: number) => {
|
||||||
average.push(Date.now(), ms)
|
average.push(Date.now(), ms)
|
||||||
@@ -113,3 +117,11 @@ export class Tree extends React.Component<Props, TreeState> {
|
|||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: AppState) => {
|
||||||
|
return {
|
||||||
|
autoExpandLimit: state.settings.autoExpandLimit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(Tree)
|
||||||
|
|||||||
@@ -1,13 +1,33 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as q from '../../../../backend/src/Model'
|
import * as q from '../../../../backend/src/Model'
|
||||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
import { withStyles, Theme } from '@material-ui/core/styles'
|
||||||
import { isElementInViewport } from '../helper/isElementInViewport'
|
import { isElementInViewport } from '../helper/isElementInViewport'
|
||||||
import TreeNodeTitle from './TreeNodeTitle'
|
import TreeNodeTitle from './TreeNodeTitle'
|
||||||
import TreeNodeSubnodes from './TreeNodeSubnodes'
|
import TreeNodeSubnodes from './TreeNodeSubnodes'
|
||||||
|
|
||||||
declare var performance: any
|
declare var performance: any
|
||||||
|
|
||||||
export interface TreeNodeProps {
|
const styles = (theme: Theme) => {
|
||||||
|
return {
|
||||||
|
collapsedSubnodes: {
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
},
|
||||||
|
displayBlock: {
|
||||||
|
display: 'block',
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
display: 'block',
|
||||||
|
marginLeft: '10px',
|
||||||
|
},
|
||||||
|
hover: {
|
||||||
|
'&:hover': {
|
||||||
|
backgroundColor: 'rgba(80, 80, 80, 0.35)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
animateChages: boolean
|
animateChages: boolean
|
||||||
isRoot?: boolean
|
isRoot?: boolean
|
||||||
treeNode: q.TreeNode
|
treeNode: q.TreeNode
|
||||||
@@ -15,20 +35,16 @@ export interface TreeNodeProps {
|
|||||||
collapsed?: boolean | undefined
|
collapsed?: boolean | undefined
|
||||||
performanceCallback?: ((ms: number) => void) | undefined
|
performanceCallback?: ((ms: number) => void) | undefined
|
||||||
didSelectNode?: (node: q.TreeNode) => void
|
didSelectNode?: (node: q.TreeNode) => void
|
||||||
theme: Theme
|
classes: any
|
||||||
autoExpandLimit: number
|
autoExpandLimit: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TreeNodeState {
|
interface State {
|
||||||
title: string | undefined
|
|
||||||
collapsed: boolean
|
|
||||||
collapsedOverride: boolean | undefined
|
collapsedOverride: boolean | undefined
|
||||||
edgeCount: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
|
class TreeNode extends React.Component<Props, State> {
|
||||||
private dirtySubnodes: boolean = true
|
private dirtySubnodes: boolean = true
|
||||||
private dirtyState: boolean = true
|
|
||||||
private dirtyEdges: boolean = true
|
private dirtyEdges: boolean = true
|
||||||
private dirtyMessage: boolean = true
|
private dirtyMessage: boolean = true
|
||||||
|
|
||||||
@@ -49,11 +65,12 @@ class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
|
|||||||
this.dirtyMessage = true
|
this.dirtyMessage = true
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: TreeNodeProps) {
|
constructor(props: Props) {
|
||||||
super(props)
|
super(props)
|
||||||
const edgeCount = Object.keys(props.treeNode.edges).length
|
|
||||||
const collapsed = edgeCount > this.props.autoExpandLimit
|
this.state = {
|
||||||
this.state = { collapsed, edgeCount, collapsedOverride: props.collapsed, title: props.name }
|
collapsedOverride: props.collapsed,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
@@ -70,32 +87,18 @@ class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
|
|||||||
treeNode.onMessage.unsubscribe(this.messageDidChange)
|
treeNode.onMessage.unsubscribe(this.messageDidChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
private getStyles() {
|
private stateHasChanged(newState: State) {
|
||||||
return {
|
return this.state.collapsedOverride !== newState.collapsedOverride
|
||||||
collapsedSubnodes: {
|
|
||||||
color: this.props.theme.palette.text.secondary,
|
|
||||||
},
|
|
||||||
displayBlock: {
|
|
||||||
display: 'block',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public setState(newState: any) {
|
private propsHasChanged(newProps: Props) {
|
||||||
this.dirtyState = this.stateHasChanged(newState)
|
return this.props.autoExpandLimit !== newProps.autoExpandLimit
|
||||||
|
|
||||||
super.setState(newState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private stateHasChanged(newState: any) {
|
public shouldComponentUpdate(nextProps: Props, nextState: State) {
|
||||||
return this.state.collapsed !== newState.collapsed
|
|
||||||
|| this.state.collapsedOverride !== newState.collapsedOverride
|
|
||||||
|| this.state.edgeCount !== newState.edgeCount
|
|
||||||
}
|
|
||||||
|
|
||||||
public shouldComponentUpdate() {
|
|
||||||
const shouldRenderToRemoveCssAnimation = this.cssAnimationWasSetAt !== undefined
|
const shouldRenderToRemoveCssAnimation = this.cssAnimationWasSetAt !== undefined
|
||||||
return this.dirtyState
|
return this.stateHasChanged(nextState)
|
||||||
|
|| this.propsHasChanged(nextProps)
|
||||||
|| this.dirtyEdges
|
|| this.dirtyEdges
|
||||||
|| this.dirtyMessage
|
|| this.dirtyMessage
|
||||||
|| this.dirtySubnodes
|
|| this.dirtySubnodes
|
||||||
@@ -124,25 +127,26 @@ class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
|
|||||||
return this.state.collapsedOverride
|
return this.state.collapsedOverride
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.state.collapsed
|
return this.props.treeNode.edgeCount() > this.props.autoExpandLimit
|
||||||
}
|
|
||||||
|
|
||||||
public componentWillReceiveProps() {
|
|
||||||
const edgeCount = Object.keys(this.props.treeNode.edges).length
|
|
||||||
this.setState({ edgeCount, collapsed: edgeCount > this.props.autoExpandLimit })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const { displayBlock } = this.getStyles()
|
|
||||||
const animationStyle = this.indicatingChangeAnimationStyle()
|
const animationStyle = this.indicatingChangeAnimationStyle()
|
||||||
|
const { classes } = this.props
|
||||||
|
this.dirtyEdges = this.dirtyMessage = this.dirtySubnodes = false
|
||||||
|
|
||||||
this.dirtyState = this.dirtyEdges = this.dirtyMessage = this.dirtySubnodes = false
|
return <div
|
||||||
|
key={this.props.treeNode.hash()}
|
||||||
return <div key={this.props.treeNode.hash()} style={ { display: 'block', marginLeft: '10px' } }>
|
className={`${classes.node} ${!this.props.isRoot ? classes.hover : ''}`}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
this.toggle()
|
||||||
|
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<span ref={this.titleRef} style={animationStyle}>
|
<span ref={this.titleRef} style={animationStyle}>
|
||||||
<TreeNodeTitle
|
<TreeNodeTitle
|
||||||
onClick={() => this.toggle()}
|
onClick={() => this.toggle()}
|
||||||
edgeCount={this.state.edgeCount}
|
|
||||||
collapsed={this.collapsed()}
|
collapsed={this.collapsed()}
|
||||||
treeNode={this.props.treeNode}
|
treeNode={this.props.treeNode}
|
||||||
name={this.props.name}
|
name={this.props.name}
|
||||||
@@ -186,4 +190,4 @@ class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme()(TreeNode)
|
export default withStyles(styles)(TreeNode)
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as q from '../../../../backend/src/Model'
|
import * as q from '../../../../backend/src/Model'
|
||||||
import { Typography } from '@material-ui/core'
|
|
||||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
import { withTheme, Theme } from '@material-ui/core/styles'
|
||||||
|
|
||||||
export interface TreeNodeProps extends React.HTMLAttributes<HTMLElement> {
|
export interface TreeNodeProps extends React.HTMLAttributes<HTMLElement> {
|
||||||
treeNode: q.TreeNode
|
treeNode: q.TreeNode
|
||||||
// ref: React.Ref<HTMLElement>
|
|
||||||
name?: string | undefined
|
name?: string | undefined
|
||||||
collapsed?: boolean | undefined
|
collapsed?: boolean | undefined
|
||||||
toggleCollapsed: () => void
|
toggleCollapsed: () => void
|
||||||
didSelectNode?: (node: q.TreeNode) => void
|
didSelectNode?: (node: q.TreeNode) => void
|
||||||
edgeCount: number
|
|
||||||
theme: Theme
|
theme: Theme
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +78,7 @@ class TreeNodeTitle extends React.Component<TreeNodeProps, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderExpander() {
|
private renderExpander() {
|
||||||
if (this.props.edgeCount === 0) {
|
if (this.props.treeNode.edgeCount() === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +86,7 @@ class TreeNodeTitle extends React.Component<TreeNodeProps, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderCollapsedSubnodes() {
|
private renderCollapsedSubnodes() {
|
||||||
if (this.props.edgeCount === 0 || !this.props.collapsed) {
|
if (this.props.treeNode.edgeCount() === 0 || !this.props.collapsed) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as ReactDOM from 'react-dom'
|
import * as ReactDOM from 'react-dom'
|
||||||
|
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import { createStore } from 'redux'
|
||||||
|
import reducers, { AppState } from './reducers'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
|
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
|
||||||
|
|
||||||
@@ -12,10 +15,23 @@ const theme = createMuiTheme({
|
|||||||
})
|
})
|
||||||
|
|
||||||
declare var document: any
|
declare var document: any
|
||||||
|
declare var window: any
|
||||||
|
|
||||||
|
const initialAppState = {
|
||||||
|
settings: {
|
||||||
|
autoExpandLimit: 0,
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = createStore(reducers, initialAppState)
|
||||||
|
window.reduxStore = store
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<MuiThemeProvider theme={theme}>
|
<MuiThemeProvider theme={theme}>
|
||||||
<App />
|
<Provider store={store}>
|
||||||
|
<App name="" />
|
||||||
|
</Provider>
|
||||||
</MuiThemeProvider>,
|
</MuiThemeProvider>,
|
||||||
document.getElementById('example'),
|
document.getElementById('example'),
|
||||||
)
|
)
|
||||||
|
|||||||
50
app/src/reducers/index.ts
Normal file
50
app/src/reducers/index.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { Reducer, Action } from 'redux'
|
||||||
|
|
||||||
|
export enum ActionTypes {
|
||||||
|
setAutoExpandLimit = 'SET_AUTO_EXPAND_LIMIT',
|
||||||
|
toggleSettingsVisibility = 'TOGGLE_SETTINGS_VISIBILITY',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SettingsAction extends Action {
|
||||||
|
type: ActionTypes,
|
||||||
|
autoExpandLimit: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AppState {
|
||||||
|
settings: SettingsModel
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SettingsModel {
|
||||||
|
autoExpandLimit: number
|
||||||
|
visible: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const reducer: Reducer<AppState | undefined, SettingsAction> = (state, action) => {
|
||||||
|
if (!state) {
|
||||||
|
throw Error('No initial state')
|
||||||
|
}
|
||||||
|
console.log(action)
|
||||||
|
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionTypes.setAutoExpandLimit:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
settings: {
|
||||||
|
visible: state.settings.visible,
|
||||||
|
autoExpandLimit: action.autoExpandLimit,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case ActionTypes.toggleSettingsVisibility:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
settings: {
|
||||||
|
visible: !state.settings.visible,
|
||||||
|
autoExpandLimit: state.settings.autoExpandLimit,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default reducer
|
||||||
@@ -34,25 +34,5 @@
|
|||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"instrument": true
|
"instrument": true
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"mqtt": "^2.18.8",
|
|
||||||
"sha1": "^1.1.1",
|
|
||||||
"socket.io": "^2.2.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/chai": "^4.1.7",
|
|
||||||
"@types/mocha": "^5.2.5",
|
|
||||||
"@types/node": "^10.12.18",
|
|
||||||
"@types/sha1": "^1.1.1",
|
|
||||||
"@types/socket.io": "^2.1.2",
|
|
||||||
"chai": "^4.2.0",
|
|
||||||
"mocha": "^5.2.0",
|
|
||||||
"nyc": "^13.1.0",
|
|
||||||
"source-map-support": "^0.5.9",
|
|
||||||
"ts-node": "^7.0.1",
|
|
||||||
"tslint": "^5.12.0",
|
|
||||||
"tslint-strict-null-checks": "^1.0.1",
|
|
||||||
"typescript": "^3.2.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ export class TreeNode {
|
|||||||
return this.leafes().length
|
return this.leafes().length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public edgeCount(): number {
|
||||||
|
return Object.values(this.edges).length
|
||||||
|
}
|
||||||
|
|
||||||
public leafes(): TreeNode[] {
|
public leafes(): TreeNode[] {
|
||||||
if (this.cachedLeafes === undefined) {
|
if (this.cachedLeafes === undefined) {
|
||||||
if (Object.values(this.edges).length === 0) {
|
if (Object.values(this.edges).length === 0) {
|
||||||
|
|||||||
9
build.ts
9
build.ts
@@ -6,7 +6,7 @@ const linux: builder.CliOptions = {
|
|||||||
armv7l: true,
|
armv7l: true,
|
||||||
arm64: true,
|
arm64: true,
|
||||||
linux: ['snap', 'AppImage', 'deb', 'pacman'],
|
linux: ['snap', 'AppImage', 'deb', 'pacman'],
|
||||||
prepackaged: './build/topackage',
|
projectDir: './build/clean',
|
||||||
}
|
}
|
||||||
|
|
||||||
const win: builder.CliOptions = {
|
const win: builder.CliOptions = {
|
||||||
@@ -15,7 +15,7 @@ const win: builder.CliOptions = {
|
|||||||
armv7l: false,
|
armv7l: false,
|
||||||
arm64: false,
|
arm64: false,
|
||||||
win: ['portable'],
|
win: ['portable'],
|
||||||
prepackaged: './build/topackage',
|
projectDir: './build/clean',
|
||||||
}
|
}
|
||||||
|
|
||||||
const mac: builder.CliOptions = {
|
const mac: builder.CliOptions = {
|
||||||
@@ -24,12 +24,13 @@ const mac: builder.CliOptions = {
|
|||||||
armv7l: false,
|
armv7l: false,
|
||||||
arm64: false,
|
arm64: false,
|
||||||
mac: ['dmg'],
|
mac: ['dmg'],
|
||||||
|
projectDir: './build/clean',
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAll() {
|
async function buildAll() {
|
||||||
await builder.build(linux)
|
// await builder.build(linux)
|
||||||
await builder.build(mac)
|
await builder.build(mac)
|
||||||
await builder.build(win)
|
// await builder.build(win)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildAll()
|
buildAll()
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ require('./backend/build/backend/src/index.js')
|
|||||||
let mainWindow
|
let mainWindow
|
||||||
|
|
||||||
function createWindow () {
|
function createWindow () {
|
||||||
|
BrowserWindow.addDevToolsExtension ('/Users/thomas/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/3.5.0_0');
|
||||||
|
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({
|
||||||
width: 1024,
|
width: 1024,
|
||||||
|
|||||||
2206
package-lock.json
generated
2206
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -11,9 +11,14 @@
|
|||||||
"release": "npm run test && ./release.sh"
|
"release": "npm run test && ./release.sh"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "mq-explorer",
|
"appId": "mqtt-explorer",
|
||||||
"mac": {
|
"mac": {
|
||||||
"category": "de.t7n.apps.mq-explorer"
|
"category": "de.t7n.apps.mq-explorer",
|
||||||
|
"files": [
|
||||||
|
"**/*",
|
||||||
|
"!**/*.ts",
|
||||||
|
"!app/node_modules"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"category": "Development",
|
"category": "Development",
|
||||||
@@ -36,11 +41,23 @@
|
|||||||
"tslint": "^5.12.0",
|
"tslint": "^5.12.0",
|
||||||
"tslint-config-airbnb": "^5.11.1",
|
"tslint-config-airbnb": "^5.11.1",
|
||||||
"tslint-react": "^3.6.0",
|
"tslint-react": "^3.6.0",
|
||||||
"typescript": "^3.2.2"
|
"typescript": "^3.2.2",
|
||||||
|
"@types/chai": "^4.1.7",
|
||||||
|
"@types/mocha": "^5.2.5",
|
||||||
|
"@types/node": "^10.12.18",
|
||||||
|
"@types/sha1": "^1.1.1",
|
||||||
|
"@types/socket.io": "^2.1.2",
|
||||||
|
"chai": "^4.2.0",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"nyc": "^13.1.0",
|
||||||
|
"source-map-support": "^0.5.9",
|
||||||
|
"tslint-strict-null-checks": "^1.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/electron": "^1.6.10",
|
"@types/electron": "^1.6.10",
|
||||||
"@types/socket.io": "^2.1.2",
|
"@types/socket.io": "^2.1.2",
|
||||||
"socket.io": "^2.2.0"
|
"socket.io": "^2.2.0",
|
||||||
|
"mqtt": "^2.18.8",
|
||||||
|
"sha1": "^1.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DIR=build/topackage
|
DIR=build/clean
|
||||||
|
|
||||||
rm -rf "$DIR"
|
rm -rf "$DIR"
|
||||||
mkdir -p "$DIR"
|
mkdir -p "$DIR"
|
||||||
@@ -14,6 +14,8 @@ npm run build
|
|||||||
rm -rf app/node_modules
|
rm -rf app/node_modules
|
||||||
cd "$ORIGINAL_DIR"
|
cd "$ORIGINAL_DIR"
|
||||||
|
|
||||||
|
node_modules/.bin/ts-node build.ts
|
||||||
|
exit 0
|
||||||
docker run --rm -ti \
|
docker run --rm -ti \
|
||||||
--env ELECTRON_CACHE="/root/.cache/electron" \
|
--env ELECTRON_CACHE="/root/.cache/electron" \
|
||||||
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
|
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
|
||||||
|
|||||||
Reference in New Issue
Block a user