bcd1918bcc7d09a04fb63aec4d211d51423a1f7e
[osm/riftware.git] /
1 /**
2  * Created by onvelocity on 3/2/16.
3  */
4
5 'use strict';
6
7 import d3 from 'd3'
8 import React from 'react'
9 import Button from '../Button'
10 import LayoutRow from '../LayoutRow'
11 import ContentEditableDiv from '../ContentEditableDiv'
12 import changeCase from 'change-case'
13 import ClassNames from 'classnames'
14 import DescriptorModelFactory from '../../libraries/model/DescriptorModelFactory'
15 import DescriptorModelMetaFactory from '../../libraries/model/DescriptorModelMetaFactory'
16 import HighlightRecordServicePaths from '../../libraries/graph/HighlightRecordServicePaths'
17 import ComposerAppActions from '../../actions/ComposerAppActions'
18 import CatalogItemsActions from '../../actions/CatalogItemsActions'
19 import SelectionManager from '../../libraries/SelectionManager'
20 import DeletionManager from '../../libraries/DeletionManager'
21 import TooltipManager from '../../libraries/TooltipManager'
22 import ConnectionPointSelector from './ConnectionPointSelector'
23 import mapConnectionPoint from './mapConnectionPoint'
24 import EditableProperty from './EditableProperty'
25 import onCutDelegateToRemove from './onCutDelegateToRemove'
26 import onClickSelectAndShowInDetailsPanel from './onClickSelectAndShowInDetailsPanel'
27 import onFormInputChangedModifyContainerAndNotify from './onFormInputChangedModifyContainerAndNotify'
28
29 import imgNSD from '../../images/default-catalog-icon.svg'
30 import imgFG from '../../../../node_modules/open-iconic/svg/infinity.svg'
31 import imgRemove from '../../../../node_modules/open-iconic/svg/trash.svg'
32 import imgAdd from '../../../../node_modules/open-iconic/svg/plus.svg'
33 import imgConnection from '../../../../node_modules/open-iconic/svg/random.svg'
34 import imgClassifier from '../../../../node_modules/open-iconic/svg/spreadsheet.svg'
35 import imgReorder from '../../../../node_modules/open-iconic/svg/menu.svg'
36
37 export default function mapClassifier(context, classifier, i) {
38
39         // todo if a classifier is linked to an rsp then highlight it
40         //rsp.uiState.showPath = rsp.uiState.hasOwnProperty('showPath') ? rsp.uiState.showPath : true;
41
42         function onInputUpdateModel(context, attr, name, event) {
43                 event.preventDefault();
44                 attr.setFieldValue(name, event.target.value);
45                 CatalogItemsActions.catalogItemDescriptorChanged(attr.getRoot());
46         }
47
48         function onClickAddNewMatchAttributes(context, classifier) {
49                 event.preventDefault();
50                 event.stopPropagation();
51                 const newMatchAttr = classifier.createMatchAttributes();
52                 SelectionManager.disableOutlineChanges();
53                 CatalogItemsActions.catalogItemDescriptorChanged(classifier.getRoot());
54                 setTimeout(() => {
55                         SelectionManager.enableOutlineChanges();
56                         SelectionManager.select(newMatchAttr);
57                         SelectionManager.refreshOutline();
58                         const input = Array.from(document.querySelectorAll(`tr[data-uid="${newMatchAttr.uid}"] input`)).forEach((element, index) => {
59                                 // index 0 is hidden id field
60                                 if (index === 1) {
61                                         element.focus();
62                                 }
63                         });
64                 }, 100);
65         }
66
67         function mapClassifierMatchAttributes(context, matchAttributes, key) {
68                 const fields = matchAttributes.fieldNames.map((name, i) => {
69                         return (
70                                 <td key={i} className={name + '-property'}>
71                                         <div className="match-attr-name">{name}</div>
72                                         <ContentEditableDiv value={matchAttributes.getFieldValue(name)}
73                                                                                 onBlur={() => DeletionManager.addEventListeners()}
74                                                                                 onClick={event => {
75                                                                                         event.preventDefault();
76                                                                                         SelectionManager.select(matchAttributes);
77                                                                                         SelectionManager.refreshOutline();
78                                                                                 }}
79                                                                                 onCut={event => {
80                                                                                         event.stopPropagation();
81                                                                                 }}
82                                                                                 onChange={onInputUpdateModel.bind(null, context, matchAttributes, name)}
83                                                                                 className="match-attr-value"/>
84                                 </td>
85                         );
86                 });
87                 return (
88                         <tr key={key}
89                                 data-uid={matchAttributes.uid}
90                                 onCut={event => {
91                                         event.stopPropagation();
92                                         matchAttributes.remove();
93                                         CatalogItemsActions.catalogItemDescriptorChanged(matchAttributes.getRoot());
94                                         SelectionManager.refreshOutline();
95                                 }}>
96                                 {fields}
97                         </tr>
98                 )
99         }
100
101         function buildRecordServicePathSelector(classifier) {
102                 const rspId = classifier.model['rsp-id-ref'];
103                 const options = [{}].concat(classifier.parent.recordServicePaths).map((rsp, i) => {
104                         return (
105                                 <option key={i} name="rsp-id-ref" value={rsp.id}>{rsp.title}</option>
106                         )
107                 });
108                 return (
109                         <select name="rsp-id-ref" value={rspId} onChange={onFormInputChangedModifyContainerAndNotify.bind(null, classifier)}>{options}</select>
110                 )
111         }
112
113         function onClickExitPathEdithMode(component, event) {
114                 event.preventDefault();
115                 component.setState({editClassifierConnectionPointRef: false});
116         }
117
118         function onClickAddConnectionPointRef(component, classifier, connector, event) {
119                 event.preventDefault();
120                 classifier.addVnfdConnectionPoint(connector);
121                 CatalogItemsActions.catalogItemDescriptorChanged(classifier.getRoot());
122         }
123
124         function onClickOpenConnectionPointSelector(component, classifier, event) {
125                 component.setState({editClassifierConnectionPointRef: classifier.uid});
126                 function closeAndRemoveHandler() {
127                         component.setState({editClassifierConnectionPointRef: false});
128                         document.body.removeEventListener('click', closeAndRemoveHandler, true);
129                 }
130                 document.body.addEventListener('click', closeAndRemoveHandler, true);
131         }
132
133         const attributeNames = DescriptorModelMetaFactory.getModelFieldNamesForType('nsd.vnffgd.classifier.match-attributes');
134
135         const selectedConnectionPoint = classifier.uiState.vnfdRef ? `${classifier.uiState.vnfdRef.name}/${classifier.vnfdConnectionPointRef.vnfdIndex}/${classifier.vnfdConnectionPointRef.vnfdConnectionPointName}` : '';
136
137         const isEditClassifierConnectionPointRef = context.component.state.editClassifierConnectionPointRef === classifier.uid;
138
139         const hasClassifierServiceFunctionVNFDs = context.containers.filter(d => DescriptorModelFactory.isConstituentVnfdWithServiceChain(d, 'CLASSIFIER')).length > 0;
140
141         return (
142                 <LayoutRow key={classifier.uid}
143                                    data-uid={classifier.uid}
144                                    data-offset-width="true"
145                                    className={ClassNames('fg-classifier', classifier.className, {'-is-edit-classifier-connection-point-ref': isEditClassifierConnectionPointRef})}
146                                    onClick={onClickSelectAndShowInDetailsPanel.bind(null, classifier)}>
147                         <div className="classifier-properties">
148                                 <div className="classifier-property">
149                                         <EditableProperty title="name">
150                                                 <ContentEditableDiv name="name"
151                                                                                         value={classifier.name}
152                                                                                         autoPadRight="true"
153                                                                                         onBlur={() => DeletionManager.addEventListeners()}
154                                                                                         onChange={onFormInputChangedModifyContainerAndNotify.bind(null, classifier)}
155                                                                                         className="classifier-name" />
156                                         </EditableProperty>
157                                 </div>
158                                 <div className="classifier-property">
159                                         <EditableProperty title="path">
160                                                 {buildRecordServicePathSelector(classifier)}
161                                         </EditableProperty>
162                                 </div>
163                                 <div className="classifier-property">
164                                         <EditableProperty title="connection point ref" disabled={!hasClassifierServiceFunctionVNFDs}>
165                                                 <ContentEditableDiv autoPadRight="true"
166                                                                                         value={selectedConnectionPoint}
167                                                                                         disabled={!hasClassifierServiceFunctionVNFDs}
168                                                                                         onChange={() => {}}
169                                                                                         onClick={onClickOpenConnectionPointSelector.bind(null, context.component, classifier)} />
170                                         </EditableProperty>
171                                         <div className="select-connection-point-ref">
172                                                 <ConnectionPointSelector containers={context.containers}
173                                                                                                  style={context.styleSecondary}
174                                                                                                  serviceChain="CLASSIFIER"
175                                                                                                  isDisabled={!hasClassifierServiceFunctionVNFDs}
176                                                                                                  onExitEditPathMode={onClickExitPathEdithMode.bind(null, context.component)}
177                                                                                                  onAddConnectionPointRef={onClickAddConnectionPointRef.bind(null, context.component, classifier)}
178                                                 />
179                                         </div>
180                                         {!hasClassifierServiceFunctionVNFDs ? <div className="hint">A VNFD with the chain CLASSIFIER is required to add a connection point ref.</div> : ''}
181                                 </div>
182                         </div>
183                         <table className="classifier-match-attributes">
184                                 <thead>
185                                         <tr>
186                                                 {attributeNames.map((name, i) => <th key={i} className={ClassNames(name + '-property')}>{changeCase.title(name)}</th>)}
187                                         </tr>
188                                 </thead>
189                                 <tbody>
190                                         {classifier.matchAttributes.map(mapClassifierMatchAttributes.bind(null, context))}
191                                 </tbody>
192                                 <tfoot>
193                                         <tr className="xfooter-actions">
194                                                 <th colSpan={attributeNames.length} className="row-action-column">
195                                                         <Button className="create-new-match-attributes" src={imgAdd} width="20px" onClick={onClickAddNewMatchAttributes.bind(null, context, classifier)} label="Add Match Attributes" />
196                                                 </th>
197                                         </tr>
198                                 </tfoot>
199                         </table>
200                 </LayoutRow>
201         );
202
203 }