Unverified Commit 17d900a4 authored by Kevin Di Lallo's avatar Kevin Di Lallo Committed by GitHub
Browse files

Merge pull request #31 from renaudmx/fr_sp_29

New Exec tab with data analytics dashboard
parents e982a907 87cabc9e
Loading
Loading
Loading
Loading
+155 −64
Original line number Diff line number Diff line
@@ -75,8 +75,11 @@ import {
  PREFIX_EDGE_FOG,
  PREFIX_TERM_LINK,
  PREFIX_LINK,
  PREFIX_APP
  PREFIX_APP,

  // NC Group Layouts
  MEEP_COMPONENT_SINGLE_COLUMN_LAYOUT,
  MEEP_COMPONENT_TABLE_LAYOUT
} from '../../meep-constants';

const MIN_LATENCY_VALUE = 0;
@@ -158,6 +161,83 @@ const validateThroughput = (val) => {
  return null;
};



const TableLayout = (props) => {
  return (
    <div>
      <Grid>
        <GridCell span="6">
          {props.latencyComponent}
        </GridCell>
       
        <GridCell span="6">
          {props.latencyVariationComponent}
        </GridCell>
      </Grid>

      <Grid style={{marginBottom: 10}}>
        <GridCell span="6">
          {props.packetLossComponent}
        </GridCell>
      
        <GridCell span="6">
          {props.throughputComponent}
        </GridCell>
      </Grid>
    </div>
  );
};

const SingleColumnLayout = (props) => {
  return (
    <div>
      <Grid>
        <GridCell span="12">
          {props.latencyComponent}
        </GridCell>
       
      </Grid>

      <Grid>
        <GridCell span="12">
          {props.latencyVariationComponent}
        </GridCell>
      </Grid>

      <Grid style={{marginBottom: 10}}>
        <GridCell span="12">
          {props.packetLossComponent}
        </GridCell>
      </Grid>

      <Grid style={{marginBottom: 10}}>
        
        <GridCell span="12">
          {props.throughputComponent}
        </GridCell>
      </Grid>
    </div>
  );
};

const NCLayout = (props) => {
  switch(props.layout) {
  case MEEP_COMPONENT_SINGLE_COLUMN_LAYOUT:
    return (
      <SingleColumnLayout {...props} />
    );
  case MEEP_COMPONENT_TABLE_LAYOUT:
    return (
      <TableLayout {...props} />
    );
  default:
    return (
      <TableLayout {...props} />
    );
  }
};

const NCGroup = ({prefix, onUpdate, element}) => {
  const formLabel = (valueName) => {
    const space = prefix ? ' ' : '';
@@ -229,10 +309,8 @@ const NCGroup = ({prefix, onUpdate, element}) => {
    return null;
  }

  return (
    <div>
      <Grid>
        <GridCell span="6">
  const latencyComponent = (
    <>
     <TextField outlined style={{width: '100%'}}
       label={formLabel('Latency') + ' (ms)'}
       onChange={(e) => handleEvent(e, latencyFieldName, validateLatency)}
@@ -245,8 +323,11 @@ const NCGroup = ({prefix, onUpdate, element}) => {
        {getElemFieldErr(element, latencyFieldName)}
      </span>
    </TextFieldHelperText>
        </GridCell>
        <GridCell span="6">
    </>
  );

  const latencyVariationComponent = (
    <>
    <TextField outlined style={{width: '100%'}}
      label={formLabel('Latency Variation') + ' (ms)'}
      onChange={(e) => handleEvent(e, latencyVarFieldName, validateLatencyVariation)}
@@ -259,11 +340,11 @@ const NCGroup = ({prefix, onUpdate, element}) => {
        {getElemFieldErr(element, latencyVarFieldName)}
      </span>
    </TextFieldHelperText>
        </GridCell>
      </Grid>
    </>
  );

      <Grid style={{marginBottom: 10}}>
        <GridCell span="6">
  const packetLossComponent = (
    <>
    <TextField outlined style={{width: '100%'}}
      label={formLabel('Packet Loss') + ' (%)'}
      onChange={(e) =>  handleEvent(e, packetLossFieldName, validatePacketLoss)}
@@ -276,9 +357,11 @@ const NCGroup = ({prefix, onUpdate, element}) => {
        {getElemFieldErr(element, packetLossFieldName)}
      </span>
    </TextFieldHelperText>
    </>
  );

        </GridCell>
        <GridCell span="6">
  const throughputComponent = (
    <>
    <TextField outlined style={{width: '100%'}}
      label={formLabel('Throughput') + ' Mbps'}
      onChange={(e) =>  handleEvent(e, throughputFieldName, validateThroughput)}
@@ -291,9 +374,17 @@ const NCGroup = ({prefix, onUpdate, element}) => {
        {getElemFieldErr(element, throughputFieldName)}
      </span>
    </TextFieldHelperText>
        </GridCell>
      </Grid>
    </div>
    </>
  );

  return (
    <NCLayout
      latencyComponent={latencyComponent}
      latencyVariationComponent={latencyVariationComponent}
      packetLossComponent={packetLossComponent}
      throughputComponent={throughputComponent}
    >
    </NCLayout>
  );
};

+5 −1
Original line number Diff line number Diff line
@@ -117,7 +117,10 @@ import {
  CFG_ELEM_EGRESS_SVC_MAP,

  CFG_BTN_NEW_ELEM,
  CFG_BTN_DEL_ELEM
  CFG_BTN_DEL_ELEM,

  // Layout type
  MEEP_COMPONENT_TABLE_LAYOUT
} from '../../meep-constants';


@@ -475,6 +478,7 @@ const NCGroups = ({prefixes, onUpdate, element}) => {
        element={element}
        prefix={p}
        key={p}
        layout={MEEP_COMPONENT_TABLE_LAYOUT}
      />
    );
  });
+266 −102
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import { Elevation } from '@rmwc/elevation';
// import ReactDOM from 'react-dom';
import { Button } from '@rmwc/button';
import { Checkbox } from '@rmwc/checkbox';
import { Slider } from '@rmwc/slider';
import moment from 'moment';
import * as d3 from 'd3';
import axios from 'axios';
@@ -14,6 +15,9 @@ 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 IDCVis from './idc-vis';
import ResizeableContainer from './resizeable-container';


import {
  idlog
@@ -31,13 +35,17 @@ import {
import {
  execFakeChangeSelectedDestination,
  execChangeSourceNodeSelected,
  execAddMetricsEpoch
  execAddMetricsEpoch,
  execChangeMetricsTimeIntervalDuration,
  execClearMetricsEpochs
} from '../state/exec';

import {
  LATENCY_METRICS,
  THROUGHPUT_METRICS,
  MOBILITY_EVENT
  MOBILITY_EVENT,
  TYPE_EXEC,
  EXEC_STATE_IDLE
} from '../meep-constants';

const VIEW_NAME_NONE = 'none';
@@ -85,8 +93,54 @@ const epochsToSeries = (epochs) => {
  return series;
};

const TimeIntervalConfig = (props) => {
  let  PauseResumeButton = null;
  if (props.metricsPollingStopped) {
    PauseResumeButton = () => (
      <Button outlined
        onClick={() => props.startMetricsPolling()}
      >
        RESUME
      </Button>
    );
  } else {
    PauseResumeButton = () => (
      <Button outlined
        onClick={() => props.stopMetricsPolling()}
      >
        PAUSE
      </Button>
    );
  }
  return (
    <div>
      <Grid>
        <GridCell span={3}>
          <Slider
            value={props.value}
            onChange={e => props.timeIntervalDurationChanged(e.detail.value)}
            discrete
            min={5}
            max={60}
            step={1}
          />
        </GridCell>
        <GridCell span={1}>

        </GridCell>
        <GridCell span={8}>
          <PauseResumeButton />
        </GridCell>
      </Grid>
    </div>
    
    
  );
};

const ConfigurationView = (props) => {
  return (
    <>
    <Grid>
      <GridCell span={2}>
        <IDSelect
@@ -110,7 +164,7 @@ const ConfigurationView = (props) => {
          value={props.view1}
        />
      </GridCell>
      <GridCell span={2}>
      <GridCell span={3}>
        <IDSelect
          label={'Select Source Node'}
          outlined
@@ -121,7 +175,7 @@ const ConfigurationView = (props) => {
          value={props.sourceNodeSelected ? props.sourceNodeSelected.data.id : ''}
        />
      </GridCell>
      <GridCell span={1}>
      <GridCell span={4}>
        <Checkbox
          checked={props.displayEdgeLabels}
          onChange={() => props.changeDisplayEdgeLabels(!props.displayEdgeLabels)}
@@ -129,9 +183,16 @@ const ConfigurationView = (props) => {
                    Show data on edges
        </Checkbox>
      </GridCell>
      <GridCell span={5}>
      <GridCell span={1}>
      </GridCell>
    </Grid>
    <TimeIntervalConfig 
      timeIntervalDurationChanged={(value) => {props.timeIntervalDurationChanged(value);}}
      stopMetricsPolling={props.stopMetricsPolling}
      startMetricsPolling={props.startMetricsPolling}
      metricsPollingStopped={props.metricsPollingStopped}
    />
    </>
  );
};

@@ -145,14 +206,15 @@ const HIERARCHY_VIEW = 'HIERARCHY_VIEW';
const APPS_VIEW = 'APPS_VIEW';
const LATENCY_VIEW = 'LATENCY_VIEW';
const THROUGHPUT_VIEW = 'THROUGHPUT_VIEW';
const VIS_VIEW = 'VIS_VIEW';

const DASHBOARD_VIEWS_LIST = [VIEW_NAME_NONE, HIERARCHY_VIEW, APPS_VIEW, LATENCY_VIEW, THROUGHPUT_VIEW];
const DASHBOARD_VIEWS_LIST = [VIEW_NAME_NONE, VIS_VIEW, APPS_VIEW, LATENCY_VIEW, THROUGHPUT_VIEW, HIERARCHY_VIEW];

const ViewForName = (
  {
    keyForSvg,
    apps,
    colorRange,
    width,
    min,
    max,
    data,
@@ -174,18 +236,26 @@ const ViewForName = (
  switch(viewName) {
  case HIERARCHY_VIEW:
    return (
      <ResizeableContainer key={keyForSvg}>
        {(width, height) => (
          <IDCGraph 
            keyForSvg={keyForSvg}
            width={width}
        height={600}
      />
            height={height}
          />)}
      </ResizeableContainer>
    );
  case APPS_VIEW:
    return (
      <ResizeableContainer key={keyForSvg}>
        {
          (width, height) => (
            <IDCAppsView
              keyForSvg={keyForSvg}
              apps={apps}
              colorRange={colorRange}
              width={width}
        height={600}
              height={height}
              data={data}
              series={series}
              startTime={startTime}
@@ -198,15 +268,22 @@ const ViewForName = (
              }}
              displayEdgeLabels={displayEdgeLabels}
            />
          )
        }
      </ResizeableContainer>
      
    );
  case LATENCY_VIEW:
    return (
      <ResizeableContainer key={keyForSvg}>
        {(width, height) => (
          <IDCLineChart
            keyForSvg={keyForSvg}
            data={dataPoints}
            series={series}
            startTime={startTime}
            mobilityEvents={mobilityEvents}
        width={width} height={600}
            width={width} height={height}
            destinations={appIds}
            colorRange={colorRange}
            selectedSource={selectedSource}
@@ -215,15 +292,23 @@ const ViewForName = (
            max={max}
            colorForApp={colorForApp}
          />
        )
        }
      </ResizeableContainer>
      
    );
  case THROUGHPUT_VIEW:
    return (
      <ResizeableContainer key={keyForSvg}>
        {
          (width, height) => (
            <IDCLineChart
              keyForSvg={keyForSvg}
              data={dataPoints}
              series={series}
              startTime={startTime}
              mobilityEvents={mobilityEvents}
        width={width} height={600}
              width={width} height={height}
              destinations={appIds}
              colorRange={colorRange}
              selectedSource={selectedSource}
@@ -232,6 +317,25 @@ const ViewForName = (
              max={max}
              colorForApp={colorForApp}
            />
          )
        }
      </ResizeableContainer>
    );
  case VIS_VIEW:
    return (
      <ResizeableContainer>
        {
          (width, height) => (
            <IDCVis 
              type={TYPE_EXEC}
              width={width}
              height={height}
              onEditElement={() => {}}
            />
          )
        }
        
      </ResizeableContainer>
    );
  default:
    return null;
@@ -255,6 +359,10 @@ const DashboardConfiguration = (props) => {
        changeSourceNodeSelected={props.changeSourceNodeSelected}
        changeDisplayEdgeLabels={props.changeDisplayEdgeLabels}
        displayEdgeLabels={props.displayEdgeLabels}
        timeIntervalDurationChanged={props.timeIntervalDurationChanged}
        stopMetricsPolling={props.stopMetricsPolling}
        startMetricsPolling={props.startMetricsPolling}
        metricsPollingStopped={props.metricsPollingStopped}
      />
    );
  }
@@ -321,6 +429,8 @@ class DashboardContainer extends Component {
  constructor(props) {
    super(props);

    this.keyForSvg = 0;

    this.state = {
      configurationType: null,
      view1Name: APPS_VIEW,
@@ -329,15 +439,13 @@ class DashboardContainer extends Component {
      nbSecondsToDisplay: 25,
      displayEdgeLabels: false
    };

    this.epochs = [];
  }

  componentDidMount() {
    this.epochCount = 0;
    const nextData = () => {
      this.epochCount += 1;
      this.fetchMetrics();
    };
    this.dataTimer = setInterval(nextData, 1000);
    clearInterval(this.dataTimer);
    this.startMetricsPolling();
  }

  componentWillUnmount() {
@@ -345,8 +453,9 @@ class DashboardContainer extends Component {
  }

  fetchMetrics() {
    const startTime = moment().utc().add(-7, 'seconds').format(TIME_FORMAT);
    const stopTime = moment().utc().add(-6, 'seconds').format(TIME_FORMAT);
    const delta = -7;
    const startTime = moment().utc().add(delta, 'seconds').format(TIME_FORMAT);
    const stopTime = moment().utc().add(delta + 1, 'seconds').format(TIME_FORMAT);
    return axios.get(`${metricsBasePath}/metrics?startTime=${startTime}&stopTime=${stopTime}`)
      .then(res => {

@@ -381,7 +490,45 @@ class DashboardContainer extends Component {
    this.setState({displayEdgeLabels: val});
  }

  changeMetricsTimeIntervalDuration(duration) {
    this.props.changeMetricsTimeIntervalDuration(duration);
  }

  stopMetricsPolling() {
    // clearInterval(this.dataTimer);
    this.setState({metricsPollingStopped: true});
  }
  startMetricsPolling() {
    // this.props.clearMetricsEpochs();
    this.epochCount = 0;
    const nextData = () => {
      this.epochCount += 1;
      this.fetchMetrics();
    };

    if (!this.dataTimer) {
      this.dataTimer = setInterval(nextData, 1000);
    }
    
    this.setState({metricsPollingStopped: false});
  }


  render() {

    if (EXEC_STATE_IDLE === this.props.scenarioState) {
      console.log('Scenario is idle');
    }

    let epochs = null;
    if (!this.state.metricsPollingStopped) {
      this.epochs = this.props.epochs.slice();
      epochs = this.epochs;
    } else {
      epochs = this.epochs;
    }

    this.keyForSvg++;
    const root = this.getRoot();
    const nodes = root.descendants();
   
@@ -410,11 +557,11 @@ class DashboardContainer extends Component {
    };

    // Determine first and last epochs
    const firstEpoch = this.props.epochs.length ? this.props.epochs[0] : {
    const firstEpoch = epochs.length ? epochs[0] : {
      data: [],
      startTime: null
    };
    let lastEpoch = this.props.epochs.length ? this.props.epochs.slice(-1)[0] : {
    let lastEpoch = epochs.length ? epochs.slice(-1)[0] : {
      data: [],
      startTime: null
    };
@@ -422,7 +569,7 @@ class DashboardContainer extends Component {
    // Determine startTime of first epoch and endTime of last epoch
    const startTime = firstEpoch.data.length ? firstEpoch.startTime : null;
    const endTime = lastEpoch.data.length ? moment(lastEpoch.startTime).add(1, 'seconds').format(TIME_FORMAT) : null;
    const series = epochsToSeries(this.props.epochs, selectedSource);
    const series = epochsToSeries(epochs, selectedSource);

    const withTypeAndSource = type => source => point => {
      return point.dataType === type && point.src === source;
@@ -441,37 +588,39 @@ class DashboardContainer extends Component {
    // Mobility events
    const extractPointsOfType = type => epoch => epoch.data.filter(isDataPointOfType(type));
    const extractMobilityEvents = extractPointsOfType(MOBILITY_EVENT);
    const mobilityEvents = this.props.epochs.flatMap(extractMobilityEvents);
    const mobilityEvents = epochs.flatMap(extractMobilityEvents);

    if (mobilityEvents.length) {
      // console.log('Some mobility events ...');
    }
  
    
    const height = 600;
    // const height = 600;

    let span1 = 6;
    let width1 = 700;
    let width2 = 700;
    let span1 = 12;
    let span2 = 12;
    // let width1 = 700;
    // let width2 = 700;

    if (this.state.view1Name === VIEW_NAME_NONE) {
      span1 = 0;
      width1 = 0;
      width2 = 1400;
    }
    const view1Present = this.state.view1Name !== VIEW_NAME_NONE;
    const view2Present = this.state.view2Name !== VIEW_NAME_NONE;

    if (this.state.view2Name === VIEW_NAME_NONE) {
      span1 = 12;
      width1 = 1400;
      width2 = 0;
    if (view1Present && view2Present) {
      span1 = 6;
      span2 = 6;
    } else if (!view1Present && !view2Present) {
      span1 = 0;
      span2 = 0;
    }

    const view1 = (

      <ViewForName
        keyForSvg={this.keyForSvg}
        apps={apps}
        colorRange={colorRange}
        width={width1}
        height={height}
        // width={width1}
        // height={height}
        data={lastEpochData1}
        series={series1}
        startTime={startTime}
@@ -488,10 +637,11 @@ class DashboardContainer extends Component {

    const view2 = (
      <ViewForName
        keyForSvg={this.keyForSvg}
        apps={apps}
        colorRange={colorRange}
        width={width2}
        height={height}
        // width={width2}
        // height={height}
        data={lastEpochData2}
        series={series2}
        startTime={startTime}
@@ -520,6 +670,10 @@ class DashboardContainer extends Component {
          nodeIds={appIds}
          sourceNodeSelected={this.props.sourceNodeSelected}
          changeSourceNodeSelected={(nodeId) => this.props.changeSourceNodeSelected(appMap[nodeId])}
          timeIntervalDurationChanged={(duration) => {this.changeMetricsTimeIntervalDuration(duration);}}
          stopMetricsPolling={() => this.stopMetricsPolling()}
          startMetricsPolling={() => this.startMetricsPolling()}
          metricsPollingStopped={this.state.metricsPollingStopped}
          dashboardViewsList={DASHBOARD_VIEWS_LIST}
          changeView1={(viewName) => this.changeView1(viewName)}
          changeView2={(viewName) => this.changeView2(viewName)}
@@ -529,21 +683,26 @@ class DashboardContainer extends Component {
        
        <Grid>

          <GridCell span={span1} style={{paddingRight: 10}}>
          {!view1Present ? null : (
            <GridCell span={span1} style={{paddingRight: 10}} className='chartContainer'>
              <Elevation z={2}
                style={{padding: 10}}
              >
                {view1}
              </Elevation>
            </GridCell>
          )}
          
          <GridCell span={span1} style={{marginLeft: -10, paddingLeft: 10}}>
          {!view2Present ? null : (
            <GridCell span={span2} style={{marginLeft: -10, paddingLeft: 10}} className='chartContainer'>
              <Elevation z={2}
                style={{padding: 10}}
              >
                {view2}
              </Elevation>
            </GridCell>
         
          )}
        </Grid>
      
      </>
@@ -556,7 +715,10 @@ const mapStateToProps = state => {
    displayedScenario: state.exec.displayedScenario,
    epochs: state.exec.metrics.epochs,
    sourceNodeSelected: state.exec.metrics.sourceNodeSelected,
    dataTypeSelected: state.exec.metrics.dataTypeSelected
    dataTypeSelected: state.exec.metrics.dataTypeSelected,
    eventCreationMode: state.exec.eventCreationMode,
    metricsTimeIntervalDuration: state.exec.metrics.timeIntervalDuration,
    scenarioState: state.exec.state.scenario
  };
};

@@ -564,7 +726,9 @@ const mapDispatchToProps = dispatch => {
  return {
    changeSelectedDestination: (dest) => dispatch(execFakeChangeSelectedDestination(dest)),
    changeSourceNodeSelected: (src) => dispatch(execChangeSourceNodeSelected(src)),
    addMetricsEpoch: (epoch) => dispatch(execAddMetricsEpoch(epoch))
    addMetricsEpoch: (epoch) => dispatch(execAddMetricsEpoch(epoch)),
    changeMetricsTimeIntervalDuration: (duration) => dispatch(execChangeMetricsTimeIntervalDuration(duration)),
    clearMetricsEpochs: () => dispatch(execClearMetricsEpochs())
  };
};

+8 −12
Original line number Diff line number Diff line
@@ -48,8 +48,7 @@ import {
  // Event types
  MOBILITY_EVENT,
  NETWORK_CHARACTERISTICS_EVENT,
  PAGE_EXECUTE,
  PAGE_EXPERIMENTAL_EXECUTE
  PAGE_EXECUTE
} from '../../state/ui';

import {
@@ -60,8 +59,6 @@ import {
} from '../../state/exec';

import {
  TYPE_EXEC,

  // States
  EXEC_STATE_IDLE
} from '../../meep-constants';
@@ -185,9 +182,9 @@ class ExecPageContainer extends Component {

  showApps(show) {
    this.props.changeShowApps(show);
    // _.defer(() => {
    //   this.props.execVis.network.setData(this.props.execVisData);
    // });
    _.defer(() => {
      this.props.execVis.network.setData(this.props.execVisData);
    });
  }

  renderDialogs() {
@@ -223,7 +220,7 @@ class ExecPageContainer extends Component {
  }

  render() {
    if (this.props.page !== PAGE_EXECUTE && this.props.page !== PAGE_EXPERIMENTAL_EXECUTE) {
    if (this.props.page !== PAGE_EXECUTE) {
      return null;
    }

@@ -231,8 +228,8 @@ class ExecPageContainer extends Component {
      ? this.props.execScenarioName
      : this.props.cfgScenarioName;

    const spanLeft = this.props.eventCreationMode ? 8 : 12;
    const spanRight = this.props.eventCreationMode ? 4 : 0;
    const spanLeft = this.props.eventCreationMode ? 10 : 12;
    const spanRight = this.props.eventCreationMode ? 2 : 0;
    return (
      <div style={{width: '100%'}}>
        {this.renderDialogs()}
@@ -275,8 +272,7 @@ class ExecPageContainer extends Component {
                <GridCell span={spanLeft}>
                  {/* <Elevation className="component-style" z={2}> */}
                  <div>
                    {this.props.experimental ? (<DashboardContainer showAppsView={true}/>) : (<IDCVis type={TYPE_EXEC} />)}
                        
                    <DashboardContainer showAppsView={true}/>
                  </div>
                  {/* </Elevation> */}
                </GridCell>
+75 −65
Original line number Diff line number Diff line
@@ -44,6 +44,40 @@ class MobilityEventPane extends Component {
    };
  }

  shouldComponentUpdate(nextProps, nextState) {

    /**
     * element={props.element}
        eventTypes={props.eventTypes}
        api={props.api}
        onSuccess={props.onSuccess}
        onClose={props.onClose}
        currentEvent={props.currentEvent}
        UEs={props.UEs}
        POAs={props.POAs}
        EDGEs={props.EDGEs}
        FOGs={props.FOGs}
        ZONEs={props.ZONEs}
        MobTypes={props.MobTypes}
        FogEdges={props.FogEdges}
        EdgeApps={props.EdgeApps}
     */
    return this.props.api !== nextProps.api
      || this.props.element !== nextProps.element
      || this.props.api !== nextProps.api
      || this.props.currentEvent !== nextProps.currentEvent
      || this.props.UEs !== nextProps.UEs
      || this.props.POAs !== nextProps.POAs
      || this.props.EDGEs !== nextProps.EDGEs
      || this.props.FOGs !== nextProps.FOGs
      || this.props.ZONEs !== nextProps.ZONEs
      || this.props.MobTypes !== nextProps.MobTypes
      || this.props.FogEdges !== nextProps.FogEdges
      || this.props.EdgeApps !== nextProps.EdgeApps
      || this.state.eventTarget !== nextState.eventTarget;
      
  }

  triggerEvent(e) {
    e.preventDefault();
    var meepEvent = {
@@ -65,38 +99,9 @@ class MobilityEventPane extends Component {

  render() {

    //check with list the target belongs to
    if (this.values.eventTarget === undefined || this.values.eventTarget === '') {
      return (
        <div>
          <Grid style={styles.field}>
            <GridCell span="8">
              <Select
                style={styles.select}
                label="Target"
                outlined
                options={_.map(this.props.MobTypes, elem => getElemFieldVal(elem, FIELD_NAME))}
                onChange={(event)=>{this.values['eventTarget'] = event.target.value;}}
                data-cy={EXEC_EVT_MOB_TARGET}
              />
            </GridCell>
            <GridCell span="4">
            </GridCell>
          </Grid>

          <CancelApplyPair
            cancelText="Close"
            applyText="Submit"
            onCancel={this.props.onClose}
            onApply={(e) => this.triggerEvent(e)}
          />
        </div>
      );
    }

    //let found = this.props.UEs.find(element => element.label == this.values.eventTarget);
    //find if its the selection was a UE, otherwise (in order) EDGE, FOG, EDGE-APP, UE-APP
    var target = this.values.eventTarget;
    var target = this.state.eventTarget;
    var found = this.props.UEs.find(function(element) {
      return element.label === target;
    });
@@ -127,8 +132,10 @@ class MobilityEventPane extends Component {
        }
      }
    }
  
    return (
      <div>
        <>
      <Grid style={styles.field}>
        <GridCell span="8">
          <Select
@@ -136,7 +143,10 @@ class MobilityEventPane extends Component {
            label="Target"
            outlined
            options={_.map(this.props.MobTypes, elem => getElemFieldVal(elem, FIELD_NAME))}
              onChange={(event)=>{this.values['eventTarget'] = event.target.value;}}
            onChange={(event)=>{
              this.values['eventTarget'] = event.target.value;
              this.setState({eventTarget: event.target.value});
            }}
            data-cy={EXEC_EVT_MOB_TARGET}
          />
        </GridCell>
@@ -150,20 +160,20 @@ class MobilityEventPane extends Component {
            label="Destination"
            outlined
            options={_.map(populateDestination, elem => getElemFieldVal(elem, FIELD_NAME))}
              onChange={(event)=>{this.values['eventDestination'] = event.target.value;}}
            onChange={(event)=>{this.values['eventDestination'] = event.target.value; this.setState({eventDestination: event.target.value});}}
            data-cy={EXEC_EVT_MOB_DEST}
          />
        </GridCell>
        <GridCell span="4">
        </GridCell>
      </Grid>

      <CancelApplyPair
        cancelText="Close"
        applyText="Submit"
        onCancel={this.props.onClose}
        onApply={(e) => this.triggerEvent(e)}
      />
      </>
      </div>
    );
  }
Loading