From c0ec0fc448af1c5d6eacb195e95938c921ba1bce Mon Sep 17 00:00:00 2001 From: sebdet Date: Mon, 18 May 2020 12:31:11 +0200 Subject: Create SVG in UI Remove the SVG generation from the backend and put it in the UI Issue-ID: CLAMP-854 Signed-off-by: sebdet Change-Id: Icfa9e107d83bb244ac3d87300d013555bfa0b037 --- .../loop_viewer/svg/LoopComponentConverter.js | 17 -- ui-react/src/components/loop_viewer/svg/LoopSvg.js | 110 ---------- .../src/components/loop_viewer/svg/LoopSvg.test.js | 132 ------------ .../src/components/loop_viewer/svg/SvgGenerator.js | 240 +++++++++++++++++++++ .../svg/__snapshots__/LoopSvg.test.js.snap | 34 --- .../src/components/loop_viewer/svg/example.svg | 1 - 6 files changed, 240 insertions(+), 294 deletions(-) delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopSvg.js delete mode 100644 ui-react/src/components/loop_viewer/svg/LoopSvg.test.js create mode 100644 ui-react/src/components/loop_viewer/svg/SvgGenerator.js delete mode 100644 ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap delete mode 100644 ui-react/src/components/loop_viewer/svg/example.svg (limited to 'ui-react/src/components/loop_viewer') diff --git a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js b/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js deleted file mode 100644 index 29422a1f..00000000 --- a/ui-react/src/components/loop_viewer/svg/LoopComponentConverter.js +++ /dev/null @@ -1,17 +0,0 @@ -export default class LoopComponentConverter { - - static buildMapOfComponents(loopCache) { - var componentsMap = new Map([]); - if (typeof (loopCache.getMicroServicePolicies()) !== "undefined") { - loopCache.getMicroServicePolicies().forEach(ms => { - componentsMap.set(ms.name, "/policyModal/MICRO-SERVICE-POLICY/"+ms.name); - }) - } - if (typeof (loopCache.getOperationalPolicies()) !== "undefined") { - loopCache.getOperationalPolicies().forEach(op => { - componentsMap.set(op.name, "/policyModal/OPERATIONAL-POLICY/"+op.name); - }) - } - return componentsMap; - } -} diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.js deleted file mode 100644 index 048f6304..00000000 --- a/ui-react/src/components/loop_viewer/svg/LoopSvg.js +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP CLAMP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights - * reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * =================================================================== - * - */ -import React from 'react'; -import styled from 'styled-components'; -import LoopCache from '../../../api/LoopCache'; -import { withRouter } from "react-router-dom"; -import LoopService from '../../../api/LoopService'; -import LoopComponentConverter from './LoopComponentConverter'; - -const LoopViewSvgDivStyled = styled.svg` - display: flex; - flex-direction: row; - overflow-x: scroll; - background-color: ${props => (props.theme.loopViewerBackgroundColor)}; - border: 1px solid; - border-color: ${props => (props.theme.loopViewerHeaderColor)}; - margin-top: 1em; - margin-left: auto; - margin-right:auto; - margin-bottom: -3em; - align-items: center; - height: 100%; - width: 100%; - -` - -class LoopViewSvg extends React.Component { - - static emptySvg = "No LOOP (SVG)"; - - state = { - svgContent: LoopViewSvg.emptySvg, - loopCache: new LoopCache({}), - componentModalMapping: new Map([]) - } - - constructor(props) { - super(props); - this.handleSvgClick = this.handleSvgClick.bind(this); - this.getSvg = this.getSvg.bind(this); - this.state.loopCache = props.loopCache; - this.state.componentModalMapping = LoopComponentConverter.buildMapOfComponents(props.loopCache); - this.getSvg(props.loopCache.getLoopName()); - } - - shouldComponentUpdate(nextProps, nextState) { - return this.state.svgContent !== nextState.svgContent; - } - - componentWillReceiveProps(newProps) { - if (this.state.loopCache !== newProps.loopCache) { - this.setState({ - loopCache: newProps.loopCache, - componentModalMapping: LoopComponentConverter.buildMapOfComponents(newProps.loopCache) - }); - this.getSvg(newProps.loopCache.getLoopName()); - } - } - - getSvg(loopName) { - if (typeof loopName !== "undefined") { - LoopService.getSvg(loopName).then(svgXml => { - if (svgXml.length !== 0) { - this.setState({ svgContent: svgXml }) - } else { - this.setState({ svgContent: LoopViewSvg.emptySvg }) - } - }); - } else { - this.setState({ svgContent: LoopViewSvg.emptySvg }) - } - } - - handleSvgClick(event) { - console.debug("svg click event received"); - var elementName = event.target.parentNode.parentNode.parentNode.getAttribute('data-element-id'); - console.info("SVG element clicked", elementName); - this.props.history.push(this.state.componentModalMapping.get(elementName)); - } - - render() { - return ( - - - - ); - } -} - -export default withRouter(LoopViewSvg); diff --git a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js b/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js deleted file mode 100644 index e54b500f..00000000 --- a/ui-react/src/components/loop_viewer/svg/LoopSvg.test.js +++ /dev/null @@ -1,132 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP CLAMP - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights - * reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * =================================================================== - * - */ -import React from 'react'; -import { shallow } from 'enzyme'; -import LoopSvg from './LoopSvg'; -import LoopCache from '../../../api/LoopCache'; -import LoopService from '../../../api/LoopService'; - -describe('Verify LoopSvg', () => { - const loopCache = new LoopCache({ - "name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca", - "microServicePolicies": [{ - "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", - "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", - "properties": {"domain": "measurementsForVfScaling"}, - "shared": false, - "jsonRepresentation": {"schema": {}} - }], - "operationalPolicies": [{ - "name": "OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca", - "configurationsJson": { - "operational_policy": { - "controlLoop": {}, - "policies": [] - } - } - }] - }); - - it('Test the render method no loopName', () => { - const localLoopCache = new LoopCache({ - "microServicePolicies": [{ - "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", - "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", - "properties": {"domain": "measurementsForVfScaling"}, - "shared": false, - "jsonRepresentation": {"schema": {}} - }] - }); - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('Test the render method', () => { - const component = shallow( - - ); - - expect(component).toMatchSnapshot(); - }); - - it('Test the render method svg not empty', async () => { - const flushPromises = () => new Promise(setImmediate); - LoopService.getSvg = jest.fn().mockImplementation(() => { - return Promise.resolve(""); - }); - const component = shallow( - - ); - await flushPromises(); - expect(component).toMatchSnapshot(); - }); - - it('Test handleSvgClick', () => { - const historyMock = { push: jest.fn() }; - - const component = shallow( - - ); - let dummyElement = document.createElement('div'); - dummyElement.setAttribute("data-element-id","TCA_h2NMX_v1_0_ResourceInstanceName1_tca"); - - const event = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}}; - - component.simulate('click', event); - component.update(); - - expect(historyMock.push.mock.calls[0]).toEqual([ '/policyModal/MICRO-SERVICE-POLICY/TCA_h2NMX_v1_0_ResourceInstanceName1_tca']); - - //click operational policy - dummyElement.setAttribute("data-element-id","OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca"); - const event2 = { target: { parentNode: { parentNode:{ parentNode: dummyElement }}}}; - - component.simulate('click', event2); - component.update(); - - expect(historyMock.push.mock.calls[1]).toEqual([ '/policyModal/OPERATIONAL-POLICY/OPERATIONAL_h2NMX_v1_0_ResourceInstanceName1_tca']); - }); - - it('Test componentWillReceiveProps method', () => { - const localLoopCache = new LoopCache({ - "microServicePolicies": [{ - "name": "TCA_h2NMX_v1_0_ResourceInstanceName1_tca", - "modelType": "onap.policies.monitoring.cdap.tca.hi.lo.app", - "properties": {"domain": "measurementsForVfScaling"}, - "shared": false, - "jsonRepresentation": {"schema": {}} - }] - }); - const component = shallow( - - ); - - expect(component.state('componentModalMapping').size).toEqual(1); - - component.setProps({loopCache: loopCache}); - expect(component.state('componentModalMapping').size).toEqual(2); - }); -}); diff --git a/ui-react/src/components/loop_viewer/svg/SvgGenerator.js b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js new file mode 100644 index 00000000..d718c2e4 --- /dev/null +++ b/ui-react/src/components/loop_viewer/svg/SvgGenerator.js @@ -0,0 +1,240 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * =================================================================== + * + */ + +import React from 'react' +import styled from 'styled-components'; +import { withRouter } from "react-router-dom"; +import LoopCache from '../../../api/LoopCache'; +import OnapConstant from '../../../utils/OnapConstants'; + +const DivStyled = styled.div` + overflow-x: scroll; + width: 100%; + height: 100%; +` + +const emptySvg = ( No LOOP (SVG) ); + +class SvgGenerator extends React.Component { + boxWidth = 200; + boxHeight = 100; + boxSpace = 50; + + static GENERATED_FROM_INSTANCE = "INSTANCE"; + static GENERATED_FROM_TEMPLATE = "TEMPLATE"; + + state = { + loopCache: new LoopCache({}), + clickable: false, + generatedFrom: SvgGenerator.GENERATED_FROM_INSTANCE, // INSTANCE / TEMPLATE + } + + constructor(props) { + super(props); + this.state.loopCache = props.loopCache; + this.state.clickable = props.clickable; + this.state.generatedFrom = props.generatedFrom; + this.handleSvgClick = this.handleSvgClick.bind(this); + this.renderSvg = this.renderSvg.bind(this); + } + + shouldComponentUpdate(nextProps, nextState) { + return this.state.loopCache !== nextState.loopCache; + } + + componentWillReceiveProps(newProps) { + if (this.state.loopCache !== newProps.loopCache) { + this.setState({ + loopCache: newProps.loopCache, + }); + } + } + + handleSvgClick(event) { + if (this.state.clickable) { + console.debug("svg click event received"); + var elementName = event.target.parentNode.getAttribute('policyId'); + console.info("SVG element clicked", elementName); + if (elementName !== null) { + this.props.history.push("/policyModal/"+event.target.parentNode.getAttribute('policyType')+"/"+elementName); + } + } + } + + createVesBox (xPos) { + return this.createOneBox(xPos,null,null,'VES Collector','VES',null); + } + + createOneArrow(xPos) { + return ( + + + + + + + + + ); + } + + createBeginCircle(xPos, text) { + return ( + + + {text} + + ); + } + + createEndCircle(xPos, text) { + return ( + + + {text} + + ); + } + + createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) { + return ( + + + + {title} + {name} + {policyId} + + + ); + } + + createSvgFromTemplate() { + const allElements = []; + var xPos = 0; + + allElements.push(this.createBeginCircle(xPos,"Start")) + xPos+=(this.boxWidth+this.boxSpace); + + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + + allElements.push(this.createVesBox(xPos)); + xPos+=(this.boxWidth+this.boxSpace); + + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + //createOneBox(xPos, policyId, loopElementModelId , name, title, policyType) + for (var loopElement of this.state.loopCache.getAllLoopElementModels()) { + + allElements.push(this.createOneBox(xPos, + loopElement['name'], + loopElement['name'], + loopElement['shortName'], + loopElement['loopElementType'], + loopElement['loopElementType'])) + xPos+=(this.boxWidth+this.boxSpace); + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + } + + allElements.push(this.createEndCircle(xPos, "End")) + xPos+=(this.boxWidth+this.boxSpace); + + return allElements; + } + + createSvgFromInstance() { + const allElements = []; + var xPos = 0; + + allElements.push(this.createBeginCircle(xPos,"Start")) + xPos+=(this.boxWidth+this.boxSpace); + + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + + allElements.push(this.createVesBox(xPos)); + xPos+=(this.boxWidth+this.boxSpace); + + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + + for (var msPolicy in this.state.loopCache.getMicroServicePolicies()) { + var loopElementModelName = this.state.loopCache.getMicroServicePolicies()[msPolicy]['loopElementModel']; + if (loopElementModelName !== undefined) { + loopElementModelName = loopElementModelName['name']; + } + allElements.push(this.createOneBox(xPos, + this.state.loopCache.getMicroServicePolicies()[msPolicy]['name'], + loopElementModelName, + this.state.loopCache.getMicroServicePolicies()[msPolicy]['policyModel']['policyAcronym'], + 'microservice', + OnapConstant.microServiceType)) + xPos+=(this.boxWidth+this.boxSpace); + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + } + + for (var opPolicy in this.state.loopCache.getOperationalPolicies()) { + loopElementModelName = this.state.loopCache.getOperationalPolicies()[opPolicy]['loopElementModel']; + if (loopElementModelName !== undefined) { + loopElementModelName = loopElementModelName['name']; + } + allElements.push(this.createOneBox(xPos, + this.state.loopCache.getOperationalPolicies()[opPolicy]['name'], + loopElementModelName, + this.state.loopCache.getOperationalPolicies()[opPolicy]['policyModel']['policyAcronym'], + 'operational', + OnapConstant.operationalPolicyType)) + xPos+=(this.boxWidth+this.boxSpace); + allElements.push(this.createOneArrow(xPos-this.boxSpace)); + } + + allElements.push(this.createEndCircle(xPos, "End")) + xPos+=(this.boxWidth+this.boxSpace); + + return allElements; + } + + renderSvg() { + if (this.state.loopCache.getLoopName() === undefined) { + return [emptySvg]; + } + if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_INSTANCE) { + return this.createSvgFromInstance(); + } else if (this.state.generatedFrom === SvgGenerator.GENERATED_FROM_TEMPLATE) { + return this.createSvgFromTemplate(); + } + } + + render() { + var allTheElements = this.renderSvg(); + var svgWidth = this.boxWidth*allTheElements.length; + var svgHeight = this.boxHeight+100; + return ( + + + {allTheElements} + + + ); + } +} + +export default withRouter(SvgGenerator); diff --git a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap b/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap deleted file mode 100644 index e05f1c79..00000000 --- a/ui-react/src/components/loop_viewer/svg/__snapshots__/LoopSvg.test.js.snap +++ /dev/null @@ -1,34 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Verify LoopSvg Test the render method 1`] = ` -No LOOP (SVG)", - } - } - onClick={[Function]} -/> -`; - -exports[`Verify LoopSvg Test the render method no loopName 1`] = ` -No LOOP (SVG)", - } - } - onClick={[Function]} -/> -`; - -exports[`Verify LoopSvg Test the render method svg not empty 1`] = ` -", - } - } - onClick={[Function]} -/> -`; diff --git a/ui-react/src/components/loop_viewer/svg/example.svg b/ui-react/src/components/loop_viewer/svg/example.svg deleted file mode 100644 index a7c40ee2..00000000 --- a/ui-react/src/components/loop_viewer/svg/example.svg +++ /dev/null @@ -1 +0,0 @@ -VESTCAOperationalPolicy \ No newline at end of file -- cgit