d718c2e445bb66b94589175cf4581fb4ccef82b4
[clamp.git] / ui-react / src / components / loop_viewer / svg / SvgGenerator.js
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END============================================
19  * ===================================================================
20  *
21  */
22
23 import React from 'react'
24 import styled from 'styled-components';
25 import { withRouter } from "react-router-dom";
26 import LoopCache from '../../../api/LoopCache';
27 import OnapConstant from '../../../utils/OnapConstants';
28
29 const DivStyled = styled.div`
30         overflow-x: scroll;
31     width: 100%;
32     height: 100%;
33 `
34
35 const emptySvg = (<svg> <text x="20" y="40">No LOOP (SVG)</text> </svg>);
36
37 class SvgGenerator extends React.Component {
38     boxWidth = 200;
39     boxHeight = 100;
40     boxSpace = 50;
41
42     static GENERATED_FROM_INSTANCE = "INSTANCE";
43     static GENERATED_FROM_TEMPLATE = "TEMPLATE";
44
45         state = {
46                 loopCache: new LoopCache({}),
47                 clickable: false,
48                 generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE
49         }
50
51         constructor(props) {
52                 super(props);
53                 this.state.loopCache = props.loopCache;
54                 this.state.clickable = props.clickable;
55                 this.state.generatedFrom = props.generatedFrom;
56                 this.handleSvgClick = this.handleSvgClick.bind(this);
57                 this.renderSvg = this.renderSvg.bind(this);
58         }
59
60         shouldComponentUpdate(nextProps, nextState) {
61                 return this.state.loopCache !== nextState.loopCache;
62         }
63
64         componentWillReceiveProps(newProps) {
65                 if (this.state.loopCache !== newProps.loopCache) {
66                         this.setState({
67                                 loopCache: newProps.loopCache,
68                         });
69                 }
70         }
71
72         handleSvgClick(event) {
73             if (this.state.clickable) {
74             console.debug("svg click event received");
75             var elementName = event.target.parentNode.getAttribute('policyId');
76             console.info("SVG element clicked", elementName);
77             if (elementName !== null) {
78                 this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName);
79             }
80                 }
81         }
82
83     createVesBox (xPos) {
84         return this.createOneBox(xPos,null,null,'VES Collector','VES',null);
85     }
86
87     createOneArrow(xPos) {
88         return (
89          <svg width={this.boxSpace} height={this.boxHeight} x={xPos}>
90            <defs>
91                         <marker viewBox="0 0 20 20" markerWidth="20" markerHeight="20" orient="auto" refX="8.5" refY="5" id="arrow">
92                                 <path d="m 1 5 l 0 -3 l 7 3 l -7 3 z"
93                                         stroke-width= "1" stroke-linecap= "butt" stroke-dasharray= "10000, 1"
94                                         fill="#000000" stroke="#000000" />
95                         </marker>
96            </defs>
97            <line x1="0" y1="50%" x2="100%" y2="50%" stroke-width="2" color="black" stroke="black" marker-end="url(#arrow)"/>
98          </svg>
99         );
100     }
101
102     createBeginCircle(xPos, text) {
103             return (
104             <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
105                 <circle cx={this.boxWidth-30} cy="50%" r="30" stroke-width="1" color="black" stroke="black" fill="#27ae60"/>
106                 <text x={this.boxWidth-30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
107             </svg>
108             );
109     }
110
111     createEndCircle(xPos, text) {
112             return (
113             <svg width={this.boxWidth} height={this.boxHeight} x={xPos}>
114                 <circle cx={30} cy="50%" r="30" stroke-width="2" color="black" stroke="black" fill="#27ae60"/>
115                 <text x={30} y="50%" text-anchor="middle" dominant-baseline="middle" textLength="20%" lengthAdjust="spacingAndGlyphs" >{text}</text>
116             </svg>
117             );
118     }
119
120     createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) {
121         return (
122         <svg width={this.boxWidth} height={this.boxHeight} x={xPos} title="test">
123             <g policyId={policyId} loopElementModelId={loopElementModelId} policyType={policyType}>
124                 <rect width="100%" height="100%" stroke-width="2" color="black" stroke="black" fill="#1abc9c"/>
125                 <text x="50%" y="15%" color="white" fill="white" dominant-baseline="middle" text-anchor="middle" textLength="50%" lengthAdjust="spacingAndGlyphs">{title}</text>
126                 <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" textLength="80%" lengthAdjust="spacingAndGlyphs" >{name}</text>
127                 <text x="50%" y="80%" text-anchor="middle" dominant-baseline="middle" textLength="110%" lengthAdjust="spacingAndGlyphs" >{policyId}</text>
128             </g>
129         </svg>
130         );
131     }
132
133     createSvgFromTemplate() {
134         const allElements = [];
135         var xPos = 0;
136
137         allElements.push(this.createBeginCircle(xPos,"Start"))
138         xPos+=(this.boxWidth+this.boxSpace);
139
140         allElements.push(this.createOneArrow(xPos-this.boxSpace));
141
142         allElements.push(this.createVesBox(xPos));
143         xPos+=(this.boxWidth+this.boxSpace);
144
145         allElements.push(this.createOneArrow(xPos-this.boxSpace));
146         //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType)
147         for (var loopElement of this.state.loopCache.getAllLoopElementModels()) {
148
149             allElements.push(this.createOneBox(xPos,
150                 loopElement['name'],
151                 loopElement['name'],
152                 loopElement['shortName'],
153                 loopElement['loopElementType'],
154                 loopElement['loopElementType']))
155             xPos+=(this.boxWidth+this.boxSpace);
156             allElements.push(this.createOneArrow(xPos-this.boxSpace));
157         }
158
159         allElements.push(this.createEndCircle(xPos, "End"))
160         xPos+=(this.boxWidth+this.boxSpace);
161
162         return allElements;
163     }
164
165     createSvgFromInstance() {
166         const allElements = [];
167         var xPos = 0;
168
169         allElements.push(this.createBeginCircle(xPos,"Start"))
170         xPos+=(this.boxWidth+this.boxSpace);
171
172         allElements.push(this.createOneArrow(xPos-this.boxSpace));
173
174         allElements.push(this.createVesBox(xPos));
175         xPos+=(this.boxWidth+this.boxSpace);
176
177         allElements.push(this.createOneArrow(xPos-this.boxSpace));
178
179         for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) {
180             var loopElementModelName =  this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel'];
181             if (loopElementModelName !== undefined) {
182                 loopElementModelName = loopElementModelName['name'];
183             }
184             allElements.push(this.createOneBox(xPos,
185                 this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'],
186                 loopElementModelName,
187                 this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'],
188                 'microservice',
189                 OnapConstant.microServiceType))
190             xPos+=(this.boxWidth+this.boxSpace);
191             allElements.push(this.createOneArrow(xPos-this.boxSpace));
192         }
193
194         for (var opPolicy in this.state.loopCache.getOperationalPolicies()) {
195             loopElementModelName =  this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel'];
196             if (loopElementModelName !== undefined) {
197                 loopElementModelName = loopElementModelName['name'];
198             }
199             allElements.push(this.createOneBox(xPos,
200                 this.state.loopCache.getOperationalPolicies()[opPolicy]['name'],
201                 loopElementModelName,
202                 this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'],
203                 'operational',
204                 OnapConstant.operationalPolicyType))
205             xPos+=(this.boxWidth+this.boxSpace);
206             allElements.push(this.createOneArrow(xPos-this.boxSpace));
207         }
208
209         allElements.push(this.createEndCircle(xPos, "End"))
210         xPos+=(this.boxWidth+this.boxSpace);
211
212         return allElements;
213     }
214
215     renderSvg() {
216         if (this.state.loopCache.getLoopName() === undefined) {
217             return [emptySvg];
218         }
219         if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) {
220             return this.createSvgFromInstance();
221         } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) {
222             return this.createSvgFromTemplate();
223         }
224     }
225
226     render() {
227         var allTheElements = this.renderSvg();
228         var svgWidth = this.boxWidth*allTheElements.length;
229         var svgHeight = this.boxHeight+100;
230         return (
231             <DivStyled onClick={this.handleSvgClick} >
232                 <svg height={svgHeight} width={svgWidth}  preserveAspectRatio="none">
233                     {allTheElements}
234                 </svg>
235             </DivStyled>
236         );
237     }
238 }
239
240 export default withRouter(SvgGenerator);