Commit 8847946d authored by Simon Pastor's avatar Simon Pastor
Browse files

feature ready

parent 18dac65d
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019  InterDigital Communications, Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import React from 'react';
import { Grid, GridInner, GridCell } from '@rmwc/grid';
import { Button } from '@rmwc/button';
import { MEEP_BTN_CANCEL, MEEP_BTN_APPLY, MEEP_BTN_DUPLICATE } from '../../meep-constants';

const buttonStyles = {
  marginRight: 10
};

const CancelApplyTriplet = props => {
  return (
    <Grid style={{ marginTop: 10 }}>
      <GridInner align={'right'}>
        <GridCell span={12}>
          <Button
            outlined
            style={buttonStyles}
            onClick={props.onCancel}
            data-cy={MEEP_BTN_CANCEL}
          >
            {props.cancelText ? props.cancelText : 'Cancel'}
          </Button>
          <Button
            outlined
            style={buttonStyles}
            onClick={props.onApply}
            disabled={props.saveDisabled}
            data-cy={MEEP_BTN_APPLY}
          >
            {props.applyText ? props.applyText : 'Apply'}
          </Button>
          <Button
            outlined
            style={buttonStyles}
            onClick={props.onDuplicate}
            disabled={props.duplicateDisabled}
            data-cy={MEEP_BTN_DUPLICATE}
          >
            {props.duplicateText ? props.duplicateText : 'Duplicate'}
          </Button>
        </GridCell>
      </GridInner>
    </Grid>
  );
};

export default CancelApplyTriplet;
+35 −5
Original line number Diff line number Diff line
@@ -25,8 +25,10 @@ import { Checkbox } from '@rmwc/checkbox';
import { Typography } from '@rmwc/typography';

import { updateObject } from '../../util/object-util';
import { createUniqueName } from '../../util/elem-utils';

import IDSelect from '../../components/helper-components/id-select';
import CancelApplyPair from '../../components/helper-components/cancel-apply-pair';
import CancelApplyTriplet from '../../components/helper-components/cancel-apply-triplet';
import NCGroup from '../../components/helper-components/nc-group';

import {
@@ -56,7 +58,12 @@ import {
  setElemFieldErr
} from '../../util/elem-utils';

import { CFG_ELEM_MODE_EDIT, cfgElemUpdate } from '../../state/cfg';
import {
  CFG_ELEM_MODE_EDIT,
  CFG_ELEM_MODE_DUPLICATE,
  cfgElemUpdate,
  cfgElemDuplicate
} from '../../state/cfg';

import {
  TYPE_CFG,
@@ -1064,6 +1071,17 @@ export class CfgNetworkElementContainer extends Component {
    this.props.cfgElemUpdate(updatedElem);
  }

  // Element duplicate handler
  onDuplicateElement(newName) {
    var duplicatedElem = updateObject({}, this.props.configuredElement);
    setElemFieldVal(duplicatedElem, FIELD_NAME, newName);
    setElemFieldVal(duplicatedElem, FIELD_PARENT, null);
    var elementType = getElemFieldVal(duplicatedElem, FIELD_TYPE);
    duplicatedElem.parentElements = this.elementsOfType(getParentTypes(elementType));

    this.props.cfgElemDuplicate(duplicatedElem);
  }

  // Retrieve names of elements with matching type
  elementsOfType(types) {
    return _.chain(this.props.tableData)
@@ -1155,11 +1173,21 @@ export class CfgNetworkElementContainer extends Component {
              {this.props.errorMessage}
            </div>

            <CancelApplyPair
            <CancelApplyTriplet
              duplicateDisabled={
                (element && this.props.configMode === CFG_ELEM_MODE_EDIT && this.props.isModified === false)
                  ? false
                  : true
              }
              saveDisabled={(this.props.isModified === false) ? true : false}
              onCancel={this.props.onCancelElement}
              onApply={() => {
                this.props.onSaveElement(element);
                (this.props.configMode === CFG_ELEM_MODE_DUPLICATE) ? this.props.onDuplicateElement(element) : this.props.onSaveElement(element);
              }}
              onDuplicate={() => {
                this.onDuplicateElement(createUniqueName(this.props.tableData, getElemFieldVal(element, FIELD_NAME) + '-copy'));
              }}

            />
          </>
        )}
@@ -1192,13 +1220,15 @@ const mapStateToProps = state => {
    tableData: state.cfg.table.entries,
    configuredElement: state.cfg.elementConfiguration.configuredElement,
    configMode: state.cfg.elementConfiguration.configurationMode,
    isModified: state.cfg.elementConfiguration.isModified,
    errorMessage: state.cfg.elementConfiguration.errorMessage
  };
};

const mapDispatchToProps = dispatch => {
  return {
    cfgElemUpdate: element => dispatch(cfgElemUpdate(element))
    cfgElemUpdate: element => dispatch(cfgElemUpdate(element)),
    cfgElemDuplicate: element => dispatch(cfgElemDuplicate(element))
  };
};

+130 −3
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import { Elevation } from '@rmwc/elevation';
import IDCVis from '../idc-vis';
import CfgNetworkElementContainer from './cfg-network-element-container';
import CfgPageScenarioButtons from './cfg-page-scenario-buttons';
import { deepCopy } from '../../util/object-util';
import { getElementFromScenario } from '../../util/scenario-utils';

import HeadlineBar from '../../components/headline-bar';
import CfgTable from './cfg-table';
@@ -40,7 +42,8 @@ import {
  cfgChangeScenario,
  cfgChangeScenarioList,
  cfgChangeState,
  CFG_ELEM_MODE_NEW
  CFG_ELEM_MODE_NEW,
  CFG_ELEM_MODE_EDIT
} from '../../state/cfg';

import {
@@ -58,7 +61,9 @@ import {
  CFG_STATE_NEW,
  CFG_STATE_IDLE,
  PAGE_CONFIGURE,
  ELEMENT_TYPE_SCENARIO
  ELEMENT_TYPE_SCENARIO,
  COMMON_ZONE_TYPE_STR,
  DEFAULT_NL_TYPE_STR
} from '../../meep-constants';

import {
@@ -69,7 +74,9 @@ import {
  FIELD_EXT_PORT,
  FIELD_GPU_COUNT,
  FIELD_GPU_TYPE,
  getElemFieldVal
  getElemFieldVal,
  setElemFieldVal,
  createUniqueName
} from '../../util/elem-utils';

import { pipe, filter } from '../../util/functional';
@@ -141,6 +148,125 @@ class CfgPageContainer extends Component {
    this.props.cfgElemClear();
  }

  // DUPLICATE ELEMENT, return new element name
  duplicateElement(element, newParentName, isRoot) {
    let newElement = deepCopy(element);

    var name = getElemFieldVal(element, FIELD_NAME);
    if (isRoot === false) {
      name = createUniqueName(this.props.cfg.table.entries, name + '-copy');
      setElemFieldVal(newElement, FIELD_NAME, name);
    }
    setElemFieldVal(newElement, FIELD_PARENT, newParentName);

    // add new element to scenario
    // new id and label will be created as part of the addNewElementToScenario called by newScenarioElem
    this.props.newScenarioElem(newElement);
    return name;
  }

  // DUPLICATE
  onDuplicateElement(element) {
    // Validate network element
    if (this.validateNetworkElement(element) === false) {
      return;
    }

    // browse to find the root of the tree to duplicate

    var inDuplicateBranch = false;
    var newZoneRootParentName = '';
    var newNlRootParentName = '';
    var newPlRootParentName = '';
    var newProcessRootParentName = '';
    var elementFromScenario;

    var scenario = this.props.cfg.scenario;
    // Domains
    for (var i in scenario.deployment.domains) {
      var domain = scenario.deployment.domains[i];

      // Add domain to graph and table (ignore public domain)
      if (domain.id === element.id) {
        newZoneRootParentName = this.duplicateElement(element, getElemFieldVal(element, FIELD_PARENT), true); 
        inDuplicateBranch = true;
      }

      // Zones
      for (var j in domain.zones) {
        var zone = domain.zones[j];

        if (inDuplicateBranch) {
          if (zone.name.indexOf(COMMON_ZONE_TYPE_STR) !== -1) {
            newNlRootParentName = newZoneRootParentName + COMMON_ZONE_TYPE_STR;
          } else {
            elementFromScenario = getElementFromScenario(scenario, zone.name);
            newNlRootParentName = this.duplicateElement(elementFromScenario, newZoneRootParentName, false);
          }
        } else {
          if (zone.id === element.id) {
            newNlRootParentName = this.duplicateElement(element, getElemFieldVal(element, FIELD_PARENT), true);
            inDuplicateBranch = true;
          }
        }

        // Network Locations
        for (var k in zone.networkLocations) {
          var nl = zone.networkLocations[k];

          if (inDuplicateBranch) {
            if (nl.name.indexOf(DEFAULT_NL_TYPE_STR) !== -1) {
              newPlRootParentName = newNlRootParentName;
            } else {
              elementFromScenario = getElementFromScenario(scenario, nl.name);
              newPlRootParentName = this.duplicateElement(elementFromScenario, newNlRootParentName, false);
            }
          } else {
            if (nl.id === element.id) {
              newPlRootParentName = this.duplicateElement(element, getElemFieldVal(element, FIELD_PARENT, true));
              inDuplicateBranch = true;
            }
          }

          // Physical Locations
          for (var l in nl.physicalLocations) {
            var pl = nl.physicalLocations[l];

            if (inDuplicateBranch) {
              elementFromScenario = getElementFromScenario(scenario, pl.name);
              newProcessRootParentName = this.duplicateElement(elementFromScenario, newPlRootParentName, false);
            } else {
              if (pl.id === element.id) {
                newProcessRootParentName = this.duplicateElement(element, getElemFieldVal(element, FIELD_PARENT, true));
                inDuplicateBranch = true;
              }
            }

            // Processes
            for (var m in pl.processes) {
              var proc = pl.processes[m];

              if (inDuplicateBranch) {
                elementFromScenario = getElementFromScenario(scenario, proc.name);
                this.duplicateElement(elementFromScenario, newProcessRootParentName, false);
              } else {
                if (proc.id === element.id) {
                  this.duplicateElement(element, getElemFieldVal(element, FIELD_PARENT, true));
                }
              }
            }
          }
        }
      }

      if(inDuplicateBranch) {
        break;
      }
    }

    this.props.cfgElemClear();
  }

  // DELETE
  onDeleteElement(element) {
    this.props.deleteScenarioElem(element);
@@ -622,6 +748,7 @@ class CfgPageContainer extends Component {
                      onNewElement={() => this.onNewElement()}
                      onSaveElement={elem => this.onSaveElement(elem)}
                      onDeleteElement={elem => this.onDeleteElement(elem)}
                      onDuplicateElement={elem => this.onDuplicateElement(elem)}
                      onCancelElement={() => this.onCancelElement()}
                    />
                  </Elevation>
+2 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ export const MEEP_TAB_SET = 'meep-tab-set';
export const MEEP_LBL_SCENARIO_NAME = 'meep-lbl-scenario-name';
export const MEEP_BTN_CANCEL = 'meep-btn-cancel';
export const MEEP_BTN_APPLY = 'meep-btn-apply';
export const MEEP_BTN_DUPLICATE = 'meep-btn-duplicate';

// Dialog IDs
export const MEEP_DLG_NEW_SCENARIO = 'meep-dlg-new-scenario';
@@ -157,7 +158,7 @@ export const DEFAULT_PACKET_LOSS_INTRA_ZONE = 0;
export const DEFAULT_LATENCY_TERMINAL_LINK = 1;
export const DEFAULT_LATENCY_JITTER_TERMINAL_LINK = 1;
export const DEFAULT_THROUGHPUT_TERMINAL_LINK = 1000;
export const DEFAULT_PACKET_LOSS_TERMINAL_LINK = 1;
export const DEFAULT_PACKET_LOSS_TERMINAL_LINK = 0;
export const DEFAULT_LATENCY_LINK = 0;
export const DEFAULT_LATENCY_JITTER_LINK = 0;
export const DEFAULT_THROUGHPUT_LINK = 1000;
+26 −3
Original line number Diff line number Diff line
@@ -19,12 +19,14 @@ import { createElem } from '../../util/elem-utils';

const CFG_ELEM_NEW = 'CFG_ELEM_NEW';
const CFG_ELEM_EDIT = 'CFG_ELEM_EDIT';
const CFG_ELEM_DUPLICATE = 'CFG_ELEM_DUPLICATE';
const CFG_ELEM_CLEAR = 'CFG_ELEM_CLEAR';
const CFG_ELEM_UPDATE = 'CFG_ELEM_UPDATE';
const CFG_ELEM_SET_ERR_MSG = 'CFG_ELEM_SET_ERR_MSG';

const CFG_ELEM_MODE_NEW = 'CFG_ELEM_MODE_NEW';
const CFG_ELEM_MODE_EDIT = 'CFG_ELEM_MODE_EDIT';
const CFG_ELEM_MODE_DUPLICATE = 'CFG_ELEM_MODE_DUPLICATE';

function cfgElemNew() {
  return {
@@ -39,6 +41,13 @@ function cfgElemEdit(elem) {
  };
}

function cfgElemDuplicate(elem) {
  return {
    type: CFG_ELEM_DUPLICATE,
    payload: elem
  };
}

function cfgElemClear() {
  return {
    type: CFG_ELEM_CLEAR
@@ -62,16 +71,19 @@ function cfgElemSetErrMsg(msg) {
export {
  cfgElemNew,
  cfgElemEdit,
  cfgElemDuplicate,
  cfgElemClear,
  cfgElemUpdate,
  cfgElemSetErrMsg,
  CFG_ELEM_MODE_NEW,
  CFG_ELEM_MODE_EDIT
  CFG_ELEM_MODE_EDIT,
  CFG_ELEM_MODE_DUPLICATE
};

const initialState = {
  configuredElement: null,
  configurationMode: null,
  isModified: false,
  errorMessage: ''
};

@@ -87,12 +99,23 @@ export function cfgElementConfigurationReducer(state = initialState, action) {
    return updateObject(state, {
      configuredElement: action.payload,
      configurationMode: CFG_ELEM_MODE_EDIT,
      errorMessage: ''
      errorMessage: '',
      isModified: false
    });
  case CFG_ELEM_DUPLICATE:
    return updateObject(state, {
      configuredElement: action.payload,
      configurationMode: CFG_ELEM_MODE_DUPLICATE,
      errorMessage: '',
      isModified: true
    });
  case CFG_ELEM_CLEAR:
    return updateObject(state, initialState);
  case CFG_ELEM_UPDATE:
    return updateObject(state, { configuredElement: action.payload });
    return updateObject(state, { 
      configuredElement: action.payload,
      isModified: true
    });
  case CFG_ELEM_SET_ERR_MSG:
    return updateObject(state, { errorMessage: action.payload });
  default:
Loading