6fb4955f7d617f6df5a7700f4393142b460308ea
[osm/riftware.git] /
1 /*
2  * STANDARD_RIFT_IO_COPYRIGHT
3  */
4 /**
5  * Created by onvelocity on 2/4/16.
6  */
7
8 'use strict';
9
10 import d3 from 'd3'
11 import React from 'react'
12 import Range from '../Range'
13 import Button from '../Button'
14 import ClassNames from 'classnames'
15 import changeCase from 'change-case'
16 import LayoutRow from '../LayoutRow'
17 import SelectionManager from '../../libraries/SelectionManager'
18 import PureRenderMixin from 'react-addons-pure-render-mixin'
19 import CatalogItemsActions from '../../actions/CatalogItemsActions'
20 import CanvasEditorActions from '../../actions/CanvasEditorActions'
21 import DescriptorModelFactory from '../../libraries/model/DescriptorModelFactory'
22 import ComposerAppActions from '../../actions/ComposerAppActions'
23 import DescriptorModelMetaFactory from '../../libraries/model/DescriptorModelMetaFactory'
24 import ComposerAppStore from '../../stores/ComposerAppStore'
25 import DeletionManager from '../../libraries/DeletionManager'
26 import ContentEditableDiv from '../ContentEditableDiv'
27 import TooltipManager from '../../libraries/TooltipManager'
28 import HighlightRecordServicePaths from '../../libraries/graph/HighlightRecordServicePaths'
29 import mapClassifier from './mapClassifier'
30 import mapRecordServicePath from './mapRecordServicePath'
31 import onCutDelegateToRemove from './onCutDelegateToRemove'
32 import onClickSelectAndShowInDetailsPanel from './onClickSelectAndShowInDetailsPanel'
33
34 import '../../styles/EditForwardingGraphPaths.scss'
35
36 import imgNSD from '../../images/iconmonstr-network-6-icon.svg'
37 import imgFG from '../../images/iconmonstr-infinity-4-icon.svg'
38 import imgRemove from '../../images/recycle69.svg'
39 import imgAdd from '../../images/iconmonstr-plus-5-icon-256.png'
40 import imgConnection from '../../images/connection.svg'
41 import imgClassifier from '../../images/iconmonstr-control-panel-4.svg'
42 import imgReorder from '../../images/menu51.svg'
43
44 function mapFG(fg, i) {
45
46         const context = this;
47         context.vnffg = fg;
48
49         const colors = fg.colors;
50         const stylePrimary = {borderColor: colors.primary};
51         const styleSecondary = {borderColor: colors.secondary};
52
53         context.stylePrimary = stylePrimary;
54         context.styleSecondary = styleSecondary;
55
56         const rspMap = fg.rsp.reduce((map, rsp) => {
57                 map[rsp.id] = rsp;
58                 rsp.classifier = [];
59                 return map;
60         }, {});
61
62         fg.classifier.forEach(classifier => {
63                 const rsp = rspMap[classifier.model['rsp-id-ref']];
64                 if (rsp) {
65                         rsp.classifier.push(classifier);
66                 }
67         });
68
69         function onClickRemoveForwardingGraph(fg, event) {
70                 event.preventDefault();
71                 const root = fg.getRoot();
72                 fg.remove();
73                 CatalogItemsActions.catalogItemDescriptorChanged(root);
74         }
75
76         function onClickAddClassifier(context, fg, event) {
77                 event.preventDefault();
78                 fg.createClassifier();
79                 CatalogItemsActions.catalogItemDescriptorChanged(fg.getRoot());
80         }
81
82         function onClickToggleShowAllFGPaths(fg, event) {
83                 //event.preventDefault();
84                 event.stopPropagation();
85                 fg.uiState.showPaths = event.target.checked;
86                 fg.rsp.forEach(rsp => rsp.uiState.showPath = event.target.checked);
87                 CatalogItemsActions.catalogItemMetaDataChanged(fg.getRoot().model);
88         }
89
90         if (!fg.uiState.hasOwnProperty('showPaths')) {
91                 fg.uiState.showPaths = true;
92                 fg.rsp.forEach(d => d.uiState.showPath = true);
93         }
94
95         const toggleSelectAllPaths = (
96                 <input type="checkbox" name={'show-path' + fg.uid} checked={fg.uiState.showPaths} onChange={() => {}} onClick={onClickToggleShowAllFGPaths.bind(null, fg)} />
97         );
98
99         const srpFactory = DescriptorModelFactory.newRecordServicePathFactory({}, fg);
100         srpFactory.uid = fg.uid + i;
101
102         const hasServiceFunctionVNFDs = context.containers.filter(d => DescriptorModelFactory.isConstituentVnfdWithServiceChain(d, 'SF')).length > 0;
103
104         return (
105                 <div key={i} className={fg.className} data-uid={fg.uid} data-offset-width="true" onClick={onClickSelectAndShowInDetailsPanel.bind(null, fg)} onCut={onCutDelegateToRemove.bind(null, fg)}>
106                         <div key="outline-indicator" data-outline-indicator="true"></div>
107                         <div className="header-actions">
108                                 <Button className="remove-forwarding-graph" title="Remove" onClick={onClickRemoveForwardingGraph.bind(null, fg)} src={imgRemove}/>
109                         </div>
110                         <LayoutRow primaryActionColumn={toggleSelectAllPaths} secondaryActionColumn={<img className="fg-icon" src={imgFG} width="20px" />}>
111                                 <small>{fg.title}</small>
112                         </LayoutRow>
113                         <div>
114                                 <h4>Record Service Paths</h4>
115                                 {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>}
116                         </div>
117                         <div>
118                                 <h4>Classifiers</h4>
119                                 {fg.classifier.map(mapClassifier.bind(null, context))}
120                                 <div className="footer-actions">
121                                         <div className="row-action-column">
122                                                 <Button className="create-new-classifier" src={imgAdd} width="20px" onClick={onClickAddClassifier.bind(null, context, fg)} label="Add Classifier" />
123                                         </div>
124                                 </div>
125                         </div>
126                 </div>
127         );
128
129 }
130
131 function mapNSD(nsd, i) {
132
133         const context = this;
134         context.nsd = nsd;
135
136         function onClickAddForwardingGraph(nsd, event) {
137                 event.preventDefault();
138                 nsd.createVnffgd();
139                 CatalogItemsActions.catalogItemDescriptorChanged(nsd.getRoot());
140         }
141
142         const forwardingGraphs = nsd.forwardingGraphs.map(mapFG.bind(context));
143         if (forwardingGraphs.length === 0) {
144                 forwardingGraphs.push(
145                         <div key="1" className="welcome-message">
146                                 No Forwarding Graphs to model.
147                         </div>
148                 );
149         }
150
151         return (
152                 <div key={i} className={nsd.className}>
153                         {forwardingGraphs}
154                         <div className="footer-actions">
155                                 <div className="row-action-column">
156                                         <Button className="create-new-forwarding-graph" src={imgAdd} width="20px" onClick={onClickAddForwardingGraph.bind(null, nsd)} label="Add new Forwarding Graph" />
157                                 </div>
158                         </div>
159                 </div>
160         );
161
162 }
163
164 const EditForwardingGraphPaths = React.createClass({
165         mixins: [PureRenderMixin],
166         getInitialState: function () {
167                 return ComposerAppStore.getState();
168         },
169         getDefaultProps: function () {
170                 return {
171                         containers: []
172                 };
173         },
174         componentWillMount: function () {
175         },
176         componentDidMount: function () {
177         },
178         componentDidUpdate: function () {
179         },
180         componentWillUnmount: function () {
181         },
182         render() {
183
184                 const containers = this.props.containers;
185                 const context = {
186                         component: this,
187                         containers: containers
188                 };
189
190                 const networkService = containers.filter(d => d.type === 'nsd');
191                 if (networkService.length === 0) {
192                         return <p className="welcome-message">No <img src={imgNSD} width="20px" /> NSD open in the canvas. Try opening an NSD.</p>;
193                 }
194
195                 return (
196                         <div className="EditForwardingGraphPaths -with-transitions" data-offset-parent="true">
197                                 <div key="outline-indicator" data-outline-indicator="true"></div>
198                                 {containers.filter(d => d.type === 'nsd').map(mapNSD.bind(context))}
199                         </div>
200                 );
201
202         }
203 });
204
205 export default EditForwardingGraphPaths;