1616 */
1717
1818import React from 'react' ;
19- import { observer } from 'mobx-react' ;
19+ import { observer } from 'mobx-react' ;
2020import PropTypes from 'prop-types' ;
2121import _ from 'lodash' ;
2222import Loading from '../common/loading' ;
2323import ServiceGraphResults from './serviceGraphResults' ;
2424import Error from '../common/error' ;
25+ import Graph from './util/graph' ;
26+ import timeWindow from '../../utils/timeWindow' ;
2527
2628@observer
2729export default class ServiceGraphContainer extends React . Component {
2830 static propTypes = {
29- store : PropTypes . object . isRequired ,
30- history : PropTypes . object . isRequired ,
31- isUniversalSearch : PropTypes . bool . isRequired
31+ isUniversalSearch : PropTypes . bool ,
32+ search : PropTypes . object ,
33+ graphStore : PropTypes . object . isRequired
3234 } ;
3335
36+ static defaultProps = {
37+ isUniversalSearch : false ,
38+ search : { } ,
39+ serviceName : undefined
40+ }
41+
3442 /**
3543 *
3644 * @param graph
@@ -40,12 +48,17 @@ export default class ServiceGraphContainer extends React.Component {
4048 */
4149 static findRootNode ( graph ) {
4250 const dest = _ . map ( graph , edge => edge . destination . name ) ;
43- const rootNodes = [ ] ;
51+ let rootNodes = [ ] ;
4452 _ . forEach ( graph , ( edge ) => {
4553 if ( ! _ . includes ( dest , edge . source . name ) ) {
4654 rootNodes . push ( edge . source . name ) ;
4755 }
4856 } ) ;
57+ // No node found with outgoing connections only. Find the node with the most outgoing traffic as a root node.
58+ if ( _ . isEmpty ( rootNodes ) ) {
59+ rootNodes = dest ;
60+ }
61+
4962 const uniqRoots = _ . uniq ( rootNodes ) ;
5063 const sortedRoots = _ . sortBy ( uniqRoots , ( node ) => {
5164 const outgoingEdges = _ . filter ( graph , edge => edge . source . name === node ) ;
@@ -61,12 +74,34 @@ export default class ServiceGraphContainer extends React.Component {
6174 tabSelected : 1
6275 } ;
6376 this . toggleTab = this . toggleTab . bind ( this ) ;
64- this . props . store . fetchServiceGraph ( ) ;
77+ }
78+
79+ componentDidMount ( ) {
80+ this . fetchServiceGraphFromStore ( ) ;
6581 }
6682
6783 toggleTab ( tabIndex ) {
68- this . props . store . fetchServiceGraph ( ) ;
6984 this . setState ( { tabSelected : tabIndex } ) ;
85+ this . fetchServiceGraphFromStore ( ) ;
86+ }
87+
88+ fetchServiceGraphFromStore ( ) {
89+ const time = this . props . search . time ;
90+ const isCustomTimeRange = ! ! ( time && time . from && time . to ) ;
91+ let activeWindow ;
92+
93+ if ( isCustomTimeRange ) {
94+ activeWindow = timeWindow . toCustomTimeRange ( time . from , time . to ) ;
95+ } else {
96+ activeWindow = ( time && time . preset ) ? timeWindow . findMatchingPresetByShortName ( time . preset ) : timeWindow . defaultPreset ;
97+ }
98+
99+ const activeWindowTimeRange = timeWindow . toTimeRange ( activeWindow . value ) ;
100+ const filterQuery = {
101+ from : activeWindowTimeRange . from ,
102+ to : activeWindowTimeRange . until
103+ } ;
104+ this . props . graphStore . fetchServiceGraph ( filterQuery ) ;
70105 }
71106
72107 render ( ) {
@@ -80,31 +115,55 @@ export default class ServiceGraphContainer extends React.Component {
80115 < span className = "h6" > (will show list of partial graphs if missing data from services)</ span >
81116 </ div > )
82117 }
118+ { ! this . props . search . serviceName &&
83119 < div className = "serviceGraph__tabs pull-right" >
84120 < ul className = "nav nav-tabs" >
85121 {
86- this . props . store . graphs . map (
122+ this . props . graphStore . graphs . map (
87123 ( graph , index ) => (
88- < li className = { this . state . tabSelected === ( index + 1 ) ? 'active ' : '' } >
89- < a role = "button" className = "serviceGraph__tab-link" tabIndex = "-1" onClick = { ( ) => this . toggleTab ( index + 1 ) } > { ServiceGraphContainer . findRootNode ( graph ) } </ a >
124+ < li className = { this . state . tabSelected === ( index + 1 ) ? 'active ' : '' } key = { index . toString ( ) } >
125+ < a role = "button" className = "serviceGraph__tab-link" tabIndex = "-1" onClick = { ( ) => this . toggleTab ( index + 1 ) } > { ServiceGraphContainer . findRootNode ( graph ) } </ a >
90126 </ li >
91127 )
92128 )
93129 }
94130 </ ul >
95131 </ div >
132+ }
96133 </ div >
97134 < div >
98- { this . props . store . promiseState && this . props . store . promiseState . case ( {
99- pending : ( ) => < Loading className = "serviceGraph__loading" /> ,
100- rejected : ( ) => < Error /> ,
101- fulfilled : ( ) => ( ( this . props . store . graphs && this . props . store . graphs . length )
102- ? < ServiceGraphResults serviceGraph = { this . props . store . graphs [ this . state . tabSelected - 1 ] } history = { this . props . history } />
103- : < Error /> )
104- } )
105- }
135+ { this . props . graphStore . promiseState && this . props . graphStore . promiseState . case ( {
136+ pending : ( ) => < Loading className = "serviceGraph__loading" /> ,
137+ rejected : ( ) => < Error /> ,
138+ fulfilled : ( ) => ( ( this . props . graphStore . graphs && this . props . graphStore . graphs . length )
139+ ? < FilteredServiceGraphResults graphs = { this . props . graphStore . graphs } serviceName = { this . props . search . serviceName } tabSelected = { this . state . tabSelected } />
140+ : < Error /> )
141+ } )
142+ }
106143 </ div >
107- </ section >
108- ) ;
144+ </ section > ) ;
109145 }
110146}
147+
148+ function FilteredServiceGraphResults ( props ) {
149+ if ( ! props . serviceName ) {
150+ return ( < ServiceGraphResults serviceGraph = { props . graphs [ props . tabSelected - 1 ] } /> ) ;
151+ }
152+ const result = _ . find ( props . graphs , g => _ . includes ( Graph . buildGraph ( g ) . allNodes ( ) , props . serviceName ) ) ;
153+ if ( typeof result !== 'undefined' ) {
154+ const filtered = _ . filter ( result , edge => edge . source . name === props . serviceName || edge . destination . name === props . serviceName ) ;
155+ return ( < ServiceGraphResults serviceGraph = { filtered } /> ) ;
156+ }
157+ return ( < Error errorMessage = "ServiceGraph data not found for the given time frame." /> ) ;
158+ }
159+
160+ FilteredServiceGraphResults . propTypes = {
161+ graphs : PropTypes . object . isRequired ,
162+ serviceName : PropTypes . string ,
163+ tabSelected : PropTypes . number
164+ } ;
165+
166+ FilteredServiceGraphResults . defaultProps = {
167+ serviceName : undefined ,
168+ tabSelected : 0
169+ } ;
0 commit comments