8c831c19f656c621f5ce669ac18c147b42560510
[osm/riftware.git] /
1 /*
2  *    Copyright 2016 RIFT.IO Inc
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 /*
18  * STANDARD_RIFT_IO_COPYRIGHT
19  */
20 /**
21  * Created by onvelocity on 2/4/16.
22  */
23
24 'use strict';
25
26 import d3 from 'd3'
27 import React from 'react'
28 import Range from '../Range'
29 import Button from '../Button'
30 import ClassNames from 'classnames'
31 import changeCase from 'change-case'
32 import LayoutRow from '../LayoutRow'
33 import SelectionManager from '../../libraries/SelectionManager'
34 import PureRenderMixin from 'react-addons-pure-render-mixin'
35 import CatalogItemsActions from '../../actions/CatalogItemsActions'
36 import CanvasEditorActions from '../../actions/CanvasEditorActions'
37 import DescriptorModelFactory from '../../libraries/model/DescriptorModelFactory'
38 import ComposerAppActions from '../../actions/ComposerAppActions'
39 import DescriptorModelMetaFactory from '../../libraries/model/DescriptorModelMetaFactory'
40 import ComposerAppStore from '../../stores/ComposerAppStore'
41 import DeletionManager from '../../libraries/DeletionManager'
42 import ContentEditableDiv from '../ContentEditableDiv'
43 import TooltipManager from '../../libraries/TooltipManager'
44 import HighlightRecordServicePaths from '../../libraries/graph/HighlightRecordServicePaths'
45 import mapClassifier from './mapClassifier'
46 import mapRecordServicePath from './mapRecordServicePath'
47 import onCutDelegateToRemove from './onCutDelegateToRemove'
48 import onClickSelectAndShowInDetailsPanel from './onClickSelectAndShowInDetailsPanel'
49
50 import '../../styles/EditForwardingGraphPaths.scss'
51
52 import imgNSD from '../../images/default-catalog-icon.svg'
53 import imgFG from '../../../../node_modules/open-iconic/svg/infinity.svg'
54 import imgRemove from '../../../../node_modules/open-iconic/svg/trash.svg'
55 import imgAdd from '../../../../node_modules/open-iconic/svg/plus.svg'
56 import imgConnection from '../../../../node_modules/open-iconic/svg/random.svg'
57 import imgClassifier from '../../../../node_modules/open-iconic/svg/spreadsheet.svg'
58 import imgReorder from '../../../../node_modules/open-iconic/svg/menu.svg'
59
60 function mapFG(fg, i) {
61
62         const context = this;
63         context.vnffg = fg;
64
65         const colors = fg.colors;
66         const stylePrimary = {borderColor: colors.primary};
67         const styleSecondary = {borderColor: colors.secondary};
68
69         context.stylePrimary = stylePrimary;
70         context.styleSecondary = styleSecondary;
71
72         const rspMap = fg.rsp.reduce((map, rsp) => {
73                 map[rsp.id] = rsp;
74                 rsp.classifier = [];
75                 return map;
76         }, {});
77
78         fg.classifier.forEach(classifier => {
79                 const rsp = rspMap[classifier.model['rsp-id-ref']];
80                 if (rsp) {
81                         rsp.classifier.push(classifier);
82                 }
83         });
84
85         function onClickRemoveForwardingGraph(fg, event) {
86                 event.preventDefault();
87                 const root = fg.getRoot();
88                 fg.remove();
89                 CatalogItemsActions.catalogItemDescriptorChanged(root);
90         }
91
92         function onClickAddClassifier(context, fg, event) {
93                 event.preventDefault();
94                 fg.createClassifier();
95                 CatalogItemsActions.catalogItemDescriptorChanged(fg.getRoot());
96         }
97
98         function onClickToggleShowAllFGPaths(fg, event) {
99                 //event.preventDefault();
100                 event.stopPropagation();
101                 fg.uiState.showPaths = event.target.checked;
102                 fg.rsp.forEach(rsp => rsp.uiState.showPath = event.target.checked);
103                 CatalogItemsActions.catalogItemMetaDataChanged(fg.getRoot().model);
104         }
105
106         if (!fg.uiState.hasOwnProperty('showPaths')) {
107                 fg.uiState.showPaths = true;
108                 fg.rsp.forEach(d => d.uiState.showPath = true);
109         }
110
111         const toggleSelectAllPaths = (
112                 <input type="checkbox" name={'show-path' + fg.uid} checked={fg.uiState.showPaths} onChange={() => {}} onClick={onClickToggleShowAllFGPaths.bind(null, fg)} />
113         );
114
115         const srpFactory = DescriptorModelFactory.newRecordServicePathFactory({}, fg);
116         srpFactory.uid = fg.uid + i;
117
118         const hasServiceFunctionVNFDs = context.containers.filter(d => DescriptorModelFactory.isConstituentVnfdWithServiceChain(d, 'SF')).length > 0;
119
120         return (
121                 <div key={i} className={fg.className} data-uid={fg.uid} data-offset-width="true" onClick={onClickSelectAndShowInDetailsPanel.bind(null, fg)} onCut={onCutDelegateToRemove.bind(null, fg)}>
122                         <div key="outline-indicator" data-outline-indicator="true"></div>
123                         <div className="header-actions">
124                                 <Button className="remove-forwarding-graph" title="Remove" onClick={onClickRemoveForwardingGraph.bind(null, fg)} src={imgRemove}/>
125                         </div>
126                         <LayoutRow primaryActionColumn={toggleSelectAllPaths} secondaryActionColumn={<img className="fg-icon" src={imgFG} width="20px" />}>
127                                 <small>{fg.title}</small>
128                         </LayoutRow>
129                         <div>
130                                 <h4>Record Service Paths</h4>
131                                 {hasServiceFunctionVNFDs ? fg.recordServicePaths.concat(srpFactory).map(mapRecordServicePath.bind(null, context)) : <small className="no-service-function-chain-msg hint">A VNFD with the chain SF is required to build Record Service Paths.</small>}
132                         </div>
133                         <div>
134                                 <h4>Classifiers</h4>
135                                 {fg.classifier.map(mapClassifier.bind(null, context))}
136                                 <div className="footer-actions">
137                                         <div className="row-action-column">
138                                                 <Button className="create-new-classifier" src={imgAdd} width="20px" onClick={onClickAddClassifier.bind(null, context, fg)} label="Add Classifier" />
139                                         </div>
140                                 </div>
141                         </div>
142                 </div>
143         );
144
145 }
146
147 function mapNSD(nsd, i) {
148
149         const context = this;
150         context.nsd = nsd;
151
152         function onClickAddForwardingGraph(nsd, event) {
153                 event.preventDefault();
154                 nsd.createVnffgd();
155                 CatalogItemsActions.catalogItemDescriptorChanged(nsd.getRoot());
156         }
157
158         const forwardingGraphs = nsd.forwardingGraphs.map(mapFG.bind(context));
159         if (forwardingGraphs.length === 0) {
160                 forwardingGraphs.push(
161                         <div key="1" className="welcome-message">
162                                 No Forwarding Graphs to model.
163                         </div>
164                 );
165         }
166
167         return (
168                 <div key={i} className={nsd.className}>
169                         {forwardingGraphs}
170                         <div className="footer-actions">
171                                 <div className="row-action-column">
172                                         <Button className="create-new-forwarding-graph" src={imgAdd} width="20px" onClick={onClickAddForwardingGraph.bind(null, nsd)} label="Add new Forwarding Graph" />
173                                 </div>
174                         </div>
175                 </div>
176         );
177
178 }
179
180 const EditForwardingGraphPaths = React.createClass({
181         mixins: [PureRenderMixin],
182         getInitialState: function () {
183                 return ComposerAppStore.getState();
184         },
185         getDefaultProps: function () {
186                 return {
187                         containers: []
188                 };
189         },
190         componentWillMount: function () {
191         },
192         componentDidMount: function () {
193         },
194         componentDidUpdate: function () {
195         },
196         componentWillUnmount: function () {
197         },
198         render() {
199
200                 const containers = this.props.containers;
201                 const context = {
202                         component: this,
203                         containers: containers
204                 };
205
206                 const networkService = containers.filter(d => d.type === 'nsd');
207                 if (networkService.length === 0) {
208                         return <p className="welcome-message">No <img src={imgNSD} width="20px" /> NSD open in the canvas. Try opening an NSD.</p>;
209                 }
210
211                 return (
212                         <div className="EditForwardingGraphPaths -with-transitions" data-offset-parent="true">
213                                 <div key="outline-indicator" data-outline-indicator="true"></div>
214                                 {containers.filter(d => d.type === 'nsd').map(mapNSD.bind(context))}
215                         </div>
216                 );
217
218         }
219 });
220
221 export default EditForwardingGraphPaths;