RIFT-15726 - optimize download size -> lodash usage in UI
[osm/UI.git] / skyquake / plugins / launchpad / src / virtual_links / nsVirtualLinkCreate.jsx
1 /*
2  * 
3  *   Copyright 2016 RIFT.IO Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18 import React from 'react';
19 import Utils from 'utils/utils.js';
20 import './nsVirtualLinks.scss';
21 import NSVirtualLinkCreateStore from './nsVirtualLinkCreateStore.js';
22 import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
23 import TextInput from 'widgets/form_controls/textInput.jsx';
24 import ScreenLoader from 'widgets/screen-loader/screenLoader.jsx';
25 import Button from 'widgets/button/rw.button.js';
26 import SelectOption from 'widgets/form_controls/selectOption.jsx';
27
28
29
30 class NsVirtualLinkCreate extends React.Component {
31         constructor(props) {
32                 super(props);
33             this.Store = this.props.flux.stores.hasOwnProperty('NSVirtualLinkCreateStore') ? 
34                                 this.props.flux.stores.NSVirtualLinkCreateStore : this.props.flux.createStore(NSVirtualLinkCreateStore, 'NSVirtualLinkCreateStore');
35                 this.state = this.Store.getState();
36                 this.Store.listen(this.handleUpdate);
37         }
38
39         componentWillMount() {
40                 (!this.state.nsrId && this.props.nsrId) && this.Store.saveNSRId(this.props.nsrId);
41                 this.Store.saveMode(this.props.mode);
42                 this.Store.saveOnSuccess(this.props.onSuccess);
43                 switch (this.props.mode) {
44                         case 'creating':
45                                 if (!this.state.vld) {
46                                         this.Store.saveVld({});
47                                 }
48                                 break;
49                         case 'editing':
50                                 this.Store.saveVld(this.props.vld);
51                                 break;
52                 }
53                 if (this.props.nsd && this.props.nsd['constituent-vnfd']) {
54                         let memberVnfIndexRefs = [];
55                         let vnfdIdRefs = [];
56                         this.props.nsd['constituent-vnfd'].map((cVNFD, cVNFDI) => {
57                                 memberVnfIndexRefs.push({
58                                         label: cVNFD['member-vnf-index'],
59                                         value: cVNFD['member-vnf-index']
60                                 });
61                                 vnfdIdRefs.push({
62                                         label: cVNFD['vnfd-id-ref'],
63                                         value: cVNFD['vnfd-id-ref']
64                                 });
65                         });
66
67                         let ipProfileNames = [];
68                         this.props.nsd['ip-profiles'] && this.props.nsd['ip-profiles'].map((ipProfile, ipProfileIndex) => {
69                                 ipProfileNames.push({
70                                         label: ipProfile['name'],
71                                         value: ipProfile['name']
72                                 });
73                         })
74
75                         this.Store.saveMemberVnfIndexRefs(memberVnfIndexRefs);
76                         this.Store.saveVnfdIdRefs(vnfdIdRefs);
77                         this.Store.saveIpProfileNames(ipProfileNames);
78                 }
79         }
80
81         componentWillReceiveProps(nextProps) {
82                 if (nextProps != this.props) {
83                         if (nextProps.mode != this.props.mode) {
84                                 // mode change
85                                 this.Store.saveMode(nextProps.mode);
86                                 switch (nextProps.mode) {
87                                         case 'creating':
88                                                 // switching from editing to creating
89                                                 this.Store.saveVld({});
90                                                 break;
91                                         case 'editing':
92                                                 // switching from creating to editing
93                                                 this.Store.saveVld(nextProps.vld);
94                                                 break;
95                                 }
96                         } else {
97                                 // no mode change, but props changed
98                                 switch (nextProps.mode) {
99                                         case 'creating':
100                                                 // switching from creating to creating
101                                                 // TODO: can't figure out how to empty out without affecting create being erased
102                                                 break;
103                                         case 'editing':
104                                                 // switching from editing to editing
105                                                 if ((nextProps.vld && nextProps.vld.id) != (this.props.vld && this.props.vld.id)) {
106                                                         this.Store.saveVld(nextProps.vld);
107                                                 }
108                                                 break;
109                                 }
110                         }
111                 }
112         }
113
114         componentWillUnmount() {
115                 this.Store.saveVld({});
116                 this.Store.unlisten(this.handleUpdate);
117         }
118
119         handleUpdate = (storeState) => {
120                 this.setState(storeState);
121         }
122
123         handleSubmit = (mode, e) => {
124                 e.preventDefault();
125                 this.Store.persistVirtualLink(mode);
126         }
127
128         handleCancel = (e) => {
129                 e.preventDefault();
130                 this.props.onCancel && this.props.onCancel();
131         }
132
133         transformValue(field, value) {
134                 let transformedValue = (field.transform && field.transform(value)) || value;
135                 if (typeof transformedValue == 'object') {
136                         transformedValue = JSON.stringify(transformedValue);
137                 }
138                 return transformedValue;
139         }
140
141         handleFirstLevelKeyChange = (key, e) => {
142                 this.Store.updateFirstLevelKey(key, e);
143         }
144
145         handleSecondLevelKeyChange = (firstLevelKey, secondLevelKey, e) => {
146                 this.Store.updateSecondLevelKey(firstLevelKey, secondLevelKey, e);
147         }
148
149         handleFirstLevelListKeyChange = (listName, index, keyName, e) => {
150                 this.Store.updateFirstLevelListKeyChange(listName, index, keyName, e);
151         }
152
153         handleAddConnectionPointRef = () => {
154                 this.Store.addConnectionPointRef();
155         }
156
157         handleRemoveConnectionPoint = (vCPRI, e) => {
158                 this.Store.removeConnectionPointRef(vCPRI);
159         }
160
161
162         updateVLDInitParamsType = (type) => {
163                 this.Store.updateVLDInitParamsType(type);
164         }
165
166         updateVLDInitParamsValue = (currentVLDInitParamsType, e) => {
167                 this.Store.updateVLDInitParamsValue(currentVLDInitParamsType, e);
168         }
169
170         render() {
171                 let self = this;
172
173                 let typeOptions = this.state.typeOptions;
174                 let overlayTypeOptions = this.state.overlayTypeOptions;
175                 let currentVLDInitParamsType = this.state.currentVLDInitParamsType;
176                 let memberVnfIndexRefs = this.state.memberVnfIndexRefs;
177                 let vnfdIdRefs = this.state.vnfdIdRefs;
178                 let vnfdConnectionPointRefs = this.state.vnfdConnectionPointRefs;
179                 let ipProfileNames = this.state.ipProfileNames;
180
181                 let connectionPointsHtml = [];
182
183                 this.state.vld && this.state.vld['vnfd-connection-point-ref'] && this.state.vld['vnfd-connection-point-ref'].map((vCPR, vCPRI) => {
184                         connectionPointsHtml.push(
185                                 <li className='vnfd-connection-points-list-item'>
186                                         <div>
187                                                 <span>
188                                                         VNFD CONNECTION POINT REF - {vCPRI}
189                                                 </span>
190                                                 <a key={'vnfd-connection-point-delete-' + vCPRI} onClick={this.handleRemoveConnectionPoint.bind(self, vCPRI)} title="Delete">
191                                         <span key={'trash-' + vCPRI} className="oi" data-glyph="trash" aria-hidden="true"></span>
192                                 </a>
193                         </div>
194                         <SelectOption key={'vnfd-connection-point-ref-member-vnfd-index-ref-' + vCPRI} label={'MEMBER VNF INDEX REF'} initial={memberVnfIndexRefs[0].value} options={memberVnfIndexRefs} onChange={this.handleFirstLevelListKeyChange.bind(self, 'vnfd-connection-point-ref', vCPRI, 'member-vnf-index-ref')} defaultValue={this.state.vld['vnfd-connection-point-ref'] && this.state.vld['vnfd-connection-point-ref'][vCPRI] && this.state.vld['vnfd-connection-point-ref'][vCPRI]['member-vnf-index-ref']}/>
195                         <SelectOption key={'vnfd-connection-point-ref-vnfd-id-ref-' + vCPRI} label={'VNFD ID REF'} initial={vnfdIdRefs[0].value} options={vnfdIdRefs} onChange={this.handleFirstLevelListKeyChange.bind(self, 'vnfd-connection-point-ref', vCPRI, 'vnfd-id-ref')} defaultValue={this.state.vld['vnfd-connection-point-ref'] && this.state.vld['vnfd-connection-point-ref'][vCPRI] && this.state.vld['vnfd-connection-point-ref'][vCPRI]['vnfd-id-ref']}/>
196                         <TextInput key={'vnfd-connection-point-ref-vnfd-connection-point-ref-' + vCPRI} label='VNFD CONNECTION POINT REF' className='value' type='text' value={this.state.vld['vnfd-connection-point-ref'] && this.state.vld['vnfd-connection-point-ref'][vCPRI] && this.state.vld['vnfd-connection-point-ref'][vCPRI]['vnfd-connection-point-ref']} onChange={this.handleFirstLevelListKeyChange.bind(self, 'vnfd-connection-point-ref', vCPRI, 'vnfd-connection-point-ref')} />
197                                 </li>
198                         );
199                 });
200
201                 
202                 let vldHTML = this.state.vld && (
203                         <div>
204                                 <h3>DETAILS</h3>
205                                 <TextInput key={'id'} className='value' label={'ID'} type='text' value={this.state.vld.id} onChange={this.handleFirstLevelKeyChange.bind(self, 'id')} readonly={this.state.mode == 'editing' ? true:false} />
206                                 <TextInput key={'name'} className='value' label={'NAME'} type='text' value={this.state.vld.name} onChange={this.handleFirstLevelKeyChange.bind(self, 'name')} />
207                                 <TextInput key={'short-name'} className='value' label={'SHORT NAME'} type='text' value={this.state.vld['short-name']} onChange={this.handleFirstLevelKeyChange.bind(self, 'short-name')} />
208                                 <TextInput key={'vendor'} className='value' label={'VENDOR'} type='text' value={this.state.vld.vendor} onChange={this.handleFirstLevelKeyChange.bind(self, 'vendor')} />
209                                 <TextInput key={'description'} className='value' label={'DESCRIPTION'} type='text' value={this.state.vld.description} onChange={this.handleFirstLevelKeyChange.bind(self, 'description')} />
210                                 <TextInput key={'version'} className='value' label={'VERSION'} type='text' value={this.state.vld.version} onChange={this.handleFirstLevelKeyChange.bind(self, 'version')} />
211                                 <SelectOption label={'TYPE'} initial={typeOptions[0].value} options={typeOptions} onChange={this.handleFirstLevelKeyChange.bind(self, 'type')} defaultValue={this.state.vld['type']} />
212                                 <TextInput key={'root-bandwidth'} className='value' label={'ROOT BANDWIDTH'} type='text' value={this.state.vld['root-bandwidth']} onChange={this.handleFirstLevelKeyChange.bind(self, 'root-bandwidth')} />
213                                 <TextInput key={'leaf-bandwidth'} className='value' label={'LEAF BANDWIDTH'} type='text' value={this.state.vld['leaf-bandwidth']} onChange={this.handleFirstLevelKeyChange.bind(self, 'leaf-bandwidth')} />
214                                 <h3>PROVIDER NETWORK</h3>
215                                 <TextInput key={'physical-network'} className='value' label={'PHYSICAL NETWORK'} type='text' value={this.state.vld['provider-network'] && this.state.vld['provider-network']['physical-network']} onChange={this.handleSecondLevelKeyChange.bind(self, 'provider-network', 'physical-network')} />
216                                 <SelectOption label={'OVERLAY TYPE'} initial={overlayTypeOptions[0].value} options={overlayTypeOptions} onChange={this.handleSecondLevelKeyChange.bind(self, 'provider-network', 'overlay-type')} defaultValue={this.state.vld['provider-network'] && this.state.vld['provider-network']['overlay-type']}/>
217                                 <TextInput key={'segmentation_id'} className='value' label={'SEGMENTATION ID'} type='text' value={this.state.vld['provider-network'] && this.state.vld['provider-network']['segmentation_id']} onChange={this.handleSecondLevelKeyChange.bind(self, 'provider-network', 'segmentation_id')} />
218                                 <h3>VNF CONNECTION POINTS
219                                         <a className="plusButton" onClick={this.handleAddConnectionPointRef}>
220                                 <span className="oi" data-glyph="plus"
221                                       title="Add connection point ref" aria-hidden="true"></span>
222                                 </a>
223                                 </h3>
224                         <ul className='vnfd-connection-points-list'>
225                                         {connectionPointsHtml}
226                                 </ul>
227                                 <h3>INIT PARAMS</h3>
228                                 <div className="inputControls-radioGroup">
229                                         <label className="inputControls-radio">
230                                                 <input type="radio" name={'ip-profile-ref'} onChange={this.updateVLDInitParamsType.bind(self, 'ip-profile-ref')} checked={currentVLDInitParamsType == 'ip-profile-ref'} value='ip-profile-ref' />
231                                                 IP Profile
232                                         </label>
233                                         <label className="inputControls-radio">
234                                                 <input type="radio" name={'vim-network-name'} onChange={this.updateVLDInitParamsType.bind(self, 'vim-network-name')} checked={currentVLDInitParamsType == 'vim-network-name'} value='vim-network-name' />
235                                                 VIM Network Name
236                                         </label>
237                                         <label className="inputControls-radio">
238                                                 <input type="radio" name={'unknown'} onChange={this.updateVLDInitParamsType.bind(self, 'unknown')} checked={currentVLDInitParamsType == 'unknown'} value='unknown' />
239                                                 Unknown
240                                         </label>
241                                 </div>
242                                 {
243                                         (currentVLDInitParamsType == 'unknown') ? 
244                                                 null
245                                         :
246                                                 (currentVLDInitParamsType == 'vim-network-name') ?
247                                                         <TextInput label='NETWORK NAME' onChange={this.updateVLDInitParamsValue.bind(self, currentVLDInitParamsType)} value={this.state.vld[currentVLDInitParamsType]} />
248                                                 :
249                                                         <SelectOption label={'IP PROFILE NAME'} initial={ipProfileNames[0].value} options={ipProfileNames} onChange={this.updateVLDInitParamsValue.bind(self, currentVLDInitParamsType)} />
250                                 }
251                         </div>
252                 );
253
254                 return (
255                         <form className={'createVirtualLink'} onKeyDown={this.evaluateCreateVirtualLink}>
256                                 {vldHTML}
257                                 <div className='buttonGroup'>
258                                         <Button label='Submit' onClick={this.handleSubmit.bind(self, this.state.mode)} className='dark' type='submit' />
259                                         <Button label='Cancel' onClick={this.handleCancel.bind(self)} className='dark' type='reset' />
260                                 </div>
261                         </form>
262                 );
263         }
264 }
265
266 export default SkyquakeComponent(NsVirtualLinkCreate);