Rift.IO OSM R1 Initial Submission
[osm/UI.git] / skyquake / plugins / composer / src / src / components / EditorForwardingGraph / mapClassifier.js
diff --git a/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/mapClassifier.js b/skyquake/plugins/composer/src/src/components/EditorForwardingGraph/mapClassifier.js
new file mode 100644 (file)
index 0000000..bcd1918
--- /dev/null
@@ -0,0 +1,203 @@
+/**
+ * Created by onvelocity on 3/2/16.
+ */
+
+'use strict';
+
+import d3 from 'd3'
+import React from 'react'
+import Button from '../Button'
+import LayoutRow from '../LayoutRow'
+import ContentEditableDiv from '../ContentEditableDiv'
+import changeCase from 'change-case'
+import ClassNames from 'classnames'
+import DescriptorModelFactory from '../../libraries/model/DescriptorModelFactory'
+import DescriptorModelMetaFactory from '../../libraries/model/DescriptorModelMetaFactory'
+import HighlightRecordServicePaths from '../../libraries/graph/HighlightRecordServicePaths'
+import ComposerAppActions from '../../actions/ComposerAppActions'
+import CatalogItemsActions from '../../actions/CatalogItemsActions'
+import SelectionManager from '../../libraries/SelectionManager'
+import DeletionManager from '../../libraries/DeletionManager'
+import TooltipManager from '../../libraries/TooltipManager'
+import ConnectionPointSelector from './ConnectionPointSelector'
+import mapConnectionPoint from './mapConnectionPoint'
+import EditableProperty from './EditableProperty'
+import onCutDelegateToRemove from './onCutDelegateToRemove'
+import onClickSelectAndShowInDetailsPanel from './onClickSelectAndShowInDetailsPanel'
+import onFormInputChangedModifyContainerAndNotify from './onFormInputChangedModifyContainerAndNotify'
+
+import imgNSD from '../../images/default-catalog-icon.svg'
+import imgFG from '../../../../node_modules/open-iconic/svg/infinity.svg'
+import imgRemove from '../../../../node_modules/open-iconic/svg/trash.svg'
+import imgAdd from '../../../../node_modules/open-iconic/svg/plus.svg'
+import imgConnection from '../../../../node_modules/open-iconic/svg/random.svg'
+import imgClassifier from '../../../../node_modules/open-iconic/svg/spreadsheet.svg'
+import imgReorder from '../../../../node_modules/open-iconic/svg/menu.svg'
+
+export default function mapClassifier(context, classifier, i) {
+
+       // todo if a classifier is linked to an rsp then highlight it
+       //rsp.uiState.showPath = rsp.uiState.hasOwnProperty('showPath') ? rsp.uiState.showPath : true;
+
+       function onInputUpdateModel(context, attr, name, event) {
+               event.preventDefault();
+               attr.setFieldValue(name, event.target.value);
+               CatalogItemsActions.catalogItemDescriptorChanged(attr.getRoot());
+       }
+
+       function onClickAddNewMatchAttributes(context, classifier) {
+               event.preventDefault();
+               event.stopPropagation();
+               const newMatchAttr = classifier.createMatchAttributes();
+               SelectionManager.disableOutlineChanges();
+               CatalogItemsActions.catalogItemDescriptorChanged(classifier.getRoot());
+               setTimeout(() => {
+                       SelectionManager.enableOutlineChanges();
+                       SelectionManager.select(newMatchAttr);
+                       SelectionManager.refreshOutline();
+                       const input = Array.from(document.querySelectorAll(`tr[data-uid="${newMatchAttr.uid}"] input`)).forEach((element, index) => {
+                               // index 0 is hidden id field
+                               if (index === 1) {
+                                       element.focus();
+                               }
+                       });
+               }, 100);
+       }
+
+       function mapClassifierMatchAttributes(context, matchAttributes, key) {
+               const fields = matchAttributes.fieldNames.map((name, i) => {
+                       return (
+                               <td key={i} className={name + '-property'}>
+                                       <div className="match-attr-name">{name}</div>
+                                       <ContentEditableDiv value={matchAttributes.getFieldValue(name)}
+                                                                               onBlur={() => DeletionManager.addEventListeners()}
+                                                                               onClick={event => {
+                                                                                       event.preventDefault();
+                                                                                       SelectionManager.select(matchAttributes);
+                                                                                       SelectionManager.refreshOutline();
+                                                                               }}
+                                                                               onCut={event => {
+                                                                                       event.stopPropagation();
+                                                                               }}
+                                                                               onChange={onInputUpdateModel.bind(null, context, matchAttributes, name)}
+                                                                               className="match-attr-value"/>
+                               </td>
+                       );
+               });
+               return (
+                       <tr key={key}
+                               data-uid={matchAttributes.uid}
+                               onCut={event => {
+                                       event.stopPropagation();
+                                       matchAttributes.remove();
+                                       CatalogItemsActions.catalogItemDescriptorChanged(matchAttributes.getRoot());
+                                       SelectionManager.refreshOutline();
+                               }}>
+                               {fields}
+                       </tr>
+               )
+       }
+
+       function buildRecordServicePathSelector(classifier) {
+               const rspId = classifier.model['rsp-id-ref'];
+               const options = [{}].concat(classifier.parent.recordServicePaths).map((rsp, i) => {
+                       return (
+                               <option key={i} name="rsp-id-ref" value={rsp.id}>{rsp.title}</option>
+                       )
+               });
+               return (
+                       <select name="rsp-id-ref" value={rspId} onChange={onFormInputChangedModifyContainerAndNotify.bind(null, classifier)}>{options}</select>
+               )
+       }
+
+       function onClickExitPathEdithMode(component, event) {
+               event.preventDefault();
+               component.setState({editClassifierConnectionPointRef: false});
+       }
+
+       function onClickAddConnectionPointRef(component, classifier, connector, event) {
+               event.preventDefault();
+               classifier.addVnfdConnectionPoint(connector);
+               CatalogItemsActions.catalogItemDescriptorChanged(classifier.getRoot());
+       }
+
+       function onClickOpenConnectionPointSelector(component, classifier, event) {
+               component.setState({editClassifierConnectionPointRef: classifier.uid});
+               function closeAndRemoveHandler() {
+                       component.setState({editClassifierConnectionPointRef: false});
+                       document.body.removeEventListener('click', closeAndRemoveHandler, true);
+               }
+               document.body.addEventListener('click', closeAndRemoveHandler, true);
+       }
+
+       const attributeNames = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.vnffgd.classifier.match-attributes');
+
+       const selectedConnectionPoint = classifier.uiState.vnfdRef ? `${classifier.uiState.vnfdRef.name}/${classifier.vnfdConnectionPointRef.vnfdIndex}/${classifier.vnfdConnectionPointRef.vnfdConnectionPointName}` : '';
+
+       const isEditClassifierConnectionPointRef = context.component.state.editClassifierConnectionPointRef === classifier.uid;
+
+       const hasClassifierServiceFunctionVNFDs = context.containers.filter(d => DescriptorModelFactory.isConstituentVnfdWithServiceChain(d, 'CLASSIFIER')).length > 0;
+
+       return (
+               <LayoutRow key={classifier.uid}
+                                  data-uid={classifier.uid}
+                                  data-offset-width="true"
+                                  className={ClassNames('fg-classifier', classifier.className, {'-is-edit-classifier-connection-point-ref': isEditClassifierConnectionPointRef})}
+                                  onClick={onClickSelectAndShowInDetailsPanel.bind(null, classifier)}>
+                       <div className="classifier-properties">
+                               <div className="classifier-property">
+                                       <EditableProperty title="name">
+                                               <ContentEditableDiv name="name"
+                                                                                       value={classifier.name}
+                                                                                       autoPadRight="true"
+                                                                                       onBlur={() => DeletionManager.addEventListeners()}
+                                                                                       onChange={onFormInputChangedModifyContainerAndNotify.bind(null, classifier)}
+                                                                                       className="classifier-name" />
+                                       </EditableProperty>
+                               </div>
+                               <div className="classifier-property">
+                                       <EditableProperty title="path">
+                                               {buildRecordServicePathSelector(classifier)}
+                                       </EditableProperty>
+                               </div>
+                               <div className="classifier-property">
+                                       <EditableProperty title="connection point ref" disabled={!hasClassifierServiceFunctionVNFDs}>
+                                               <ContentEditableDiv autoPadRight="true"
+                                                                                       value={selectedConnectionPoint}
+                                                                                       disabled={!hasClassifierServiceFunctionVNFDs}
+                                                                                       onChange={() => {}}
+                                                                                       onClick={onClickOpenConnectionPointSelector.bind(null, context.component, classifier)} />
+                                       </EditableProperty>
+                                       <div className="select-connection-point-ref">
+                                               <ConnectionPointSelector containers={context.containers}
+                                                                                                style={context.styleSecondary}
+                                                                                                serviceChain="CLASSIFIER"
+                                                                                                isDisabled={!hasClassifierServiceFunctionVNFDs}
+                                                                                                onExitEditPathMode={onClickExitPathEdithMode.bind(null, context.component)}
+                                                                                                onAddConnectionPointRef={onClickAddConnectionPointRef.bind(null, context.component, classifier)}
+                                               />
+                                       </div>
+                                       {!hasClassifierServiceFunctionVNFDs ? <div className="hint">A VNFD with the chain CLASSIFIER is required to add a connection point ref.</div> : ''}
+                               </div>
+                       </div>
+                       <table className="classifier-match-attributes">
+                               <thead>
+                                       <tr>
+                                               {attributeNames.map((name, i) => <th key={i} className={ClassNames(name + '-property')}>{changeCase.title(name)}</th>)}
+                                       </tr>
+                               </thead>
+                               <tbody>
+                                       {classifier.matchAttributes.map(mapClassifierMatchAttributes.bind(null, context))}
+                               </tbody>
+                               <tfoot>
+                                       <tr className="xfooter-actions">
+                                               <th colSpan={attributeNames.length} className="row-action-column">
+                                                       <Button className="create-new-match-attributes" src={imgAdd} width="20px" onClick={onClickAddNewMatchAttributes.bind(null, context, classifier)} label="Add Match Attributes" />
+                                               </th>
+                                       </tr>
+                               </tfoot>
+                       </table>
+               </LayoutRow>
+       );
+
+}