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