7fad6f413bd57eccf0f4e3cb2ec148dad45c3cd9
[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 import {SkyquakeRBAC, isRBACValid} from 'widgets/skyquake_rbac/skyquakeRBAC.jsx';
40 import ROLES from 'utils/roleConstants.js';
41
42 const PROJECT_ROLES = ROLES.PROJECT;
43
44 export default class RecordCard extends React.Component {
45   constructor(props) {
46     super(props)
47   }
48
49   handleSelect = (index, last) => {
50       // console.log('Selected tab is', index, 'last index is', last);
51   }
52
53   openConsole = (url, event) => {
54     event.preventDefault();
55     LaunchpadFleetStore.getVDUConsoleLink(url);
56   }
57
58   render(){
59     let self = this;
60     let html;
61     let content;
62     let card;
63     let cardData = {};
64     let components = [];
65     let configPrimitivesProps = {};
66     let displayConfigPrimitives = false;
67     let configPrimitiveComponent = null;
68     let scalingGroupsProps = {};
69     let displayScalingGroups = false;
70     let scalingGroupComponent = null;
71     let consoleUrlsComponent = null;
72     let consoleUrlsList = [];
73
74     let displayNSVirtualLinks = false;
75     let nsVirtualLinksProps = {};
76     let nsVirtualLinksComponent = null;
77     let displayVolumesTab = false;
78     let volumesHTML = [];
79     let tabList = [];
80     let tabPanels = [];
81
82     let notice = null;
83
84     let hasAccess = isRBACValid(this.context.userProfile, [PROJECT_ROLES.LCM_ADMIN]);
85
86     switch(this.props.type) {
87       case 'vnfr' :
88         cardData = this.props.data[0];
89         // Disabling config primitives for VNF
90         configPrimitivesProps = [cardData];
91         displayConfigPrimitives = cardData['service-primitives-present'];
92         if (displayConfigPrimitives) {
93           configPrimitiveComponent = (
94             <div className="flex vnfrConfigPrimitiveContainer">
95               <VnfrConfigPrimitives data={configPrimitivesProps} hasAccess={hasAccess} />
96             {/* <NsrPrimitiveJobList jobs={cardData['config-agent-job']}/> */}
97             <div style={{display:'flex', flexDirection: 'column',     flex: '1 1 40%'}}>
98                 <div className="launchpadCard_title">
99                   JOB LIST
100                 </div>
101                 <div className="scrollContainer">
102                 {
103                   //Sort for recent on top
104                   this.props.jobData
105                   .sort(function(a,b){
106                     return parseInt(b['job-id']) - parseInt(a['job-id']);
107                   })
108                   .map(function(job){
109                     //Return only vnfr configs
110                     if(job["triggered-by"] == 'vnf-primitive') {
111                       return job.vnfr.map(function(v){
112                         //That match the currently selected job id
113                         if(v.id == cardData.id) {
114                           return v.primitive.map(function(p, i) {
115                             return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + i} {...p} />
116                           })
117                         }
118                       })
119                     }
120                   })}
121                 </div>
122               </div>
123             </div>
124           );
125         }
126
127         if (cardData['vdur']) {
128           cardData['vdur'].map((vdur, index) => {
129             let consoleLink = vdur['console-url'] ? 'Obtain Token And Open VM Console' : 'None';
130             consoleUrlsList.push(
131               <li key={index}>
132                 <h3>
133                   {vdur['name'] + '-' + vdur.id.substr(0,4)}
134                 </h3>
135                 <span className='consoleLink' onClick={self.openConsole.bind(self, vdur["console-url"])}>
136                   {consoleLink} *
137                 </span>
138               </li>
139             )
140             notice = <li className='notice'>* If a separate browser window does not open, please check if the popup was blocked and allow it.</li>
141             if(vdur.hasOwnProperty('volumes') && (vdur.volumes.length > 0)) {
142               displayVolumesTab = true;
143               vdur.volumes.map((volume, vi) => {
144                 // let html = Prism.highlight(JSON.stringify(volume), Prism.languages.javascript, 'javascript');
145                 // volumesHTML.push(
146                 //     <pre className="language-js" key={index + '-' + vi}>
147                 //       <code dangerouslySetInnerHTML={{__html: html}} />
148                 //     </pre>
149                 function buildProperties(obj) {
150                   let p = [];
151                     _forEach(obj, function(v, k) {
152                     p.push(
153                       <div style={{margin: '0.5rem 0.5rem'}} key={k + '-' + vi}>
154                         <div style={{margin: '0 0.5rem',
155     fontWeight: 'bold', textTransform: 'uppercase', color: '#5b5b5b'}}>{k}</div>
156                         <div style={{margin: '0 0.5rem'}}>{(v.constructor.name == 'String' || v.constructor.name == 'Number') ? v : buildProperties(v)}</div>
157                       </div>
158                     )
159                   });
160                     return p;
161                  }
162                 volumesHTML.push(
163                     <div key={vi}>
164                       <div className="launchpadCard_title">
165                         VOLUME
166                       </div>
167                       <div style={{display: 'flex', flexDirection: 'column'}}>
168                       {
169                         buildProperties(volume)
170                       }
171                       </div>
172                     </div>
173                 )
174               })
175             }
176           });
177           consoleUrlsComponent = (
178             <div className="consoleUrlsComponent">
179               <ul className="consoleUrlsList">
180                 {consoleUrlsList}
181                 {notice}
182               </ul>
183             </div>
184           );
185         }
186         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
187         break;
188       case 'nsr' :
189         cardData = this.props.data.nsrs[0];
190         configPrimitivesProps = cardData;
191         scalingGroupsProps = cardData;
192         displayConfigPrimitives = cardData['service-primitive'];
193         displayScalingGroups = cardData['scaling-group-descriptor'] ? true : false;
194         let sortedJobs = this.props.jobData.sort(function(a,b){
195                     return parseInt(b['job-id']) - parseInt(a['job-id']);
196                   });
197         if (displayConfigPrimitives) {
198           configPrimitiveComponent = (
199             <div className="flex nsConfigPrimitiveContainer">
200               <NsrConfigPrimitives data={configPrimitivesProps} />
201               <div style={{display:'flex', flexDirection: 'column',     flex: '1 1 40%'}}>
202                 <div className="launchpadCard_title">
203                   JOB LIST
204                 </div>
205                 <div className="scrollContainer">
206                   {sortedJobs.map(function(job, i){
207                     if(job["triggered-by"] == 'ns-primitive') {
208                       return <JobListCard type="nsr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'nsr'} {...job} />
209                     }
210                   })
211                   .concat(sortedJobs.map(function(job) {
212                     if(!job.hasOwnProperty('job-name') && (job["triggered-by"] == 'ns-primitive')) {
213                       return job.vnfr.map(function(v, h){
214                         //That match the currently selected job id
215                         if(v.id == cardData.id) {
216                           return v.primitive.map(function(p, i) {
217                             return <JobListCard type="vnfr" job-id={job['job-id']} cardData={cardData} key={job['job-id'] + '-' + 'vnfr' + '-' + h} {...p} />
218                           })
219                         }
220                       })
221                     }
222                   }))
223                 }
224                 </div>
225               </div>
226             </div>
227           );
228         }
229         if (displayScalingGroups) {
230           scalingGroupComponent = (
231             <div className="flex nsrScalingGroupContainer">
232               <NsrScalingGroups data={scalingGroupsProps} />
233             </div>
234           );
235         }
236
237         // Virtual Links tab content
238         displayNSVirtualLinks = true;
239         nsVirtualLinksProps = cardData;
240         if (displayNSVirtualLinks) {
241           nsVirtualLinksComponent = (
242             <div className='flex nsVirtualLinksContainer'>
243               <NSVirtualLinks data={nsVirtualLinksProps} />
244             </div>
245           );
246         };
247
248         components = ParseMP.call(this, cardData["monitoring-param"], "vnfr-id");
249         break;
250     }
251     let mgmt_interface = cardData["dashboard-url"];
252     let mgmtHTML;
253     let metricsAndParams = [];
254
255
256     let nfviMetrics = <LpCardNfviMetrics data={cardData["nfvi-metrics"]} />;
257     metricsAndParams.push(<div className="monitoringParams" key="mp">
258                           {components.map(function(c, k) {
259                             return <div key={k} className="mpSlide">{c.title}{c.component}</div>
260                           })}
261                           </div>)
262     metricsAndParams.push((<div key="nvfi" className="nfvi-metrics">
263       { nfviMetrics }
264       <EpaParams data={cardData["epa-params"]} />
265     </div>))
266
267
268
269     if(mgmt_interface) {
270       mgmtHTML = <a href={mgmt_interface} target="_blank">Open Application Dashboard</a>;
271     }
272       if(this.props.isLoading) {
273         html = <DashboardCard className="loading" showHeader={true} title={cardData["short-name"]}><LoadingIndicator size={10} show={true} /></DashboardCard>
274       } else {
275         let glyphValue = (!this.props.recordDetailsToggleValue) ? "chevron-left" : "chevron-right";
276
277         if (this.props.type == 'nsr') {
278           tabList.push(
279             <Tab key={cardData.id}>NS Data</Tab>
280           )
281         } else if (this.props.type == 'vnfr') {
282           tabList.push(
283             <Tab key={cardData.id}>VNF Data</Tab>
284           )
285         }
286
287         tabPanels.push(
288           <TabPanel key={cardData.id + '-panel'}>
289
290               <div className="launchpadCard_title" style={{textAlign:'right'}}><span style={{float:'left'}}>MONITORING PARAMETERS</span>
291                 {mgmtHTML}
292               </div>
293               {metricsAndParams}
294               <div className="cardSectionFooter">
295               </div>
296           </TabPanel>
297         )
298
299
300         if (this.props.type == 'nsr') {
301           if (scalingGroupComponent) {
302             tabList.push(
303             <Tab key={cardData.id + '-sg'}>Scaling Groups</Tab>
304           );
305
306           tabPanels.push(
307               <TabPanel key={cardData.id + '-sg-panel'}>
308                   <div>
309                     {scalingGroupComponent}
310                   </div>
311                   <div className="cardSectionFooter">
312                   </div>
313               </TabPanel>
314             );
315           }
316           if(cardData.hasOwnProperty('vnfd-placement-group-maps')
317              || cardData.hasOwnProperty('nsd-placement-group-maps')) {
318             tabList.push(
319                <Tab key='placement_groups'>
320                 Placement
321                </Tab>
322              );
323             tabPanels.push(
324                <TabPanel key='placement_groups_panel'>
325                   <div>
326                     <PlacementGroupsInfo nsr={cardData} navRef={this.props.navRef} />
327                   </div>
328               </TabPanel>
329              );
330           }
331         }
332
333         if (configPrimitiveComponent) {
334           let primitivesTabTitle = '';
335           if (this.props.type == 'nsr') {
336             primitivesTabTitle = 'Service Primitive';
337           } else if (this.props.type == 'vnfr') {
338             primitivesTabTitle = 'Service Primitive'
339           }
340
341           tabList.push(
342             <Tab key={cardData.id + '-cp'}>{primitivesTabTitle}</Tab>
343           );
344
345           tabPanels.push(
346             <TabPanel key={cardData.id + '-cp-panel'}>
347               <div className="configPrimitives">
348                 {configPrimitiveComponent}
349               </div>
350               <div className="cardSectionFooter">
351               </div>
352             </TabPanel>
353           )
354         }
355
356         if (nsVirtualLinksComponent) {
357           let nsVirtualLinksTabTitle = 'Virtual Links';
358           tabList.push(
359               <Tab key={cardData.id + '-nsvl'}>{nsVirtualLinksTabTitle}</Tab>
360           );
361
362           tabPanels.push(
363             <TabPanel key={cardData.id + '-nsvl-panel'}>
364               <div className='nsVirtualLinks'>
365                 {nsVirtualLinksComponent}
366               </div>
367               <div className="cardSectionFooter">
368               </div>
369             </TabPanel>
370           );
371         }
372
373         if (consoleUrlsComponent) {
374           let consoleUrlsTabTitle = '';
375           consoleUrlsTabTitle = 'VDU Console Links';
376
377           tabList.push(
378             <Tab key={cardData.id + '-cp'}>{consoleUrlsTabTitle}</Tab>
379           );
380
381           tabPanels.push(
382             <TabPanel key={cardData.id + '-cp-panel'}>
383               <div className="consoleUrls">
384                 {consoleUrlsComponent}
385               </div>
386               <div className="cardSectionFooter">
387               </div>
388             </TabPanel>
389           )
390         }
391
392         if (displayVolumesTab) {
393
394           tabList.push(
395             <Tab key={cardData.id + '-volumes'}>Volumes</Tab>
396           );
397
398           tabPanels.push(
399             <TabPanel key={cardData.id + '-volumes-panel'}>
400               {volumesHTML}
401               <div className="cardSectionFooter">
402               </div>
403             </TabPanel>
404           )
405         }
406
407         html = (
408             <DashboardCard className="recordCard" showHeader={true} title={cardData["short-name"]}>
409               <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>
410               <Tabs onSelect={this.handleSelect}>
411                 <TabList>
412                     {tabList}
413                 </TabList>
414                 {tabPanels}
415               </Tabs>
416             </DashboardCard>
417         );
418       }
419     return html;
420   }
421 }
422 RecordCard.defaultProps = {
423   type: "default",
424   data: {},
425   isLoading: true,
426   jobData: []
427 }
428 RecordCard.contextTypes = {
429     router: React.PropTypes.object,
430     userProfile: React.PropTypes.object
431 };