RIFT-14850: Volume styling update
[osm/UI.git] / skyquake / plugins / launchpad / src / recordViewer / recordCard.jsx
1
2 /*
3  *
4  *   Copyright 2016 RIFT.IO Inc
5  *
6  *   Licensed under the Apache License, Version 2.0 (the "License");
7  *   you may not use this file except in compliance with the License.
8  *   You may obtain a copy of the License at
9  *
10  *       http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *   Unless required by applicable law or agreed to in writing, software
13  *   distributed under the License is distributed on an "AS IS" BASIS,
14  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *   See the License for the specific language governing permissions and
16  *   limitations under the License.
17  *
18  */
19 import React from 'react';
20 import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
21 import DashboardCard from 'widgets/dashboard_card/dashboard_card.jsx';
22 import MonitoringParamsCarousel from '../monitoring_params/monitoringParamsCarousel.jsx';
23 import VnfrCard from '../vnfr/vnfrCard.jsx';
24 import {LaunchpadCard, LpCardNfviMetrics, EpaParams, NsrPrimitiveJobList} from '../launchpad_card/launchpadCard.jsx';
25 import VnfrConfigPrimitives from '../launchpad_card/vnfrConfigPrimitives.jsx';
26 import NsrConfigPrimitives from '../launchpad_card/nsrConfigPrimitives.jsx';
27 import NsrScalingGroups from '../launchpad_card/nsrScalingGroups.jsx';
28 import LoadingIndicator from 'widgets/loading-indicator/loadingIndicator.jsx';
29 import NfviMetricBars from 'widgets/nfvi-metric-bars/nfviMetricBars.jsx';
30 import ParseMP from '../monitoring_params/monitoringParamComponents.js';
31 import PlacementGroupsInfo from './placementGroupsInfo.jsx';
32 import JobListCard from '../launchpad_card/jobListCard.jsx';
33 import NSVirtualLinks from '../virtual_links/nsVirtualLinks.jsx';
34 import LaunchpadFleetStore from '../launchpadFleetStore.js';
35
36 import Prism from 'prismjs';
37 import 'prismjs/themes/prism.css';
38
39
40 export default class RecordCard extends React.Component {
41   constructor(props) {
42     super(props)
43   }
44
45   handleSelect = (index, last) => {
46       // console.log('Selected tab is', index, 'last index is', last);
47   }
48
49   openConsole = (url, event) => {
50     event.preventDefault();
51     LaunchpadFleetStore.getVDUConsoleLink(url);
52   }
53
54   render(){
55     let self = this;
56     let html;
57     let content;
58     let card;
59     let cardData = {};
60     let components = [];
61     let configPrimitivesProps = {};
62     let displayConfigPrimitives = false;
63     let configPrimitiveComponent = null;
64     let scalingGroupsProps = {};
65     let displayScalingGroups = false;
66     let scalingGroupComponent = null;
67     let consoleUrlsComponent = null;
68     let consoleUrlsList = [];
69
70     let displayNSVirtualLinks = false;
71     let nsVirtualLinksProps = {};
72     let nsVirtualLinksComponent = null;
73     let displayVolumesTab = false;
74     let volumesHTML = [];
75     let tabList = [];
76     let tabPanels = [];
77
78     let notice = null;
79
80     switch(this.props.type) {
81       case 'vnfr' :
82         cardData = this.props.data[0];
83         // Disabling config primitives for VNF
84         configPrimitivesProps = [cardData];
85         displayConfigPrimitives = cardData['service-primitives-present'];
86         if (displayConfigPrimitives) {
87           configPrimitiveComponent = (
88             <div className="flex vnfrConfigPrimitiveContainer">
89               <VnfrConfigPrimitives data={configPrimitivesProps} />
90             {/* <NsrPrimitiveJobList jobs={cardData['config-agent-job']}/> */}
91             <div style={{display:'flex', flexDirection: 'column',     flex: '1 1 40%'}}>
92                 <div className="launchpadCard_title">
93                   JOB LIST
94                 </div>
95                 <div className="scrollContainer">
96                 {
97                   //Sort for recent on top
98                   this.props.jobData
99                   .sort(function(a,b){
100                     return parseInt(b['job-id']) - parseInt(a['job-id']);
101                   })
102                   .map(function(job){
103                     //Return only vnfr configs
104                     if(job["triggered-by"] == 'vnf-primitive') {
105                       return job.vnfr.map(function(v){
106                         //That match the currently selected job id
107                         if(v.id == cardData.id) {
108                           return v.primitive.map(function(p, i) {
109                             return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={ob['job-id'] + '-' + i} {...p} />
110                           })
111                         }
112                       })
113                     }
114                   })}
115                 </div>
116               </div>
117             </div>
118           );
119         }
120
121         if (cardData['vdur']) {
122           cardData['vdur'].map((vdur, index) => {
123             let consoleLink = vdur['console-url'] ? 'Obtain Token And Open VM Console' : 'None';
124             consoleUrlsList.push(
125               <li key={index}>
126                 <h3>
127                   {vdur['name'] + '-' + vdur.id.substr(0,4)}
128                 </h3>
129                 <span className='consoleLink' onClick={self.openConsole.bind(self, vdur["console-url"])}>
130                   {consoleLink} *
131                 </span>
132               </li>
133             )
134             notice = <li className='notice'>* If a separate browser window does not open, please check if the popup was blocked and allow it.</li>
135             if(vdur.hasOwnProperty('volumes') && (vdur.volumes.length > 0)) {
136               displayVolumesTab = true;
137               vdur.volumer.map((volume, vi) => {
138                 // let html = Prism.highlight(JSON.stringify(volume), Prism.languages.javascript, 'javascript');
139                 // volumesHTML.push(
140                 //     <pre className="language-js" key={index + '-' + vi}>
141                 //       <code dangerouslySetInnerHTML={{__html: html}} />
142                 //     </pre>
143                 let properties = [];
144                  _.forEach(volume, function(v, k) {
145                     properties.push(
146                       <div style={{display: 'flex', margin: '0.5rem 0'}} key={k + vi}>
147                         <div style={{margin: '0 1rem',
148     fontWeight: 'bold', textTransform: 'uppercase'}}>{k}</div>
149                         <div>{v}</div>
150                       </div>
151                     )
152                   })
153                 volumesHTML.push(
154                     <div key={vi}>
155                       <div className="launchpadCard_title">
156                         VOLUME
157                       </div>
158
159                       {
160                         properties
161                       }
162                     </div>
163                 )
164               })
165             }
166           });
167           consoleUrlsComponent = (
168             <div className="consoleUrlsComponent">
169               <ul className="consoleUrlsList">
170                 {consoleUrlsList}
171                 {notice}
172               </ul>
173             </div>
174           );
175         }
176         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
177         break;
178       case 'nsr' :
179         cardData = this.props.data.nsrs[0];
180         configPrimitivesProps = cardData;
181         scalingGroupsProps = cardData;
182         displayConfigPrimitives = cardData['service-primitive'];
183         displayScalingGroups = cardData['scaling-group-descriptor'] ? true : false;
184         let sortedJobs = this.props.jobData.sort(function(a,b){
185                     return parseInt(b['job-id']) - parseInt(a['job-id']);
186                   });
187         if (displayConfigPrimitives) {
188           configPrimitiveComponent = (
189             <div className="flex nsConfigPrimitiveContainer">
190               <NsrConfigPrimitives data={configPrimitivesProps} />
191               <div style={{display:'flex', flexDirection: 'column',     flex: '1 1 40%'}}>
192                 <div className="launchpadCard_title">
193                   JOB LIST
194                 </div>
195                 <div className="scrollContainer">
196                   {sortedJobs.map(function(job, i){
197                     if(job["triggered-by"] == 'ns-primitive') {
198                       return <JobListCard type="nsr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'nsr'} {...job} />
199                     }
200                   })
201                   .concat(sortedJobs.map(function(job) {
202                     if(!job.hasOwnProperty('job-name') && (job["triggered-by"] == 'ns-primitive')) {
203                       return job.vnfr.map(function(v, h){
204                         //That match the currently selected job id
205                         if(v.id == cardData.id) {
206                           return v.primitive.map(function(p, i) {
207                             return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={ob['job-id'] + '-' + 'vnfr' + '-' + h} {...p} />
208                           })
209                         }
210                       })
211                     }
212                   }))
213                 }
214                 </div>
215               </div>
216             </div>
217           );
218         }
219         if (displayScalingGroups) {
220           scalingGroupComponent = (
221             <div className="flex nsrScalingGroupContainer">
222               <NsrScalingGroups data={scalingGroupsProps} />
223             </div>
224           );
225         }
226
227         // Virtual Links tab content
228         displayNSVirtualLinks = true;
229         nsVirtualLinksProps = cardData;
230         if (displayNSVirtualLinks) {
231           nsVirtualLinksComponent = (
232             <div className='flex nsVirtualLinksContainer'>
233               <NSVirtualLinks data={nsVirtualLinksProps} />
234             </div>
235           );
236         };
237
238         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
239         break;
240     }
241     let mgmt_interface = cardData["dashboard-url"];
242     let mgmtHTML;
243     let metricsAndParams = [];
244
245
246     let nfviMetrics = <LpCardNfviMetrics data={cardData["nfvi-metrics"]} />;
247     metricsAndParams.push(<div className="monitoringParams" key="mp">
248                           {components.map(function(c, k) {
249                             return <div key={k} className="mpSlide">{c.title}{c.component}</div>
250                           })}
251                           </div>)
252     metricsAndParams.push((<div key="nvfi" className="nfvi-metrics">
253       { nfviMetrics }
254       <EpaParams data={cardData["epa-params"]} />
255     </div>))
256
257
258
259     if(mgmt_interface) {
260       mgmtHTML = <a href={mgmt_interface} target="_blank">Open Application Dashboard</a>;
261     }
262       if(this.props.isLoading) {
263         html = <DashboardCard className="loading" showHeader={true} title={cardData["short-name"]}><LoadingIndicator size={10} show={true} /></DashboardCard>
264       } else {
265         let glyphValue = (this.props.mmmrecordDetailsToggleValue) ? "chevron-left" : "chevron-right";
266
267         if (this.props.type == 'nsr') {
268           tabList.push(
269             <Tab key={cardData.id}>NS Data</Tab>
270           )
271         } else if (this.props.type == 'vnfr') {
272           tabList.push(
273             <Tab key={cardData.id}>VNF Data</Tab>
274           )
275         }
276
277         tabPanels.push(
278           <TabPanel key={cardData.id + '-panel'}>
279
280               <div className="launchpadCard_title" style={{textAlign:'right'}}><span style={{float:'left'}}>MONITORING PARAMETERS</span>
281                 {mgmtHTML}
282               </div>
283               {metricsAndParams}
284               <div className="cardSectionFooter">
285               </div>
286           </TabPanel>
287         )
288
289
290         if (this.props.type == 'nsr') {
291           if (scalingGroupComponent) {
292             tabList.push(
293             <Tab key={cardData.id + '-sg'}>Scaling Groups</Tab>
294           );
295
296           tabPanels.push(
297               <TabPanel key={cardData.id + '-sg-panel'}>
298                   <div>
299                     {scalingGroupComponent}
300                   </div>
301                   <div className="cardSectionFooter">
302                   </div>
303               </TabPanel>
304             );
305           }
306           if(cardData.hasOwnProperty('vnfd-placement-group-maps')
307              || cardData.hasOwnProperty('nsd-placement-group-maps')) {
308             tabList.push(
309                <Tab key='placement_groups'>
310                 Placement
311                </Tab>
312              );
313             tabPanels.push(
314                <TabPanel key='placement_groups_panel'>
315                   <div>
316                     <PlacementGroupsInfo nsr={cardData} navRef={this.props.navRef} />
317                   </div>
318               </TabPanel>
319              );
320           }
321         }
322
323         if (configPrimitiveComponent) {
324           let primitivesTabTitle = '';
325           if (this.props.type == 'nsr') {
326             primitivesTabTitle = 'Service Primitive';
327           } else if (this.props.type == 'vnfr') {
328             primitivesTabTitle = 'Service Primitive'
329           }
330
331           tabList.push(
332             <Tab key={cardData.id + '-cp'}>{primitivesTabTitle}</Tab>
333           );
334
335           tabPanels.push(
336             <TabPanel key={cardData.id + '-cp-panel'}>
337               <div className="configPrimitives">
338                 {configPrimitiveComponent}
339               </div>
340               <div className="cardSectionFooter">
341               </div>
342             </TabPanel>
343           )
344         }
345
346         if (nsVirtualLinksComponent) {
347           let nsVirtualLinksTabTitle = 'Virtual Links';
348           tabList.push(
349               <Tab key={cardData.id + '-nsvl'}>{nsVirtualLinksTabTitle}</Tab>
350           );
351
352           tabPanels.push(
353             <TabPanel key={cardData.id + '-nsvl-panel'}>
354               <div className='nsVirtualLinks'>
355                 {nsVirtualLinksComponent}
356               </div>
357               <div className="cardSectionFooter">
358               </div>
359             </TabPanel>
360           );
361         }
362
363         if (consoleUrlsComponent) {
364           let consoleUrlsTabTitle = '';
365           consoleUrlsTabTitle = 'VDU Console Links';
366
367           tabList.push(
368             <Tab key={cardData.id + '-cp'}>{consoleUrlsTabTitle}</Tab>
369           );
370
371           tabPanels.push(
372             <TabPanel key={cardData.id + '-cp-panel'}>
373               <div className="consoleUrls">
374                 {consoleUrlsComponent}
375               </div>
376               <div className="cardSectionFooter">
377               </div>
378             </TabPanel>
379           )
380         }
381
382         if (displayVolumesTab) {
383
384           tabList.push(
385             <Tab key={cardData.id + '-volumes'}>Volumes</Tab>
386           );
387
388           tabPanels.push(
389             <TabPanel key={cardData.id + '-volumes-panel'}>
390               {volumesHTML}
391               <div className="cardSectionFooter">
392               </div>
393             </TabPanel>
394           )
395         }
396
397         html = (
398             <DashboardCard className="recordCard" showHeader={true} title={cardData["short-name"]}>
399               <a onClick={this.props.recordDetailsToggleFn} className={"recordViewToggle " + (this.props.recordDetailsToggleValue ? "on": null)}><span className="oi" data-glyph={glyphValue} title="Toggle Details Panel" aria-hidden="true"></span></a>
400               <Tabs onSelect={this.handleSelect}>
401                 <TabList>
402                     {tabList}
403                 </TabList>
404                 {tabPanels}
405               </Tabs>
406             </DashboardCard>
407         );
408       }
409     return html;
410   }
411 }
412 RecordCard.defaultProps = {
413   type: "default",
414   data: {},
415   isLoading: true,
416   jobData: []
417 }