0d58f7308b765a4068d9b06889d342b0443716ea
[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 import _forEach from 'lodash/forEach';
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={job['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.volumes.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                 function buildProperties(obj) {
144                   let p = [];
145                     _forEach(obj, function(v, k) {
146                       if (!v) {
147                         return null;
148                       }
149                     p.push(
150                       <div style={{margin: '0.5rem 0.5rem'}} key={k + '-' + vi}>
151                         <div style={{margin: '0 0.5rem', fontWeight: 'bold', textTransform: 'uppercase', color: '#5b5b5b'}}>{k}</div>
152                         <div style={{margin: '0 0.5rem'}}>{(v.constructor.name == 'String' || v.constructor.name == 'Number') ? v : buildProperties(v)}</div>
153                       </div>
154                     )
155                   });
156                     return p;
157                  }
158                 volumesHTML.push(
159                     <div key={vi}>
160                       <div className="launchpadCard_title">
161                         VOLUME
162                       </div>
163                       <div style={{display: 'flex', flexDirection: 'column'}}>
164                       {
165                         buildProperties(volume)
166                       }
167                       </div>
168                     </div>
169                 )
170               })
171             }
172           });
173           consoleUrlsComponent = (
174             <div className="consoleUrlsComponent">
175               <ul className="consoleUrlsList">
176                 {consoleUrlsList}
177                 {notice}
178               </ul>
179             </div>
180           );
181         }
182         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
183         break;
184       case 'nsr' :
185         cardData = this.props.data.nsrs[0];
186         configPrimitivesProps = cardData;
187         scalingGroupsProps = cardData;
188         displayConfigPrimitives = cardData['service-primitive'];
189         displayScalingGroups = cardData['scaling-group-descriptor'] ? true : false;
190         let sortedJobs = this.props.jobData.sort(function(a,b){
191                     return parseInt(b['job-id']) - parseInt(a['job-id']);
192                   });
193         if (displayConfigPrimitives) {
194           configPrimitiveComponent = (
195             <div className="flex nsConfigPrimitiveContainer">
196               <NsrConfigPrimitives data={configPrimitivesProps} />
197               <div style={{display:'flex', flexDirection: 'column',     flex: '1 1 40%'}}>
198                 <div className="launchpadCard_title">
199                   JOB LIST
200                 </div>
201                 <div className="scrollContainer">
202                   {sortedJobs.map(function(job, i){
203                     if(job["triggered-by"] == 'ns-primitive') {
204                       return <JobListCard type="nsr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'nsr'} {...job} />
205                     }
206                   })
207                   .concat(sortedJobs.map(function(job) {
208                     if(!job.hasOwnProperty('job-name') && (job["triggered-by"] == 'ns-primitive')) {
209                       return job.vnfr.map(function(v, h){
210                         //That match the currently selected job id
211                         if(v.id == cardData.id) {
212                           return v.primitive.map(function(p, i) {
213                             return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'vnfr' + '-' + h} {...p} />
214                           })
215                         }
216                       })
217                     }
218                   }))
219                 }
220                 </div>
221               </div>
222             </div>
223           );
224         }
225         if (displayScalingGroups) {
226           scalingGroupComponent = (
227             <div className="flex nsrScalingGroupContainer">
228               <NsrScalingGroups data={scalingGroupsProps} />
229             </div>
230           );
231         }
232
233         // Virtual Links tab content
234         displayNSVirtualLinks = true;
235         nsVirtualLinksProps = cardData;
236         if (displayNSVirtualLinks) {
237           nsVirtualLinksComponent = (
238             <div className='flex nsVirtualLinksContainer'>
239               <NSVirtualLinks data={nsVirtualLinksProps} />
240             </div>
241           );
242         };
243
244         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
245         break;
246     }
247     let mgmt_interface = cardData["dashboard-url"];
248     let mgmtHTML;
249     let metricsAndParams = [];
250
251
252     let nfviMetrics = <LpCardNfviMetrics data={cardData["nfvi-metrics"]} />;
253     metricsAndParams.push(<div className="monitoringParams" key="mp">
254                           {components.map(function(c, k) {
255                             return <div key={k} className="mpSlide">{c.title}{c.component}</div>
256                           })}
257                           </div>)
258     metricsAndParams.push((<div key="nvfi" className="nfvi-metrics">
259       { nfviMetrics }
260       <EpaParams data={cardData["epa-params"]} />
261     </div>))
262
263
264
265     if(mgmt_interface) {
266       mgmtHTML = <a href={mgmt_interface} target="_blank">Open Application Dashboard</a>;
267     }
268       if(this.props.isLoading) {
269         html = <DashboardCard className="loading" showHeader={true} title={cardData["short-name"]}><LoadingIndicator size={10} show={true} /></DashboardCard>
270       } else {
271         let glyphValue = (!this.props.recordDetailsToggleValue) ? "chevron-left" : "chevron-right";
272
273         if (this.props.type == 'nsr') {
274           tabList.push(
275             <Tab key={cardData.id}>NS Data</Tab>
276           )
277         } else if (this.props.type == 'vnfr') {
278           tabList.push(
279             <Tab key={cardData.id}>VNF Data</Tab>
280           )
281         }
282
283         tabPanels.push(
284           <TabPanel key={cardData.id + '-panel'}>
285
286               <div className="launchpadCard_title" style={{textAlign:'right'}}><span style={{float:'left'}}>MONITORING PARAMETERS</span>
287                 {mgmtHTML}
288               </div>
289               {metricsAndParams}
290               <div className="cardSectionFooter">
291               </div>
292           </TabPanel>
293         )
294
295
296         if (this.props.type == 'nsr') {
297           if (scalingGroupComponent) {
298             tabList.push(
299             <Tab key={cardData.id + '-sg'}>Scaling Groups</Tab>
300           );
301
302           tabPanels.push(
303               <TabPanel key={cardData.id + '-sg-panel'}>
304                   <div>
305                     {scalingGroupComponent}
306                   </div>
307                   <div className="cardSectionFooter">
308                   </div>
309               </TabPanel>
310             );
311           }
312           if(cardData.hasOwnProperty('vnfd-placement-group-maps')
313              || cardData.hasOwnProperty('nsd-placement-group-maps')) {
314             tabList.push(
315                <Tab key='placement_groups'>
316                 Placement
317                </Tab>
318              );
319             tabPanels.push(
320                <TabPanel key='placement_groups_panel'>
321                   <div>
322                     <PlacementGroupsInfo nsr={cardData} navRef={this.props.navRef} />
323                   </div>
324               </TabPanel>
325              );
326           }
327         }
328
329         if (configPrimitiveComponent) {
330           let primitivesTabTitle = '';
331           if (this.props.type == 'nsr') {
332             primitivesTabTitle = 'Service Primitive';
333           } else if (this.props.type == 'vnfr') {
334             primitivesTabTitle = 'Service Primitive'
335           }
336
337           tabList.push(
338             <Tab key={cardData.id + '-cp'}>{primitivesTabTitle}</Tab>
339           );
340
341           tabPanels.push(
342             <TabPanel key={cardData.id + '-cp-panel'}>
343               <div className="configPrimitives">
344                 {configPrimitiveComponent}
345               </div>
346               <div className="cardSectionFooter">
347               </div>
348             </TabPanel>
349           )
350         }
351
352         if (nsVirtualLinksComponent) {
353           let nsVirtualLinksTabTitle = 'Virtual Links';
354           tabList.push(
355               <Tab key={cardData.id + '-nsvl'}>{nsVirtualLinksTabTitle}</Tab>
356           );
357
358           tabPanels.push(
359             <TabPanel key={cardData.id + '-nsvl-panel'}>
360               <div className='nsVirtualLinks'>
361                 {nsVirtualLinksComponent}
362               </div>
363               <div className="cardSectionFooter">
364               </div>
365             </TabPanel>
366           );
367         }
368
369         if (consoleUrlsComponent) {
370           let consoleUrlsTabTitle = '';
371           consoleUrlsTabTitle = 'VDU Console Links';
372
373           tabList.push(
374             <Tab key={cardData.id + '-vducl'}>{consoleUrlsTabTitle}</Tab>
375           );
376
377           tabPanels.push(
378             <TabPanel key={cardData.id + '-vducl-panel'}>
379               <div className="consoleUrls">
380                 {consoleUrlsComponent}
381               </div>
382               <div className="cardSectionFooter">
383               </div>
384             </TabPanel>
385           )
386         }
387
388         if (displayVolumesTab) {
389
390           tabList.push(
391             <Tab key={cardData.id + '-volumes'}>Volumes</Tab>
392           );
393
394           tabPanels.push(
395             <TabPanel key={cardData.id + '-volumes-panel'}>
396               {volumesHTML}
397               <div className="cardSectionFooter">
398               </div>
399             </TabPanel>
400           )
401         }
402
403         html = (
404             <DashboardCard className="recordCard" showHeader={true} title={cardData["short-name"]}>
405               <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>
406               <Tabs onSelect={this.handleSelect}>
407                 <TabList>
408                     {tabList}
409                 </TabList>
410                 {tabPanels}
411               </Tabs>
412             </DashboardCard>
413         );
414       }
415     return html;
416   }
417 }
418 RecordCard.defaultProps = {
419   type: "default",
420   data: {},
421   isLoading: true,
422   jobData: []
423 }