Loading js-apps/meep-frontend/src/js/components/helper-components/nc-group.js +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import { firstLetterUpper } from '../../util/stringManipulation'; } from '../../util/string-manipulation'; import { // Field Names Loading js-apps/meep-frontend/src/js/containers/dashboard-container.js +400 −67 Original line number Diff line number Diff line import _ from 'lodash'; import { connect } from 'react-redux'; import React, { Component } from 'react'; import React, { Component, useState } from 'react'; import { Grid, GridCell, GridInner } from '@rmwc/grid'; import { Elevation } from '@rmwc/elevation'; import { Graph } from 'react-d3-graph'; import ReactDOM from 'react-dom'; import { Button } from '@rmwc/button'; import { Checkbox } from '@rmwc/checkbox'; import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import * as d3 from 'd3'; import axios from 'axios'; Loading @@ -13,18 +16,33 @@ import axios from 'axios'; import IDCLineChart from './idc-line-chart'; import IDCGraph from './idc-graph'; import IDCAppsView from './idc-apps-view'; import IDSelect from '../components/helper-components/id-select'; import { getScenarioNodeChildren, isApp } from '../util/scenario-utils'; import { dataAccessorForType, dataSetterForType, isDataPointOfType } from '../util/metrics'; import { execFakeChangeSelectedDestination, execChangeSourceNodeSelected, execAddMetricsEpoch } from '../state/exec'; import { LATENCY_METRICS, THROUGHPUT_METRICS, MOBILITY_EVENT } from '../meep-constants'; const VIEW_NAME_NONE = 'none'; function colorArray(dataLength) { const colorScale = d3.interpolateInferno; // const colorScale = d3.interpolateMagma; Loading Loading @@ -79,27 +97,234 @@ const dataPointFromEpochDataPoints = destinations => sourceNodeId => dataAccesso const notNull = x => x; const epochsToDataPoints = epochs => nb => destinations => dataAccessor => sourceNodeId => { const selectedEpochs = epochs.length ? epochs.slice(-nb) : []; if (selectedEpochs.length === 0) { console.log('epoch length is 0'); } const dataPoints = selectedEpochs.map(dataPointFromEpochDataPoints(destinations)(sourceNodeId)(dataAccessor)).filter(notNull); return dataPoints; }; const dataAccessorForType = dataType => { switch (dataType) { case 'latency': return p => p.data.latency; case 'ingressPacketStats': return p => p.data.throughput; const ConfigurationView = (props) => { return ( <Grid> <GridCell span={2}> <IDSelect label={'Select View 1'} outlined options={props.dashboardViewsList} onChange={(e) => { props.changeView1(e.target.value); }} // disabled={props.disabled} value={props.view1} /> </GridCell> <GridCell span={2}> <IDSelect label={'Select View 2'} outlined options={props.dashboardViewsList} onChange={(e) => { props.changeView2(e.target.value); }} // disabled={props.disabled} value={props.view1} /> </GridCell> <GridCell span={2}> <IDSelect label={'Select Source Node'} outlined options={props.nodeIds} onChange={(e) => { props.changeSourceNodeSelected(e.target.value); }} // disabled={props.disabled} value={props.sourceNodeSelected ? props.sourceNodeSelected.data.id : ''} /> </GridCell> <GridCell span={1}> <Checkbox checked={props.displayEdgeLabels} onChange={() => props.changeDisplayEdgeLabels(!props.displayEdgeLabels)} > Show data on edges </Checkbox> </GridCell> <GridCell span={5}> </GridCell> </Grid> ); }; const DATA_CONFIGURATION = 'DATA_CONFIGURATION'; const MAIN_CONFIGURATION = 'MAIN_CONFIGURATION'; const buttonStyles = { marginRight: 0 }; const HIERARCHY_VIEW = 'HIERARCHY_VIEW'; const APPS_VIEW = 'APPS_VIEW'; const LATENCY_VIEW = 'LATENCY_VIEW'; const THROUGHPUT_VIEW = 'THROUGHPUT_VIEW'; const DASHBOARD_VIEWS_LIST = [VIEW_NAME_NONE, HIERARCHY_VIEW, APPS_VIEW, LATENCY_VIEW, THROUGHPUT_VIEW]; const ViewForName = ( { apps, colorRange, width, height, min, max, data, mobilityEvents, dataPoints, dataAccessor, dataType, selectedSource, colorForApp, changeSourceNodeSelected, viewName, displayEdgeLabels } ) => { const appIds = apps.map(app => app.data.id); switch(viewName) { case HIERARCHY_VIEW: return ( <IDCGraph width={width} height={600} /> ); case APPS_VIEW: return ( <IDCAppsView apps={apps} colorRange={colorRange} width={width} height={600} data={data} dataAccessor={dataAccessor} dataType={dataType} selectedSource={selectedSource} colorForApp={colorForApp} onNodeClicked={(e) => { console.log('Node clicked is: ', e.node); changeSourceNodeSelected(e.node); }} displayEdgeLabels={displayEdgeLabels} /> ); case LATENCY_VIEW: return ( <IDCLineChart data={dataPoints} mobilityEvents={mobilityEvents} width={width} height={600} destinations={appIds} colorRange={colorRange} selectedSource={selectedSource} dataType={dataType} // Specify units // Specify label min={min} max={max} colorForApp={colorForApp} /> ); case THROUGHPUT_VIEW: return ( <IDCLineChart data={dataPoints} mobilityEvents={mobilityEvents} width={width} height={600} destinations={appIds} colorRange={colorRange} selectedSource={selectedSource} dataType={dataType} // Specify units // Specify label min={min} max={max} colorForApp={colorForApp} /> ); default: return dataAccessorForType('latency'); return null; } }; const DashboardConfiguration = (props) => { let configurationView = null; if(props.configurationType) { configurationView = ( <ConfigurationView dashboardViewsList={props.dashboardViewsList} view1Type={props.view1Type} view2Type={props.view2Type} changeView1={props.changeView1} changeView2={props.changeView2} nodeIds={props.nodeIds} sourceNodeSelected={props.sourceNodeSelected} changeSourceNodeSelected={props.changeSourceNodeSelected} changeDisplayEdgeLabels={props.changeDisplayEdgeLabels} displayEdgeLabels={props.displayEdgeLabels} /> ); } const buttonConfig = !props.configurationType ? ( <Button outlined style={buttonStyles} onClick={props.displayConfiguration}> Configuration </Button> ) : null; const buttonClose = props.configurationType ? ( <Button outlined style={buttonStyles} onClick={props.hideConfiguration}> Close </Button> ) : null; const backgroundColor = 'ffffff'; // props.configurationType ? '#e4e4e4' : 'ffffff'; return ( <div style={{border: '1px solid #e4e4e4', padding: 10, marginBottom: 10, backgroundColor: backgroundColor}}> <Grid> <GridCell span={10}> </GridCell> <GridCell span={2}> {buttonConfig} {buttonClose} </GridCell> </Grid> {configurationView} </div> ); }; class DashboardContainer extends Component { constructor(props) { super(props); this.state = { configurationType: null, view1Name: APPS_VIEW, view2Name: LATENCY_VIEW, sourceNodeId: '', nbSecondsToDisplay: 25, displayEdgeLabels: false }; } Loading Loading @@ -129,84 +354,192 @@ class DashboardContainer extends Component { return d3.hierarchy(this.props.displayedScenario, getScenarioNodeChildren); } changeView1(name) { this.setState({ view1Name: name }); } changeView2(name) { this.setState({ view2Name: name }); } changeDisplayEdgeLabels(val) { this.setState({displayEdgeLabels: val}); } render() { const root = this.getRoot(); const nodes = root.descendants(); const apps = nodes.filter(isApp); const destinations = apps.map(a => a.data.id); const colorRange = colorArray(destinations.length); const appIds = apps.map(a => a.data.id); const appMap = apps.reduce((acc, app) => {acc[app.data.id] = app; return acc;}, {}); const colorRange = colorArray(appIds.length); const nbEpochs = 25; const selectedNodeId = this.props.sourceNodeSelected ? this.props.sourceNodeSelected.data.id : null; const dataAccessor = dataAccessorForType(this.props.dataTypeSelected); const dataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(destinations)(dataAccessor)(selectedNodeId); const selectedSource = this.props.sourceNodeSelected ? this.props.sourceNodeSelected.data.id : null; const showApps = this.props.showAppsView; const span = showApps ? 6 : 12; const colorForApp = apps.reduce((res, val, i) => { // res[val.data.id] = colorRange[i]; return {...res, [val.data.id]: colorRange[i]}; }, {}); const lastEpoch = this.props.epochs.length ? this.props.epochs.slice(-1)[0] : []; let lastEpoch = this.props.epochs.length ? this.props.epochs.slice(-1)[0] : []; const hasValue = p => { const accessor = dataAccessorForType(p.dataType); if (! accessor(p)) { console.log(`No value for src ${p.src} and dest ${p.dest}`); } return accessor(p); }; lastEpoch = lastEpoch.filter(hasValue); const isDataOfType = type => dataPoint => dataPoint.dataType === type; const data = lastEpoch.filter(isDataOfType(this.props.dataTypeSelected)); let graph = null; const dataTypeForView = view => { switch (view) { case LATENCY_VIEW: return LATENCY_METRICS; case THROUGHPUT_VIEW: return THROUGHPUT_METRICS; default: return LATENCY_METRICS; } }; if (showApps) { graph = ( <IDCAppsView const view1DataType = dataTypeForView(this.state.view1Name); const view1Accessor = dataAccessorForType(view1DataType); const view1DataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(appIds)(view1Accessor)(selectedSource); const data1 = lastEpoch.filter(isDataOfType(view1DataType)); const max1 = d3.max(data1, view1Accessor); const min1 = d3.min(data1, view1Accessor); const view2DataType = dataTypeForView(this.state.view2Name); const view2Accessor = dataAccessorForType(view2DataType); const view2DataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(appIds)(view2Accessor)(selectedSource); const data2 = lastEpoch.filter(isDataOfType(view2DataType)); const extractPointsOfType = type => epoch => epoch.filter(isDataPointOfType(type)); const extractMobilityEvents = extractPointsOfType(MOBILITY_EVENT); const mobilityEvents = this.props.epochs.flatMap(extractMobilityEvents); if (mobilityEvents.length) { console.log('Some mobility events ...'); } data2.forEach((d) => { const dd = view1Accessor(d); if (!dd) { console.log(`Null data: ${dd}. `); } }); const max2 = d3.max(data2, view2Accessor); const min2 = d3.min(data2, view2Accessor); const width = 700; const height = 600; let span1 = 6; let width1 = 700; let span2 = 6; let width2 = 700; if (this.state.view1Name === VIEW_NAME_NONE) { span1 = 0; width1 = 0; span2 = 12; width2 = 1200; } if (this.state.view2Name === VIEW_NAME_NONE) { span1 = 12; width1 = 1200; span2 = 0; width2 = 0; } const view1 = ( <ViewForName apps={apps} colorRange={colorRange} width={700} height={600} data={data} dataAccessor={dataAccessor} dataType={this.props.dataTypeSelected} selectedSource={selectedNodeId} width={width1} height={height} data={data1} mobilityEvents={mobilityEvents} min={min1} max={max1} dataPoints={view1DataPoints} dataAccessor={view1Accessor} dataType={view1DataType} selectedSource={selectedSource} colorForApp={colorForApp} onNodeClicked={(e) => { console.log('Node clicked is: ', e.node); this.props.changeSourceNodeSelected(e.node); }} changeSourceNodeSelected={(node) => this.props.changeSourceNodeSelected(node)} viewName={this.state.view1Name} displayEdgeLabels={this.state.displayEdgeLabels} /> ); } else { graph = (<IDCGraph width={1000} height={600} />); } return ( <Grid> <GridCell span={span} style={{marginLeft: -10}}> <Elevation z={4}> {graph} </Elevation> </GridCell> {showApps ? (<GridCell span={6} style={{marginRight: -10}}> <Elevation z={4}> <IDCLineChart data={dataPoints} width={700} height={600} destinations={destinations} const view2 = ( <ViewForName apps={apps} colorRange={colorRange} sourceSelected={this.props.sourceNodeSelected} // min={min} // max={max} width={width2} height={height} data={data2} mobilityEvents={mobilityEvents} min={min2} max={max2} dataPoints={view2DataPoints} dataAccessor={view2Accessor} dataType={view2DataType} selectedSource={selectedSource} colorForApp={colorForApp} changeSourceNodeSelected={(node) => this.props.changeSourceNodeSelected(node)} viewName={this.state.view2Name} displayEdgeLabels={this.state.displayEdgeLabels} > </ViewForName> ); return ( <> <Elevation z={4} style={{padding: 10}} > <DashboardConfiguration configurationType={this.state.configurationType} displayConfiguration={ () => { this.setState({configurationType: MAIN_CONFIGURATION}); }} hideConfiguration={() => {this.setState({configurationType: ''});}} nodeIds={appIds} sourceNodeSelected={this.props.sourceNodeSelected} changeSourceNodeSelected={(nodeId) => this.props.changeSourceNodeSelected(appMap[nodeId])} dashboardViewsList={DASHBOARD_VIEWS_LIST} changeView1={(viewName) => this.changeView1(viewName)} changeView2={(viewName) => this.changeView2(viewName)} displayEdgeLabels={this.state.displayEdgeLabels} changeDisplayEdgeLabels={(display) => this.changeDisplayEdgeLabels(display)} /> </Elevation> </GridCell>) : null} <Grid> <GridCell span={span1} style={{marginLeft: -10}}> {view1} </GridCell> <GridCell span={span2} style={{marginLeft: -10}}> {view2} </GridCell> </Grid> </Elevation> </> ); } } Loading js-apps/meep-frontend/src/js/containers/exec/network-characteristics-event-pane.js +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ import { camelCasePrefix, firstLetterUpper } from '../../util/stringManipulation'; } from '../../util/string-manipulation'; import { EXEC_EVT_NC_TYPE, Loading js-apps/meep-frontend/src/js/containers/idc-apps-view.js +4 −7 Original line number Diff line number Diff line Loading @@ -38,8 +38,6 @@ const edgesFromData = (data, dataAccessor, colorForApp, selectedSource) => { const apps = Object.keys(m); console.log('m: ', m); const edgesFromSource = dataAccessor => src => { const rowObject = m[src]; if (!rowObject) { Loading Loading @@ -74,7 +72,7 @@ const edgesFromData = (data, dataAccessor, colorForApp, selectedSource) => { if (selectedSource) { return e.src === selectedSource; } else { return false; return true; } }; const edges = _.flatMap(apps.map(edgesFromSource(dataAccessor))).filter(outwardEdgesIfSourceSelected); Loading Loading @@ -117,7 +115,6 @@ const unitsForDataType = type => { } }; const IDCAppsView = ( { apps, Loading @@ -129,7 +126,8 @@ const IDCAppsView = ( width, height, onNodeClicked, colorForApp colorForApp, displayEdgeLabels } ) => { Loading Loading @@ -180,8 +178,7 @@ const IDCAppsView = ( xlinkHref={`#textPathDef${i}`} startOffset={'45%'} > {`${edgeLabel} ${e.avgData.toFixed(2)} ${edgeUnits}`} {displayEdgeLabels ? `${edgeLabel} ${e.avgData.toFixed(2)} ${edgeUnits}` : null} </textPath> </text> ); Loading js-apps/meep-frontend/src/js/containers/idc-graph.js +6 −2 Original line number Diff line number Diff line Loading @@ -13,10 +13,13 @@ import { Graph } from 'react-d3-graph'; import ReactDOM from 'react-dom'; import * as d3 from 'd3'; import IDCNode from './idc-node.js'; import { plusGenerator, minusGenerator, lineGeneratorNodes, lineGeneratorReverse, visitNodes, blue } from './graph-utils'; Loading Loading @@ -240,7 +243,7 @@ class IDCGraph extends Component { <path key={'path' + i} id={'textPathDef' + i} d={lineGeneratorReverse(d)} d={lineGeneratorNodes(d.parent)(d)} style={{fill: 'none', 'strokeWidth': 2}} stroke={'#aaa'} className='line' Loading Loading @@ -268,7 +271,8 @@ class IDCGraph extends Component { xlinkHref={`#textPathDef${i}`} startOffset={'20%'} > {`${Math.ceil(Math.random()*25)}ms`} {/* {`${Math.ceil(Math.random()*25)}ms`} */} {''} </textPath> </text> ); Loading Loading
js-apps/meep-frontend/src/js/components/helper-components/nc-group.js +1 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,7 @@ import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import { firstLetterUpper } from '../../util/stringManipulation'; } from '../../util/string-manipulation'; import { // Field Names Loading
js-apps/meep-frontend/src/js/containers/dashboard-container.js +400 −67 Original line number Diff line number Diff line import _ from 'lodash'; import { connect } from 'react-redux'; import React, { Component } from 'react'; import React, { Component, useState } from 'react'; import { Grid, GridCell, GridInner } from '@rmwc/grid'; import { Elevation } from '@rmwc/elevation'; import { Graph } from 'react-d3-graph'; import ReactDOM from 'react-dom'; import { Button } from '@rmwc/button'; import { Checkbox } from '@rmwc/checkbox'; import { TextField, TextFieldHelperText } from '@rmwc/textfield'; import * as d3 from 'd3'; import axios from 'axios'; Loading @@ -13,18 +16,33 @@ import axios from 'axios'; import IDCLineChart from './idc-line-chart'; import IDCGraph from './idc-graph'; import IDCAppsView from './idc-apps-view'; import IDSelect from '../components/helper-components/id-select'; import { getScenarioNodeChildren, isApp } from '../util/scenario-utils'; import { dataAccessorForType, dataSetterForType, isDataPointOfType } from '../util/metrics'; import { execFakeChangeSelectedDestination, execChangeSourceNodeSelected, execAddMetricsEpoch } from '../state/exec'; import { LATENCY_METRICS, THROUGHPUT_METRICS, MOBILITY_EVENT } from '../meep-constants'; const VIEW_NAME_NONE = 'none'; function colorArray(dataLength) { const colorScale = d3.interpolateInferno; // const colorScale = d3.interpolateMagma; Loading Loading @@ -79,27 +97,234 @@ const dataPointFromEpochDataPoints = destinations => sourceNodeId => dataAccesso const notNull = x => x; const epochsToDataPoints = epochs => nb => destinations => dataAccessor => sourceNodeId => { const selectedEpochs = epochs.length ? epochs.slice(-nb) : []; if (selectedEpochs.length === 0) { console.log('epoch length is 0'); } const dataPoints = selectedEpochs.map(dataPointFromEpochDataPoints(destinations)(sourceNodeId)(dataAccessor)).filter(notNull); return dataPoints; }; const dataAccessorForType = dataType => { switch (dataType) { case 'latency': return p => p.data.latency; case 'ingressPacketStats': return p => p.data.throughput; const ConfigurationView = (props) => { return ( <Grid> <GridCell span={2}> <IDSelect label={'Select View 1'} outlined options={props.dashboardViewsList} onChange={(e) => { props.changeView1(e.target.value); }} // disabled={props.disabled} value={props.view1} /> </GridCell> <GridCell span={2}> <IDSelect label={'Select View 2'} outlined options={props.dashboardViewsList} onChange={(e) => { props.changeView2(e.target.value); }} // disabled={props.disabled} value={props.view1} /> </GridCell> <GridCell span={2}> <IDSelect label={'Select Source Node'} outlined options={props.nodeIds} onChange={(e) => { props.changeSourceNodeSelected(e.target.value); }} // disabled={props.disabled} value={props.sourceNodeSelected ? props.sourceNodeSelected.data.id : ''} /> </GridCell> <GridCell span={1}> <Checkbox checked={props.displayEdgeLabels} onChange={() => props.changeDisplayEdgeLabels(!props.displayEdgeLabels)} > Show data on edges </Checkbox> </GridCell> <GridCell span={5}> </GridCell> </Grid> ); }; const DATA_CONFIGURATION = 'DATA_CONFIGURATION'; const MAIN_CONFIGURATION = 'MAIN_CONFIGURATION'; const buttonStyles = { marginRight: 0 }; const HIERARCHY_VIEW = 'HIERARCHY_VIEW'; const APPS_VIEW = 'APPS_VIEW'; const LATENCY_VIEW = 'LATENCY_VIEW'; const THROUGHPUT_VIEW = 'THROUGHPUT_VIEW'; const DASHBOARD_VIEWS_LIST = [VIEW_NAME_NONE, HIERARCHY_VIEW, APPS_VIEW, LATENCY_VIEW, THROUGHPUT_VIEW]; const ViewForName = ( { apps, colorRange, width, height, min, max, data, mobilityEvents, dataPoints, dataAccessor, dataType, selectedSource, colorForApp, changeSourceNodeSelected, viewName, displayEdgeLabels } ) => { const appIds = apps.map(app => app.data.id); switch(viewName) { case HIERARCHY_VIEW: return ( <IDCGraph width={width} height={600} /> ); case APPS_VIEW: return ( <IDCAppsView apps={apps} colorRange={colorRange} width={width} height={600} data={data} dataAccessor={dataAccessor} dataType={dataType} selectedSource={selectedSource} colorForApp={colorForApp} onNodeClicked={(e) => { console.log('Node clicked is: ', e.node); changeSourceNodeSelected(e.node); }} displayEdgeLabels={displayEdgeLabels} /> ); case LATENCY_VIEW: return ( <IDCLineChart data={dataPoints} mobilityEvents={mobilityEvents} width={width} height={600} destinations={appIds} colorRange={colorRange} selectedSource={selectedSource} dataType={dataType} // Specify units // Specify label min={min} max={max} colorForApp={colorForApp} /> ); case THROUGHPUT_VIEW: return ( <IDCLineChart data={dataPoints} mobilityEvents={mobilityEvents} width={width} height={600} destinations={appIds} colorRange={colorRange} selectedSource={selectedSource} dataType={dataType} // Specify units // Specify label min={min} max={max} colorForApp={colorForApp} /> ); default: return dataAccessorForType('latency'); return null; } }; const DashboardConfiguration = (props) => { let configurationView = null; if(props.configurationType) { configurationView = ( <ConfigurationView dashboardViewsList={props.dashboardViewsList} view1Type={props.view1Type} view2Type={props.view2Type} changeView1={props.changeView1} changeView2={props.changeView2} nodeIds={props.nodeIds} sourceNodeSelected={props.sourceNodeSelected} changeSourceNodeSelected={props.changeSourceNodeSelected} changeDisplayEdgeLabels={props.changeDisplayEdgeLabels} displayEdgeLabels={props.displayEdgeLabels} /> ); } const buttonConfig = !props.configurationType ? ( <Button outlined style={buttonStyles} onClick={props.displayConfiguration}> Configuration </Button> ) : null; const buttonClose = props.configurationType ? ( <Button outlined style={buttonStyles} onClick={props.hideConfiguration}> Close </Button> ) : null; const backgroundColor = 'ffffff'; // props.configurationType ? '#e4e4e4' : 'ffffff'; return ( <div style={{border: '1px solid #e4e4e4', padding: 10, marginBottom: 10, backgroundColor: backgroundColor}}> <Grid> <GridCell span={10}> </GridCell> <GridCell span={2}> {buttonConfig} {buttonClose} </GridCell> </Grid> {configurationView} </div> ); }; class DashboardContainer extends Component { constructor(props) { super(props); this.state = { configurationType: null, view1Name: APPS_VIEW, view2Name: LATENCY_VIEW, sourceNodeId: '', nbSecondsToDisplay: 25, displayEdgeLabels: false }; } Loading Loading @@ -129,84 +354,192 @@ class DashboardContainer extends Component { return d3.hierarchy(this.props.displayedScenario, getScenarioNodeChildren); } changeView1(name) { this.setState({ view1Name: name }); } changeView2(name) { this.setState({ view2Name: name }); } changeDisplayEdgeLabels(val) { this.setState({displayEdgeLabels: val}); } render() { const root = this.getRoot(); const nodes = root.descendants(); const apps = nodes.filter(isApp); const destinations = apps.map(a => a.data.id); const colorRange = colorArray(destinations.length); const appIds = apps.map(a => a.data.id); const appMap = apps.reduce((acc, app) => {acc[app.data.id] = app; return acc;}, {}); const colorRange = colorArray(appIds.length); const nbEpochs = 25; const selectedNodeId = this.props.sourceNodeSelected ? this.props.sourceNodeSelected.data.id : null; const dataAccessor = dataAccessorForType(this.props.dataTypeSelected); const dataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(destinations)(dataAccessor)(selectedNodeId); const selectedSource = this.props.sourceNodeSelected ? this.props.sourceNodeSelected.data.id : null; const showApps = this.props.showAppsView; const span = showApps ? 6 : 12; const colorForApp = apps.reduce((res, val, i) => { // res[val.data.id] = colorRange[i]; return {...res, [val.data.id]: colorRange[i]}; }, {}); const lastEpoch = this.props.epochs.length ? this.props.epochs.slice(-1)[0] : []; let lastEpoch = this.props.epochs.length ? this.props.epochs.slice(-1)[0] : []; const hasValue = p => { const accessor = dataAccessorForType(p.dataType); if (! accessor(p)) { console.log(`No value for src ${p.src} and dest ${p.dest}`); } return accessor(p); }; lastEpoch = lastEpoch.filter(hasValue); const isDataOfType = type => dataPoint => dataPoint.dataType === type; const data = lastEpoch.filter(isDataOfType(this.props.dataTypeSelected)); let graph = null; const dataTypeForView = view => { switch (view) { case LATENCY_VIEW: return LATENCY_METRICS; case THROUGHPUT_VIEW: return THROUGHPUT_METRICS; default: return LATENCY_METRICS; } }; if (showApps) { graph = ( <IDCAppsView const view1DataType = dataTypeForView(this.state.view1Name); const view1Accessor = dataAccessorForType(view1DataType); const view1DataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(appIds)(view1Accessor)(selectedSource); const data1 = lastEpoch.filter(isDataOfType(view1DataType)); const max1 = d3.max(data1, view1Accessor); const min1 = d3.min(data1, view1Accessor); const view2DataType = dataTypeForView(this.state.view2Name); const view2Accessor = dataAccessorForType(view2DataType); const view2DataPoints = epochsToDataPoints(this.props.epochs)(nbEpochs)(appIds)(view2Accessor)(selectedSource); const data2 = lastEpoch.filter(isDataOfType(view2DataType)); const extractPointsOfType = type => epoch => epoch.filter(isDataPointOfType(type)); const extractMobilityEvents = extractPointsOfType(MOBILITY_EVENT); const mobilityEvents = this.props.epochs.flatMap(extractMobilityEvents); if (mobilityEvents.length) { console.log('Some mobility events ...'); } data2.forEach((d) => { const dd = view1Accessor(d); if (!dd) { console.log(`Null data: ${dd}. `); } }); const max2 = d3.max(data2, view2Accessor); const min2 = d3.min(data2, view2Accessor); const width = 700; const height = 600; let span1 = 6; let width1 = 700; let span2 = 6; let width2 = 700; if (this.state.view1Name === VIEW_NAME_NONE) { span1 = 0; width1 = 0; span2 = 12; width2 = 1200; } if (this.state.view2Name === VIEW_NAME_NONE) { span1 = 12; width1 = 1200; span2 = 0; width2 = 0; } const view1 = ( <ViewForName apps={apps} colorRange={colorRange} width={700} height={600} data={data} dataAccessor={dataAccessor} dataType={this.props.dataTypeSelected} selectedSource={selectedNodeId} width={width1} height={height} data={data1} mobilityEvents={mobilityEvents} min={min1} max={max1} dataPoints={view1DataPoints} dataAccessor={view1Accessor} dataType={view1DataType} selectedSource={selectedSource} colorForApp={colorForApp} onNodeClicked={(e) => { console.log('Node clicked is: ', e.node); this.props.changeSourceNodeSelected(e.node); }} changeSourceNodeSelected={(node) => this.props.changeSourceNodeSelected(node)} viewName={this.state.view1Name} displayEdgeLabels={this.state.displayEdgeLabels} /> ); } else { graph = (<IDCGraph width={1000} height={600} />); } return ( <Grid> <GridCell span={span} style={{marginLeft: -10}}> <Elevation z={4}> {graph} </Elevation> </GridCell> {showApps ? (<GridCell span={6} style={{marginRight: -10}}> <Elevation z={4}> <IDCLineChart data={dataPoints} width={700} height={600} destinations={destinations} const view2 = ( <ViewForName apps={apps} colorRange={colorRange} sourceSelected={this.props.sourceNodeSelected} // min={min} // max={max} width={width2} height={height} data={data2} mobilityEvents={mobilityEvents} min={min2} max={max2} dataPoints={view2DataPoints} dataAccessor={view2Accessor} dataType={view2DataType} selectedSource={selectedSource} colorForApp={colorForApp} changeSourceNodeSelected={(node) => this.props.changeSourceNodeSelected(node)} viewName={this.state.view2Name} displayEdgeLabels={this.state.displayEdgeLabels} > </ViewForName> ); return ( <> <Elevation z={4} style={{padding: 10}} > <DashboardConfiguration configurationType={this.state.configurationType} displayConfiguration={ () => { this.setState({configurationType: MAIN_CONFIGURATION}); }} hideConfiguration={() => {this.setState({configurationType: ''});}} nodeIds={appIds} sourceNodeSelected={this.props.sourceNodeSelected} changeSourceNodeSelected={(nodeId) => this.props.changeSourceNodeSelected(appMap[nodeId])} dashboardViewsList={DASHBOARD_VIEWS_LIST} changeView1={(viewName) => this.changeView1(viewName)} changeView2={(viewName) => this.changeView2(viewName)} displayEdgeLabels={this.state.displayEdgeLabels} changeDisplayEdgeLabels={(display) => this.changeDisplayEdgeLabels(display)} /> </Elevation> </GridCell>) : null} <Grid> <GridCell span={span1} style={{marginLeft: -10}}> {view1} </GridCell> <GridCell span={span2} style={{marginLeft: -10}}> {view2} </GridCell> </Grid> </Elevation> </> ); } } Loading
js-apps/meep-frontend/src/js/containers/exec/network-characteristics-event-pane.js +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ import { camelCasePrefix, firstLetterUpper } from '../../util/stringManipulation'; } from '../../util/string-manipulation'; import { EXEC_EVT_NC_TYPE, Loading
js-apps/meep-frontend/src/js/containers/idc-apps-view.js +4 −7 Original line number Diff line number Diff line Loading @@ -38,8 +38,6 @@ const edgesFromData = (data, dataAccessor, colorForApp, selectedSource) => { const apps = Object.keys(m); console.log('m: ', m); const edgesFromSource = dataAccessor => src => { const rowObject = m[src]; if (!rowObject) { Loading Loading @@ -74,7 +72,7 @@ const edgesFromData = (data, dataAccessor, colorForApp, selectedSource) => { if (selectedSource) { return e.src === selectedSource; } else { return false; return true; } }; const edges = _.flatMap(apps.map(edgesFromSource(dataAccessor))).filter(outwardEdgesIfSourceSelected); Loading Loading @@ -117,7 +115,6 @@ const unitsForDataType = type => { } }; const IDCAppsView = ( { apps, Loading @@ -129,7 +126,8 @@ const IDCAppsView = ( width, height, onNodeClicked, colorForApp colorForApp, displayEdgeLabels } ) => { Loading Loading @@ -180,8 +178,7 @@ const IDCAppsView = ( xlinkHref={`#textPathDef${i}`} startOffset={'45%'} > {`${edgeLabel} ${e.avgData.toFixed(2)} ${edgeUnits}`} {displayEdgeLabels ? `${edgeLabel} ${e.avgData.toFixed(2)} ${edgeUnits}` : null} </textPath> </text> ); Loading
js-apps/meep-frontend/src/js/containers/idc-graph.js +6 −2 Original line number Diff line number Diff line Loading @@ -13,10 +13,13 @@ import { Graph } from 'react-d3-graph'; import ReactDOM from 'react-dom'; import * as d3 from 'd3'; import IDCNode from './idc-node.js'; import { plusGenerator, minusGenerator, lineGeneratorNodes, lineGeneratorReverse, visitNodes, blue } from './graph-utils'; Loading Loading @@ -240,7 +243,7 @@ class IDCGraph extends Component { <path key={'path' + i} id={'textPathDef' + i} d={lineGeneratorReverse(d)} d={lineGeneratorNodes(d.parent)(d)} style={{fill: 'none', 'strokeWidth': 2}} stroke={'#aaa'} className='line' Loading Loading @@ -268,7 +271,8 @@ class IDCGraph extends Component { xlinkHref={`#textPathDef${i}`} startOffset={'20%'} > {`${Math.ceil(Math.random()*25)}ms`} {/* {`${Math.ceil(Math.random()*25)}ms`} */} {''} </textPath> </text> ); Loading