This commit is contained in:
Thomas Nordquist
2019-02-18 16:02:21 +01:00
parent 55fbc642c4
commit 55ea381b3b
8 changed files with 117 additions and 27 deletions

View File

@@ -2,6 +2,7 @@
[![Downloads](https://img.shields.io/github/release/thomasnordquist/mqtt-explorer.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer/releases) [![Downloads](https://img.shields.io/github/release/thomasnordquist/mqtt-explorer.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer/releases)
[![Downloads](https://img.shields.io/github/downloads/thomasnordquist/mqtt-explorer/total.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer/releases) [![Downloads](https://img.shields.io/github/downloads/thomasnordquist/mqtt-explorer/total.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer/releases)
[![Build_Status](https://travis-ci.org/thomasnordquist/MQTT-Explorer.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer) [![Build_Status](https://travis-ci.org/thomasnordquist/MQTT-Explorer.svg)](https://travis-ci.org/thomasnordquist/MQTT-Explorer)
![](https://img.shields.io/github/commits-since/thomasnordquist/mqtt-explorer/latest.svg?style=flat)
### Version {{ version }} ### Version {{ version }}

View File

@@ -31,7 +31,6 @@ class RemoteStorage implements PersistantStorage {
const ack = makeStorageAcknoledgementEvent(transactionId) const ack = makeStorageAcknoledgementEvent(transactionId)
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const callback = (msg: any) => { const callback = (msg: any) => {
console.log(msg)
if (msg && msg.error) { if (msg && msg.error) {
reject(msg.error) reject(msg.error)
} else { } else {
@@ -57,8 +56,6 @@ class RemoteStorage implements PersistantStorage {
const promise = new Promise<Model>((resolve, reject) => { const promise = new Promise<Model>((resolve, reject) => {
const callback = (msg: any) => { const callback = (msg: any) => {
console.log(msg)
if (msg.error) { if (msg.error) {
reject(msg.error) reject(msg.error)
} else { } else {

View File

@@ -1,21 +1,43 @@
import { Dispatch, Action } from 'redux' import { Dispatch, Action } from 'redux'
import { AppState } from '../reducers' import { AppState } from '../reducers'
import { makePublishEvent, rendererEvents } from '../../../events' import { makePublishEvent, rendererEvents } from '../../../events'
import * as q from '../../../backend/src/Model'
export const clearRetainedTopic = () => (dispatch: Dispatch<Action>, getState: () => AppState) => { export const clearRetainedTopic = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
const { selectedTopic } = getState().tree const { selectedTopic } = getState().tree
const { connectionId } = getState().connection if (!selectedTopic) {
return
}
if (!selectedTopic || !connectionId) { dispatch(clearTopic(selectedTopic, false))
}
export const clearTopic = (topic: q.TreeNode<any>, recursive: boolean) => (dispatch: Dispatch<any>, getState: () => AppState) => {
const { connectionId } = getState().connection
if (!connectionId) {
return return
} }
const publishEvent = makePublishEvent(connectionId) const publishEvent = makePublishEvent(connectionId)
const mqttMessage = { const mqttMessage = {
topic: selectedTopic.path(), topic: topic.path(),
payload: null,
retain: true,
qos: 0 as 0,
}
console.log('deleting', topic.path())
rendererEvents.emit(publishEvent, mqttMessage)
if (recursive) {
topic.childTopics().forEach((topic) => {
console.log('deleting', topic.path())
const mqttMessage = {
topic: topic.path(),
payload: null, payload: null,
retain: true, retain: true,
qos: 0 as 0, qos: 0 as 0,
} }
rendererEvents.emit(publishEvent, mqttMessage) rendererEvents.emit(publishEvent, mqttMessage)
})
}
} }

View File

@@ -4,6 +4,7 @@ import FileCopy from '@material-ui/icons/FileCopy'
import Check from '@material-ui/icons/Check' import Check from '@material-ui/icons/Check'
import green from '@material-ui/core/colors/green' import green from '@material-ui/core/colors/green'
import { withStyles, Theme } from '@material-ui/core/styles' import { withStyles, Theme } from '@material-ui/core/styles'
import CustomIconButton from './CustomIconButton';
const copy = require('copy-text-to-clipboard') const copy = require('copy-text-to-clipboard')
@@ -32,13 +33,17 @@ class Copy extends React.Component<Props, State> {
public render() { public render() {
const icon = !this.state.didCopy const icon = !this.state.didCopy
? <FileCopy fontSize="inherit" style={{ cursor: 'pointer' }} onClick={this.handleClick} /> ? <FileCopy fontSize="inherit" />
: <Check fontSize="inherit" style={{ cursor: 'default' }} /> : <Check fontSize="inherit" style={{ cursor: 'default' }} />
return ( return (
<span> <span>
<Tooltip placement="top" title="Copy to clipboard"> <Tooltip placement="top" title="Copy to clipboard">
<span style={{ fontSize: '16px' }}>{icon}</span> <span style={{ fontSize: '16px' }}>
<CustomIconButton onClick={this.handleClick} >
{icon}
</CustomIconButton>
</span>
</Tooltip> </Tooltip>
<span> <span>
<Snackbar <Snackbar

View File

@@ -0,0 +1,34 @@
import * as React from 'react'
import { IconButton } from '@material-ui/core'
import { withStyles, Theme } from '@material-ui/core/styles'
interface Props {
onClick: any,
classes: any
}
const styles = (theme: Theme) => ({
button: {
padding: '6px',
fontSize: '1.2em',
},
})
class CustomIconButton extends React.Component<Props, {}> {
constructor(props: Props) {
super(props)
}
public render() {
return (
<IconButton className={this.props.classes.button} onClick={this.onClick}>{this.props.children}</IconButton>
)
}
private onClick = (event: React.MouseEvent) => {
event.stopPropagation()
this.props.onClick(event)
}
}
export default withStyles(styles)(CustomIconButton)

View File

@@ -18,7 +18,7 @@ import { StyleRulesCallback, withStyles } from '@material-ui/core/styles'
import ChevronRight from '@material-ui/icons/ChevronRight' import ChevronRight from '@material-ui/icons/ChevronRight'
import { bindActionCreators } from 'redux' import { bindActionCreators } from 'redux'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { settingsActions, treeActions } from '../actions' import { settingsActions } from '../actions'
import { TopicOrder } from '../reducers/Settings' import { TopicOrder } from '../reducers/Settings'
import BrokerStatistics from './BrokerStatistics' import BrokerStatistics from './BrokerStatistics'
import { shell } from 'electron'; import { shell } from 'electron';

View File

@@ -1,5 +1,20 @@
import * as React from 'react'
import * as q from '../../../../backend/src/Model' import * as q from '../../../../backend/src/Model'
import * as React from 'react'
import Clear from '@material-ui/icons/Clear'
import Copy from '../Copy'
import DateFormatter from '../helper/DateFormatter'
import Delete from '@material-ui/icons/Delete'
import ExpandMore from '@material-ui/icons/ExpandMore'
import MessageHistory from './MessageHistory'
import NodeStats from './NodeStats'
import Topic from './Topic'
import { AppState } from '../../reducers'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { default as ReactResizeDetector } from 'react-resize-detector'
import { sidebarActons } from '../../actions'
import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles'
import { TopicViewModel } from '../../TopicViewModel'
import { import {
Button, Button,
@@ -12,22 +27,8 @@ import {
Typography, Typography,
Tooltip, Tooltip,
} from '@material-ui/core' } from '@material-ui/core'
import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles' import CustomIconButton from '../CustomIconButton';
import { sidebarActons } from '../../actions'
import { AppState } from '../../reducers'
import Copy from '../Copy'
import DateFormatter from '../helper/DateFormatter'
import ExpandMore from '@material-ui/icons/ExpandMore'
import Clear from '@material-ui/icons/Clear'
import MessageHistory from './MessageHistory'
import NodeStats from './NodeStats'
import Topic from './Topic'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { TopicViewModel } from '../../TopicViewModel'
import { default as ReactResizeDetector } from 'react-resize-detector'
const throttle = require('lodash.throttle') const throttle = require('lodash.throttle')
const Publish = React.lazy(() => import('./Publish/Publish')) const Publish = React.lazy(() => import('./Publish/Publish'))
@@ -92,17 +93,43 @@ class Sidebar extends React.Component<Props, State> {
private detailsStyle = { padding: '0px 16px 8px 8px', display: 'block' } private detailsStyle = { padding: '0px 16px 8px 8px', display: 'block' }
private renderTopicDeleteButton() {
if (!this.props.node) {
return null
}
return <CustomIconButton onClick={() => this.deleteTopic(this.props.node)}><Delete /></CustomIconButton>
}
private renderRecursiveTopicDeleteButton() {
if (!this.props.node) {
return null
}
return <CustomIconButton onClick={() => this.deleteTopic(this.props.node, true)}><Delete style={{ color: 'red' }} /></CustomIconButton>
}
private deleteTopic = (topic?: q.TreeNode<TopicViewModel>, recursive: boolean = false) => {
if (!topic) {
return
}
this.props.actions.clearTopic(topic, recursive)
}
private renderNode() { private renderNode() {
const { classes, node } = this.props const { classes, node } = this.props
const copyTopic = node ? <Copy value={node.path()} /> : null const copyTopic = node ? <Copy value={node.path()} /> : null
const deleteTopic = this.renderTopicDeleteButton()
const deleteRecursiveTopic = this.renderRecursiveTopicDeleteButton()
const copyValue = node && node.message ? <Copy value={node.message.value} /> : null const copyValue = node && node.message ? <Copy value={node.message.value} /> : null
const summeryStyle = { minHeight: '0' } const summeryStyle = { minHeight: '0' }
return ( return (
<div> <div>
<ExpansionPanel key="topic" defaultExpanded={true} disabled={!Boolean(this.props.node)}> <ExpansionPanel key="topic" defaultExpanded={true} disabled={!Boolean(this.props.node)}>
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}> <ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
<Typography className={classes.heading}>Topic {copyTopic}</Typography> <Typography className={classes.heading}>Topic {copyTopic} {deleteTopic} {deleteRecursiveTopic}</Typography>
</ExpansionPanelSummary> </ExpansionPanelSummary>
<ExpansionPanelDetails style={this.detailsStyle}> <ExpansionPanelDetails style={this.detailsStyle}>
<Topic node={this.props.node} didSelectNode={this.updateNode} /> <Topic node={this.props.node} didSelectNode={this.updateNode} />

View File

@@ -24,6 +24,7 @@ class IpcMainEventBus implements EventBusInterface {
public subscribe<MessageType>(subscribeEvent: Event<MessageType>, callback:(msg: MessageType) => void) { public subscribe<MessageType>(subscribeEvent: Event<MessageType>, callback:(msg: MessageType) => void) {
console.log('subscribing', subscribeEvent.topic) console.log('subscribing', subscribeEvent.topic)
this.ipc.on(subscribeEvent.topic, (event: any, arg: any) => { this.ipc.on(subscribeEvent.topic, (event: any, arg: any) => {
console.log(subscribeEvent.topic, arg)
this.client = event.sender this.client = event.sender
callback(arg) callback(arg)
}) })
@@ -39,6 +40,8 @@ class IpcMainEventBus implements EventBusInterface {
public emit<MessageType>(event: Event<MessageType>, msg: MessageType) { public emit<MessageType>(event: Event<MessageType>, msg: MessageType) {
if (!this.client.isDestroyed()) { if (!this.client.isDestroyed()) {
console.log(event.topic, msg)
this.client.send(event.topic, msg) this.client.send(event.topic, msg)
} }
} }
@@ -80,6 +83,7 @@ class IpcRendererEventBus implements EventBusInterface {
} }
public emit<MessageType>(event: Event<MessageType>, msg: MessageType) { public emit<MessageType>(event: Event<MessageType>, msg: MessageType) {
console.log(event.topic, msg)
this.ipc.send(event.topic, msg) this.ipc.send(event.topic, msg)
} }
} }