Add topic filter
This commit is contained in:
@@ -42,6 +42,10 @@ class UpdateNotifier extends React.Component<Props, {}> {
|
||||
rendererEvents.subscribe(updateAvailable, this.handleUpdate)
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
rendererEvents.unsubscribeAll(updateAvailable)
|
||||
}
|
||||
|
||||
private fixUrl(url: string, version: string) {
|
||||
if (!/^http/.test(url)) {
|
||||
return `https://github.com/thomasnordquist/MQTT-Explorer/releases/download/v${version}/${url}`
|
||||
@@ -49,9 +53,6 @@ class UpdateNotifier extends React.Component<Props, {}> {
|
||||
|
||||
return url
|
||||
}
|
||||
public componentWillUnmount() {
|
||||
rendererEvents.unsubscribeAll(updateAvailable)
|
||||
}
|
||||
|
||||
private handleUpdate = (updateInfo: UpdateInfo) => {
|
||||
this.updateInfo = updateInfo
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Dispatch } from 'redux'
|
||||
import { rendererEvents, addMqttConnectionEvent, makeConnectionStateEvent, removeConnection } from '../../../events'
|
||||
import { AppState } from '../reducers'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import { showTree } from './Tree'
|
||||
|
||||
export const connect = (options: MqttOptions, connectionId: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch(connecting(connectionId))
|
||||
@@ -14,6 +15,7 @@ export const connect = (options: MqttOptions, connectionId: string) => (dispatch
|
||||
const tree = new q.Tree()
|
||||
tree.updateWithConnection(rendererEvents, connectionId)
|
||||
dispatch(connected(tree))
|
||||
dispatch(showTree(tree))
|
||||
} else if (dataSourceState.error) {
|
||||
dispatch(showError(dataSourceState.error))
|
||||
dispatch(disconnect())
|
||||
@@ -36,11 +38,12 @@ export const showError = (error?: string) => ({
|
||||
type: ActionTypes.CONNECTION_SET_SHOW_ERROR,
|
||||
})
|
||||
|
||||
export const disconnect = () => (dispatch: Dispatch<Action>, getState: () => AppState) => {
|
||||
export const disconnect = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const { connectionId, tree } = getState().connection
|
||||
rendererEvents.emit(removeConnection, connectionId)
|
||||
tree && tree.stopUpdating()
|
||||
|
||||
dispatch(showTree(undefined))
|
||||
dispatch({
|
||||
type: ActionTypes.CONNECTION_SET_DISCONNECTED,
|
||||
})
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { Action, ActionTypes, TopicOrder } from '../reducers/Settings'
|
||||
import { ActionTypes as TreeActionTypes, Action as TreeAction } from '../reducers/Tree'
|
||||
import { Dispatch } from 'redux'
|
||||
import { AppState } from '../reducers'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
export const setAutoExpandLimit = (autoExpandLimit: number = 0): Action => {
|
||||
return {
|
||||
@@ -20,9 +24,44 @@ export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none): Action
|
||||
}
|
||||
}
|
||||
|
||||
export const filterTopics = (topicFilter: string): Action => {
|
||||
return {
|
||||
export const filterTopics = (filterStr: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const topicFilter = filterStr.toLowerCase()
|
||||
|
||||
dispatch({
|
||||
topicFilter,
|
||||
type: ActionTypes.SETTINGS_FILTER_TOPICS,
|
||||
})
|
||||
|
||||
const { tree } = getState().connection
|
||||
if (!tree) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!topicFilter) {
|
||||
dispatch({
|
||||
tree,
|
||||
filter: '',
|
||||
type: TreeActionTypes.TREE_SHOW_TREE,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const resultTree = tree.leafes()
|
||||
.filter(leaf => leaf.path().toLowerCase().indexOf(topicFilter) !== -1)
|
||||
.map((node) => {
|
||||
const clone = node.unconnectedClone()
|
||||
q.TreeNodeFactory.insertNodeAtPosition(node.path().split('/'), clone)
|
||||
return clone.firstNode()
|
||||
})
|
||||
.reduce((a: q.TreeNode, b: q.TreeNode) => {
|
||||
a.updateWithNode(b)
|
||||
return a
|
||||
}, new q.Tree())
|
||||
|
||||
dispatch({
|
||||
tree: resultTree,
|
||||
filter: topicFilter,
|
||||
type: TreeActionTypes.TREE_SHOW_TREE,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AppState } from '../reducers'
|
||||
import { makePublishEvent, rendererEvents } from '../../../events'
|
||||
|
||||
export const clearRetainedTopic = () => (dispatch: Dispatch<Action>, getState: () => AppState) => {
|
||||
const { selectedTopic } = getState().tooBigReducer
|
||||
const { selectedTopic } = getState().tree
|
||||
const { connectionId } = getState().connection
|
||||
|
||||
if (!selectedTopic || !connectionId) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ActionTypes, CustomAction, AppState } from '../reducers'
|
||||
import { AppState } from '../reducers'
|
||||
import { ActionTypes } from '../reducers/Tree'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import { Dispatch } from 'redux'
|
||||
import { setTopic } from './Publish'
|
||||
|
||||
export const selectTopic = (topic: q.TreeNode) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const { selectedTopic } = getState().tooBigReducer
|
||||
const { selectedTopic } = getState().tree
|
||||
|
||||
// Update publish topic
|
||||
if (selectedTopic && (selectedTopic.path() === getState().publish.topic || !getState().publish.topic)) {
|
||||
@@ -13,6 +14,13 @@ export const selectTopic = (topic: q.TreeNode) => (dispatch: Dispatch<any>, getS
|
||||
|
||||
dispatch({
|
||||
selectedTopic: topic,
|
||||
type: ActionTypes.selectTopic,
|
||||
type: ActionTypes.TREE_SELECT_TOPIC,
|
||||
})
|
||||
}
|
||||
|
||||
export const showTree = (tree?: q.Tree) => {
|
||||
return {
|
||||
tree,
|
||||
type: ActionTypes.TREE_SHOW_TREE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
import { AppState } from '../reducers'
|
||||
import {
|
||||
@@ -19,6 +18,7 @@ import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { settingsActions } from '../actions'
|
||||
import { TopicOrder } from '../reducers/Settings'
|
||||
import Topic from './Sidebar/Topic';
|
||||
|
||||
const styles: StyleRulesCallback = theme => ({
|
||||
drawer: {
|
||||
@@ -40,7 +40,7 @@ const styles: StyleRulesCallback = theme => ({
|
||||
})
|
||||
|
||||
interface Props {
|
||||
actions?: any
|
||||
actions: typeof settingsActions
|
||||
autoExpandLimit: number
|
||||
visible: boolean
|
||||
store?: any
|
||||
@@ -107,7 +107,7 @@ class Settings extends React.Component<Props, {}> {
|
||||
}
|
||||
|
||||
private onChangeAutoExpand = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
this.props.actions.setAutoExpandLimit(e.target.value)
|
||||
this.props.actions.setAutoExpandLimit(parseInt(e.target.value, 10))
|
||||
}
|
||||
|
||||
private renderNodeOrder() {
|
||||
@@ -133,7 +133,7 @@ class Settings extends React.Component<Props, {}> {
|
||||
}
|
||||
|
||||
private onChangeSorting = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
this.props.actions.setNodeOrder(e.target.value)
|
||||
this.props.actions.setTopicOrder(e.target.value as TopicOrder)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,10 @@ class Sidebar extends React.Component<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.props.node && this.removeUpdateListener(this.props.node)
|
||||
}
|
||||
|
||||
private registerUpdateListener(node: q.TreeNode) {
|
||||
node.onMerge.subscribe(this.updateNode)
|
||||
node.onMessage.subscribe(this.updateNode)
|
||||
@@ -215,7 +219,7 @@ class Sidebar extends React.Component<Props, State> {
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
node: state.tooBigReducer.selectedTopic,
|
||||
node: state.tree.selectedTopic,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ interface Props {
|
||||
didSelectNode?: (node: q.TreeNode) => void
|
||||
connectionId?: string
|
||||
tree?: q.Tree
|
||||
filter: string
|
||||
}
|
||||
|
||||
class Tree extends React.Component<Props, {}> {
|
||||
@@ -46,9 +47,14 @@ class Tree extends React.Component<Props, {}> {
|
||||
if (nextProps.tree) {
|
||||
nextProps.tree.onMerge.subscribe(this.throttledTreeUpdate)
|
||||
}
|
||||
this.setState(this.state)
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.props.tree && this.props.tree.onMerge.unsubscribe(this.throttledTreeUpdate)
|
||||
}
|
||||
|
||||
public throttledTreeUpdate = () => {
|
||||
if (this.updateTimer) {
|
||||
return
|
||||
@@ -68,15 +74,9 @@ class Tree extends React.Component<Props, {}> {
|
||||
}, Math.max(0, timeUntilNextUpdate))
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.props.connectionId) {
|
||||
const event = makeConnectionMessageEvent(this.props.connectionId)
|
||||
rendererEvents.unsubscribeAll(event)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (!this.props.tree) {
|
||||
const { tree, filter } = this.props
|
||||
if (!tree) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -84,17 +84,17 @@ class Tree extends React.Component<Props, {}> {
|
||||
lineHeight: '1.1',
|
||||
cursor: 'default',
|
||||
}
|
||||
|
||||
const key = `rootNode-${filter}`
|
||||
return (
|
||||
<div style={style}>
|
||||
<TreeNode
|
||||
key={key}
|
||||
animateChages={true}
|
||||
isRoot={true}
|
||||
treeNode={this.props.tree}
|
||||
treeNode={tree}
|
||||
name="/"
|
||||
lastUpdate={tree.lastUpdate}
|
||||
collapsed={false}
|
||||
key="rootNode"
|
||||
lastUpdate={this.props.tree.lastUpdate}
|
||||
performanceCallback={this.performanceCallback}
|
||||
/>
|
||||
</div>
|
||||
@@ -109,7 +109,8 @@ class Tree extends React.Component<Props, {}> {
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
autoExpandLimit: state.settings.autoExpandLimit,
|
||||
tree: state.connection.tree,
|
||||
tree: state.tree.tree,
|
||||
filter: state.tree.filter,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,17 @@ export interface Props {
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
class TreeNodeSubnodes extends React.Component<Props, {}> {
|
||||
interface State {
|
||||
alreadyAdded: number
|
||||
}
|
||||
|
||||
class TreeNodeSubnodes extends React.Component<Props, State> {
|
||||
private renderMoreAnimationFrame?: any
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this.state = { alreadyAdded: 10 }
|
||||
}
|
||||
|
||||
private sortedNodes(): q.TreeNode[] {
|
||||
const { topicOrder, treeNode } = this.props
|
||||
|
||||
@@ -39,17 +49,32 @@ class TreeNodeSubnodes extends React.Component<Props, {}> {
|
||||
return nodes
|
||||
}
|
||||
|
||||
private renderMore() {
|
||||
this.renderMoreAnimationFrame = window.requestAnimationFrame(() => {
|
||||
this.setState({ ...this.state, alreadyAdded: this.state.alreadyAdded * 1.5 })
|
||||
})
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
window.cancelAnimationFrame(this.renderMoreAnimationFrame)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const edges = Object.values(this.props.treeNode.edges)
|
||||
if (edges.length === 0 || this.props.collapsed) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (this.state.alreadyAdded < edges.length) {
|
||||
const delta = Math.min(this.state.alreadyAdded, edges.length - this.state.alreadyAdded)
|
||||
this.renderMore()
|
||||
}
|
||||
|
||||
const listItemStyle = {
|
||||
padding: '3px 0px 0px 8px',
|
||||
}
|
||||
|
||||
const nodes = this.sortedNodes()
|
||||
const nodes = this.sortedNodes().slice(0, this.state.alreadyAdded)
|
||||
const listItems = nodes.map(node => (
|
||||
<div key={node.hash()}>
|
||||
<TreeNode
|
||||
|
||||
@@ -11,7 +11,7 @@ import App from './App'
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore, applyMiddleware, compose } from 'redux'
|
||||
|
||||
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
|
||||
const composeEnhancers = /*(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || */ compose
|
||||
const store = createStore(
|
||||
reducers,
|
||||
composeEnhancers(
|
||||
|
||||
84
app/src/reducers/Settings.ts
Normal file
84
app/src/reducers/Settings.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Action } from 'redux'
|
||||
import { createReducer } from './lib'
|
||||
|
||||
export enum TopicOrder {
|
||||
none = 'none',
|
||||
messages = '#messages',
|
||||
abc = 'abc',
|
||||
topics = '#topics',
|
||||
}
|
||||
|
||||
export interface SettingsState {
|
||||
autoExpandLimit: number
|
||||
visible: boolean
|
||||
topicOrder: TopicOrder
|
||||
topicFilter?: string
|
||||
}
|
||||
export type Action = SetAutoExpandLimit | ToggleVisibility | SetTopicOrder | FilterTopics
|
||||
|
||||
export enum ActionTypes {
|
||||
SETTINGS_SET_AUTO_EXPAND_LIMIT = 'SETTINGS_SET_AUTO_EXPAND_LIMIT',
|
||||
SETTINGS_TOGGLE_VISIBILITY = 'SETTINGS_TOGGLE_VISIBILITY',
|
||||
SETTINGS_SET_TOPIC_ORDER = 'SETTINGS_SET_TOPIC_ORDER',
|
||||
SETTINGS_FILTER_TOPICS = 'SETTINGS_FILTER_TOPICS',
|
||||
}
|
||||
|
||||
const initialState: SettingsState = {
|
||||
autoExpandLimit: 0,
|
||||
topicOrder: TopicOrder.none,
|
||||
visible: false,
|
||||
}
|
||||
|
||||
export const settingsReducer = createReducer(initialState, {
|
||||
SETTINGS_SET_AUTO_EXPAND_LIMIT: setAutoExpandLimit,
|
||||
SETTINGS_TOGGLE_VISIBILITY: toggleVisibility,
|
||||
SETTINGS_SET_TOPIC_ORDER: setTopicOrder,
|
||||
SETTINGS_FILTER_TOPICS: filterTopics,
|
||||
})
|
||||
|
||||
function setAutoExpandLimit(state: SettingsState, action: SetAutoExpandLimit) {
|
||||
return {
|
||||
...state,
|
||||
autoExpandLimit: action.autoExpandLimit,
|
||||
}
|
||||
}
|
||||
|
||||
export interface SetAutoExpandLimit {
|
||||
type: ActionTypes.SETTINGS_SET_AUTO_EXPAND_LIMIT
|
||||
autoExpandLimit: number
|
||||
}
|
||||
|
||||
function toggleVisibility(state: SettingsState, action: ToggleVisibility) {
|
||||
return {
|
||||
...state,
|
||||
visible: !state.visible,
|
||||
}
|
||||
}
|
||||
|
||||
export interface ToggleVisibility {
|
||||
type: ActionTypes.SETTINGS_TOGGLE_VISIBILITY
|
||||
}
|
||||
|
||||
function setTopicOrder(state: SettingsState, action: SetTopicOrder) {
|
||||
return {
|
||||
...state,
|
||||
topicOrder: action.topicOrder,
|
||||
}
|
||||
}
|
||||
|
||||
export interface SetTopicOrder {
|
||||
type: ActionTypes.SETTINGS_SET_TOPIC_ORDER
|
||||
topicOrder: string
|
||||
}
|
||||
|
||||
function filterTopics(state: SettingsState, action: FilterTopics) {
|
||||
return {
|
||||
...state,
|
||||
topicFilter: action.topicFilter,
|
||||
}
|
||||
}
|
||||
|
||||
export interface FilterTopics {
|
||||
type: ActionTypes.SETTINGS_FILTER_TOPICS
|
||||
topicFilter: string
|
||||
}
|
||||
49
app/src/reducers/Tree.ts
Normal file
49
app/src/reducers/Tree.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import { Action } from 'redux'
|
||||
import { createReducer } from './lib'
|
||||
|
||||
export interface TreeState {
|
||||
tree?: q.Tree
|
||||
selectedTopic?: q.TreeNode
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export type Action = ShowTree | SelectTopic
|
||||
|
||||
export enum ActionTypes {
|
||||
TREE_SHOW_TREE = 'TREE_SHOW_TREE',
|
||||
TREE_SELECT_TOPIC = 'TREE_SELECT_TOPIC',
|
||||
}
|
||||
|
||||
export interface ShowTree {
|
||||
type: ActionTypes.TREE_SHOW_TREE
|
||||
tree?: q.Tree
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export interface SelectTopic {
|
||||
type: ActionTypes.TREE_SELECT_TOPIC
|
||||
selectedTopic?: q.TreeNode
|
||||
}
|
||||
|
||||
const initialState: TreeState = { }
|
||||
|
||||
export const treeReducer = createReducer(initialState, {
|
||||
TREE_SHOW_TREE: showTree,
|
||||
TREE_SELECT_TOPIC: selectTopic,
|
||||
})
|
||||
|
||||
function showTree(state: TreeState, action: ShowTree) {
|
||||
return {
|
||||
...state,
|
||||
tree: action.tree,
|
||||
filter: action.filter,
|
||||
}
|
||||
}
|
||||
|
||||
function selectTopic(state: TreeState, action: SelectTopic) {
|
||||
return {
|
||||
...state,
|
||||
selectedTopic: action.selectedTopic,
|
||||
}
|
||||
}
|
||||
@@ -6,35 +6,33 @@ import { trackEvent } from '../tracking'
|
||||
import { PublishState, publishReducer } from './Publish'
|
||||
import { ConnectionState, connectionReducer } from './Connection'
|
||||
import { SettingsState, settingsReducer } from './Settings'
|
||||
import { TreeState, treeReducer } from './Tree'
|
||||
|
||||
export enum ActionTypes {
|
||||
selectTopic = 'SELECT_TOPIC',
|
||||
showUpdateNotification = 'SHOW_UPDATE_NOTIFICATION',
|
||||
showUpdateDetails = 'SHOW_UPDATE_DETAILS',
|
||||
}
|
||||
|
||||
export interface CustomAction extends Action {
|
||||
type: ActionTypes,
|
||||
selectedTopic?: q.TreeNode
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails?: boolean
|
||||
}
|
||||
|
||||
export interface AppState {
|
||||
tooBigReducer: TooBigOfState
|
||||
tree: TreeState
|
||||
settings: SettingsState,
|
||||
publish: PublishState
|
||||
connection: ConnectionState
|
||||
}
|
||||
|
||||
export interface TooBigOfState {
|
||||
selectedTopic?: q.TreeNode
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails: boolean
|
||||
}
|
||||
|
||||
const initialBigState: TooBigOfState = {
|
||||
selectedTopic: undefined,
|
||||
showUpdateDetails: false,
|
||||
}
|
||||
|
||||
@@ -43,17 +41,8 @@ const tooBigReducer: Reducer<TooBigOfState | undefined, CustomAction> = (state =
|
||||
throw Error('No initial state')
|
||||
}
|
||||
trackEvent(action.type)
|
||||
console.log(action, state)
|
||||
switch (action.type) {
|
||||
case ActionTypes.selectTopic:
|
||||
if (!action.selectedTopic) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
selectedTopic: action.selectedTopic,
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
case ActionTypes.showUpdateNotification:
|
||||
return {
|
||||
...state,
|
||||
@@ -79,6 +68,7 @@ const reducer = combineReducers({
|
||||
publish: publishReducer,
|
||||
connection: connectionReducer,
|
||||
settings: settingsReducer,
|
||||
tree: treeReducer,
|
||||
})
|
||||
|
||||
export default reducer
|
||||
|
||||
@@ -10,9 +10,19 @@ export class RingBuffer<T extends Lengthwise> {
|
||||
private start: number = 0
|
||||
private end: number = 0
|
||||
|
||||
constructor(capacity: number, maxItems = Infinity) {
|
||||
constructor(capacity: number, maxItems = Infinity, ringBuffer?: RingBuffer<T>) {
|
||||
this.capacity = capacity
|
||||
this.maxItems = maxItems
|
||||
|
||||
if (ringBuffer) {
|
||||
this.items = ringBuffer.toArray()
|
||||
this.end = this.items.length
|
||||
this.usage = this.items.length
|
||||
}
|
||||
}
|
||||
|
||||
public clone(): RingBuffer<T> {
|
||||
return new RingBuffer(this.capacity, this.maxItems, this)
|
||||
}
|
||||
|
||||
public toArray() {
|
||||
|
||||
@@ -16,6 +16,17 @@ export class TreeNode {
|
||||
private cachedLeafes?: TreeNode[]
|
||||
private cachedLeafMessageCount?: number
|
||||
|
||||
public unconnectedClone() {
|
||||
const node = new TreeNode()
|
||||
node.message = this.message
|
||||
node.mqttMessage = this.mqttMessage
|
||||
node.messageHistory = this.messageHistory.clone()
|
||||
node.messages = this.messages
|
||||
node.lastUpdate = this.lastUpdate
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
constructor(sourceEdge?: Edge, message?: Message) {
|
||||
if (sourceEdge) {
|
||||
this.sourceEdge = sourceEdge
|
||||
|
||||
@@ -5,21 +5,29 @@ interface HasLength {
|
||||
}
|
||||
|
||||
export abstract class TreeNodeFactory {
|
||||
public static fromEdgesAndValue<T extends HasLength>(edgeNames: string[], value?: T): TreeNode {
|
||||
public static insertNodeAtPosition(edgeNames: string[], node: TreeNode) {
|
||||
let currentNode: TreeNode = new Tree()
|
||||
let edge
|
||||
for (const edgeName of edgeNames) {
|
||||
const edge = new Edge(edgeName)
|
||||
const newNode = new TreeNode(edge)
|
||||
edge.target = newNode
|
||||
edge = new Edge(edgeName)
|
||||
currentNode.addEdge(edge)
|
||||
currentNode = newNode
|
||||
currentNode = new TreeNode(edge)
|
||||
edge.target = currentNode
|
||||
}
|
||||
node.sourceEdge = edge
|
||||
node.sourceEdge!.target = node
|
||||
}
|
||||
|
||||
currentNode.setMessage({
|
||||
public static fromEdgesAndValue<T extends HasLength>(edgeNames: string[], value?: T): TreeNode {
|
||||
const node = new TreeNode()
|
||||
node.setMessage({
|
||||
value,
|
||||
length: value ? value.length : 0,
|
||||
received: new Date(),
|
||||
})
|
||||
return currentNode
|
||||
|
||||
this.insertNodeAtPosition(edgeNames, node)
|
||||
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user