Improve data model & fix tests

This commit is contained in:
Thomas Nordquist
2019-01-02 15:58:44 +01:00
parent 5697b2daea
commit 48aa317c7c
23 changed files with 335 additions and 152 deletions

41
app/package-lock.json generated
View File

@@ -46,6 +46,47 @@
"warning": "^4.0.1"
}
},
"@material-ui/icons": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-3.0.1.tgz",
"integrity": "sha512-1kNcxYiIT1x8iDPEAlgmKrfRTIV8UyK6fLVcZ9kMHIKGWft9I451V5mvSrbCjbf7MX1TbLWzZjph0aVCRf9MqQ==",
"dev": true,
"requires": {
"@babel/runtime": "7.0.0",
"recompose": "^0.29.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz",
"integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==",
"dev": true,
"requires": {
"regenerator-runtime": "^0.12.0"
}
},
"hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==",
"dev": true
},
"recompose": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/recompose/-/recompose-0.29.0.tgz",
"integrity": "sha512-J/qLXNU4W+AeHCDR70ajW8eMd1uroqZaECTj6qqDLPMILz3y0EzpYlvrnxKB9DnqcngWrtGwjXY9JeXaW9kS1A==",
"dev": true,
"requires": {
"@babel/runtime": "^7.0.0",
"change-emitter": "^0.1.2",
"fbjs": "^0.8.1",
"hoist-non-react-statics": "^2.3.1",
"react-lifecycles-compat": "^3.0.2",
"symbol-observable": "^1.0.4"
}
}
}
},
"@material-ui/utils": {
"version": "3.0.0-alpha.2",
"resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.2.tgz",

View File

@@ -9,7 +9,9 @@
},
"author": "",
"license": "ISC",
"devDependencies": {},
"devDependencies": {
"@material-ui/icons": "^3.0.1"
},
"dependencies": {
"@types/node": "^10.12.18",
"awesome-typescript-loader": "^5.2.1",

View File

@@ -1,37 +1,55 @@
import * as React from "react";
import * as q from '../../backend/src/Model'
import { AppBar, Toolbar, Typography, InputBase } from '@material-ui/core';
import { Tree } from "./components/Tree";
import { Tree } from "./components/Tree"
import TitleBar from "./components/TitleBar";
import { Sidebar } from "./components/Sidebar";
import { withStyles } from '@material-ui/core/styles';
import { withTheme, Theme } from '@material-ui/core/styles';
class State {
public selectedNode?: q.TreeNode | undefined
}
export class App extends React.Component<{}, State> {
interface Props {
theme: Theme
}
class App extends React.Component<Props, State> {
constructor(props: any) {
super(props);
this.state = {
selectedNode: undefined
}
console.log("asd", this.props)
this.theme = this.props.theme
this.styles = {
primaryText: {
backgroundColor: this.theme.palette.background.default,
padding: `${this.theme.spacing.unit}px ${this.theme.spacing.unit * 2}px`,
color: this.theme.palette.text.primary,
},
primaryColor: {
backgroundColor: this.theme.palette.background.default,
//padding: `${this.theme.spacing.unit}px ${this.theme.spacing.unit * 2}px`,
color: this.theme.palette.common.white,
},
}
}
private theme: Theme
private styles: any
public render() {
return <div>
<AppBar>
<Toolbar>
<Typography variant="h6" color="inherit">MQTT-Xplorer</Typography>
</Toolbar>
<InputBase />
</AppBar>
return <div style={this.styles.primaryColor}>
<TitleBar />
<Tree didSelectNode={(node: q.TreeNode) => {
this.setState({selectedNode: node})
console.log('did select', node)
}}/>
// <Sidebar node={this.state.selectedNode} />
}} />
</div>
}
}
export default withTheme()(App)

View File

@@ -27,12 +27,6 @@ export class Sidebar extends React.Component<Props, State> {
}
}
private getStyle(): {[s: string]: any} {
return {
marginTop: '64px'
}
}
public componentWillReceiveProps(nextProps: Props) {
this.props.node && this.props.node.removeListener('update', this.updateNode)
nextProps.node && nextProps.node.on('update', this.updateNode)
@@ -69,6 +63,4 @@ export class Sidebar extends React.Component<Props, State> {
</Paper>
</div>
}
}

View File

@@ -0,0 +1,93 @@
import * as React from "react";
import * as q from '../../../backend/src/Model'
import SearchIcon from '@material-ui/icons/Search';
import { AppBar, Toolbar, Typography, InputBase } from '@material-ui/core';
import { withStyles, StyleRulesCallback } from '@material-ui/core/styles';
import { fade } from '@material-ui/core/styles/colorManipulator';
const styles: StyleRulesCallback = (theme) => ({
title: {
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing.unit * 2,
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing.unit * 3,
width: 'auto',
},
},
searchIcon: {
width: theme.spacing.unit * 9,
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
width: '100%',
},
inputInput: {
paddingTop: theme.spacing.unit,
paddingRight: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
paddingLeft: theme.spacing.unit * 10,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: 200,
},
}
});
interface Props {
classes: any
}
class TitleBar extends React.Component<Props, {}> {
constructor(props: any) {
super(props);
this.state = {
selectedNode: undefined
}
}
public render() {
const { classes } = this.props;
return <AppBar position="static">
<Toolbar>
<Typography className={classes.title} variant="h6" color="inherit">MQTT-Xplorer</Typography>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="Search…"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
/>
</div>
</Toolbar>
</AppBar>
}
}
export default withStyles(styles)(TitleBar)

View File

@@ -52,21 +52,15 @@ export class Tree extends React.Component<TreeNodeProps, TreeState> {
this.socket.removeAllListeners()
}
private getStyle(): {[s: string]: any} {
return {
marginTop: '64px'
}
}
public render() {
return <div {...this.props}>
<List style={this.getStyle()}>
<TreeNode
didSelectNode={this.props.didSelectNode}
treeNode={this.state.tree}
name="/" collapsed={false}
performanceCallback={(ms) => this.renderDuration = ms}
/>
return <div>
<List>
<TreeNode
didSelectNode={this.props.didSelectNode}
treeNode={this.state.tree}
name="/" collapsed={false}
performanceCallback={(ms) => this.renderDuration = ms}
/>
</List>
</div>;
}

View File

@@ -1,5 +1,4 @@
import * as React from "react";
import * as io from 'socket.io-client';
import * as q from '../../../backend/src/Model'
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
@@ -82,7 +81,7 @@ export class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
if (edges.length > 0) {
const listItems = edges
.map(edge => edge.node)
.map(edge => edge.target)
.map(node => <ListItem style={listItemStyle} button key={node.hash()}>
<TreeNode didSelectNode={this.props.didSelectNode} treeNode={node} />
</ListItem>)
@@ -125,11 +124,11 @@ export class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
paddingLeft: '5px',
display: 'inline-block',
}
return this.props.treeNode.value
return this.props.treeNode.message
? <span
style={style}
onMouseOver={() => this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)}
> = {this.props.treeNode.value.toString()}</span>
> = {this.props.treeNode.message.toString()}</span>
: null
}
@@ -146,7 +145,6 @@ export class TreeNode extends React.Component<TreeNodeProps, TreeNodeState> {
public render() {
const nodeStyle: React.CSSProperties = {
//marginLeft: '10px',
display: 'block',
}

View File

@@ -32,21 +32,21 @@ export class ValueRenderer extends React.Component<Props, State> {
public render() {
let node = this.props.node
if (!node) {
if (!node || !node.message) {
return null
}
let json
try {
json = JSON.parse(node.value)
json = JSON.parse(node.message.value)
} catch(error) {
return this.renderRawValue(node.value)
return this.renderRawValue(node.message.value)
}
if (typeof json === 'string') {
return this.renderRawValue(node.value)
return this.renderRawValue(node.message.value)
} else if (typeof json === 'number') {
return this.renderRawValue(node.value)
return this.renderRawValue(node.message.value)
} else {
return <ReactJson src={json} />
}

View File

@@ -1,10 +1,21 @@
import * as React from "react";
import * as ReactDOM from "react-dom";
import { App } from './App'
import App from './App'
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
const theme = createMuiTheme({
palette: {
type: 'dark', // Switching the dark mode on is a single property value change.
},
typography: { useNextVariants: true },
});
declare var document: any
ReactDOM.render(
<App />,
<MuiThemeProvider theme={theme}>
<App />
</MuiThemeProvider>,
document.getElementById("example")
);