}, [arr[0]]);
}
+Utils.cleanImageDataURI = (imageString, type, id) => {
+ if (/\bbase64\b/g.test(imageString)) {
+ return imageString;
+ } else if (/<\?xml\b/g.test(imageString)) {
+ const imgStr = imageString.substring(imageString.indexOf('<?xml'));
+ return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(imgStr);
+ } else if (/\.(svg|png|gif|jpeg|jpg)$/.test(imageString)) {
+ return '/composer/assets/logos/' + type + '/' + id + '/' + imageString;
+ // return require('../images/logos/' + imageString);
+ }
+ if(type == 'nsd' || type == 'vnfd') {
+ return require('style/img/catalog-'+type+'-default.svg');
+ }
+ return require('style/img/catalog-default.svg');
+}
+
module.exports = Utils;
}
utils.assignPathValue(stateObject, [selected].join('.'), _.cloneDeep(choiceObject));
- if(this.model.uiState.choice.hasOwnProperty(name)) {
- delete this.model[selected];
- utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
- } else {
- // remove the current choice value from the model
- utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
+ if(selected) {
+ if(this.model.uiState.choice.hasOwnProperty(name)) {
+ delete this.model[selected];
+ utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
+ } else {
+ // remove the current choice value from the model
+ utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
+ }
}
-
-
// get any state for the new selected choice
const newChoiceObject = utils.resolvePath(stateObject, [value].join('.')) || {};
return {optionName: d.name};
});
- const options = [{optionName: ''}].concat(cases).map((d, i) => {
+ const options = [{optionName: '', optionValue: false}].concat(cases).map((d, i) => {
return (
<option key={i} value={d.optionValue} title={d.optionTitle}>
{d.optionName}
if(fieldProperties) {
//Check each case statement in model and see if it is present in container model.
cases.map(function(c){
- if(fieldProperties.hasOwnProperty(c.optionName)) {
+ if(fieldProperties.hasOwnProperty(c.optionValue.split('.')[1])) {
utils.assignPathValue(container.model, ['uiState.choice', selectName, 'selected'].join('.'), c.optionValue);
}
});
return DescriptorModelSerializer.serialize(d);
});
- return confd;
+ return cleanEmptyTopKeys(confd);
}
},
}
// fix-end
confd[property] = confd[property].map(d => DescriptorModelSerializer[property].serialize(d));
- return confd;
+ return cleanEmptyTopKeys(confd);
}
},
'vnfd-connection-point-ref': {
if(!vnfdFields) vnfdFields = DescriptorModelMetaFactory.getModelFieldNamesForType('vnfd').concat('uiState');
const confd = _.pick(vnfdModel, vnfdFields);
confd.vdu = confd.vdu.map(d => DescriptorModelSerializer.serialize(d));
- return confd;
+ return cleanEmptyTopKeys(confd);
}
},
vdu: {
checkForChoiceAndRemove(k, copy, vduModel)
}
const confd = _.omit(copy, ['uiState']);
- return confd;
+ return cleanEmptyTopKeys(confd);
}
}
};
function checkForChoiceAndRemove(k, confd, model) {
- let state = model.uiState;
- if (state.choice) {
- let choice = state.choice[k]
- if(choice) {
- for (let key in confd[k]) {
- if(choice && (choice.selected.indexOf(key) > -1)) {
- confd[key] = confd[k][key]
- }
- };
- delete confd[k];
- }
- }
- return confd;
+ let state = model.uiState;
+ if (state.choice) {
+ let choice = state.choice[k]
+ if(choice) {
+ if (choice.constructor.name == "Array") {
+ for(let i = 0; i < choice.length; i++) {
+ for (let key in confd[k][i]) {
+ if(choice[i] && (choice[i].selected.indexOf(key) > -1)) {
+ confd[k][i][key] = confd[k][i][key]
+ }
+ confd[key];
+ };
+ }
+ } else {
+ for (let key in confd[k]) {
+ if(choice && (choice.selected.indexOf(key) > -1)) {
+ confd[key] = confd[k][key]
+ }
+ };
+ delete confd[k];
+ }
+
+ }
+ }
+ return confd;
+}
+
+function cleanEmptyTopKeys(m){
+ Object.keys(m).forEach(k => {
+ const isEmptyObject = typeof m[k] === 'object' && _.isEmpty(m[k]);
+ if (typeof m[k] === 'undefined' || isEmptyObject || m[k] === '') {
+ delete m[k];
+ }
+ });
+ return m;
}
export default DescriptorModelSerializer;
import './catalogCard.scss';
import 'style/common.scss';
import React, {Component} from 'react';
+import Utils from 'utils/utils.js'
export default class CatalogCard extends Component {
constructor(props) {
super(props);
<div key={i} className="details-section-item">
<img
onError={self.handleImageError}
- src={cleanDataURI(descriptor.logo, 'vnfd', descriptor.id)}
+ src={Utils.cleanImageDataURI(descriptor.logo, 'vnfd', descriptor.id)}
/>
{v['name']}
</div>
className = "CatalogCard " + buildClass(this.props);
return (
<div className={className} onClick={props.onClick} onDoubleClick={props.onDoubleClick}>
- <img className="CatalogCard-thumbnail" onError={this.handleImageError} src={cleanDataURI(descriptor.logo, 'nsd', descriptor.id)} />
+ <img className="CatalogCard-thumbnail" onError={this.handleImageError} src={Utils.cleanImageDataURI(descriptor.logo, 'nsd', descriptor.id)} />
<div className="CatalogCard-body">
<div className="CatalogCard-header">
<div className="CatalogCard-name">
''
}
}
-
-function cleanDataURI(imageString, type, id) {
- if (/\bbase64\b/g.test(imageString)) {
- return imageString;
- } else if (/<\?xml\b/g.test(imageString)) {
- const imgStr = imageString.substring(imageString.indexOf('<?xml'));
- return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(imgStr);
- } else if (/\.(svg|png|gif|jpeg|jpg)$/.test(imageString)) {
- return '/composer/assets/logos/' + type + '/' + id + '/' + imageString;
- // return require('../images/logos/' + imageString);
- }
- if(type == 'nsd' || type == 'vnfd') {
- return require('style/img/catalog-'+type+'-default.svg');
- }
- return require('style/img/catalog-default.svg');
- }
-ms-flex-flow: col wrap;
flex-flow: col wrap;
}
+
+ .nsrSummary {
+ font-size: 50%;
+ padding-top: 1rem;
+ .nsrSummaryItem {
+ padding-right: 0.5rem;
+ }
+ }
}
.nsListPanelToggle {
const {nsrs, openedNsrIDs, emptyRows, isVisible, ...props} = this.props;
const fieldKeys = FIELD_KEYS;
let glyphValue = (isVisible) ? "chevron-left" : "chevron-right";
+
+ let totalNSRs = nsrs && nsrs.length;
+ let runningNSRs = 0;
+ let failedNSRs = 0;
+ let scalingOutNSRs = 0;
+ let scalingInNSRs = 0;
+ let initializingNSRs = 0;
+
+ nsrs && nsrs.map((nsr) => {
+ nsr['operational-status'] == 'running' && runningNSRs++;
+ nsr['operational-status'] == 'failed' && failedNSRs++;
+ nsr['operational-status'] == 'scaling-out' && scalingOutNSRs++;
+ nsr['operational-status'] == 'scaling-in' && scalingInNSRs++;
+ (
+ nsr['operational-status'] == 'init' ||
+ nsr['operational-status'] == 'vl-init-phase' ||
+ nsr['operational-status'] == 'vnf-init-phase'
+ ) && initializingNSRs++;
+ });
+
+
if (isVisible) {
+
+ let title = (
+ <div>
+ NETWORK SERVICES
+ <div className='nsrSummary'>
+ <span className='nsrSummaryItem'>Total: {totalNSRs}</span>
+ <span className='nsrSummaryItem'>Running: {runningNSRs}</span>
+ <span className='nsrSummaryItem'>Failed: {failedNSRs}</span>
+ <span className='nsrSummaryItem'>Scaling Out: {scalingOutNSRs}</span>
+ <span className='nsrSummaryItem'>Scaling In: {scalingInNSRs}</span>
+ <span className='nsrSummaryItem'>Initializing: {initializingNSRs}</span>
+ </div>
+ </div>
+ );
+
+
return (
<DashboardCard className="nsListPanel" showHeader={true}
- title="NETWORK SERVICES">
+ title={title}>
{this.panelToolbar()}
<a onClick={this.handleShowHideToggle(!isVisible)}
className={"nsListPanelToggle"}>
import RecordViewActions from './recordViewActions.js';
import LoadingIndicator from 'widgets/loading-indicator/loadingIndicator.jsx';
import DashboardCard from 'widgets/dashboard_card/dashboard_card.jsx';
+import Utils from 'utils/utils.js';
+
import './recordNavigator.scss';
-import nsdImg from 'style/img/catalog-default.svg';
export default class RecordNavigator extends React.Component{
constructor(props) {
super(props)
}
+ handleImageError = (e) => {
+ console.log('Bad logo path, using default');
+ e.target.src = require('style/img/catalog-default.svg');
+ }
+
+ getDescriptorTypeFromRecordType = (recordType) => {
+ if (recordType == 'nsr') {
+ return 'nsd';
+ } else if (recordType == 'vnfr') {
+ return 'vnfd';
+ }
+
+ return null;
+ }
+
render(){
let navClass = 'catalogItems';
}
navObj.push(
<div key={'id' + k + '-' + vnfr.id} onClick={self.props.loadRecord.bind(self,vnfr)} className={iClassName}>
- <img src={nsdImg} />
+ <img
+ onError={self.handleImageError}
+ src={Utils.cleanImageDataURI(vnfr.logo, self.getDescriptorTypeFromRecordType(vnfr.type), vnfr.logoId)}
+ />
<section id={vnfr.id}>
<h1 title={vnfr.name}>{vnfr.name}</h1>
<h2>{vnfr.type}</h2>
}
navObj.push(
<div key={'id' + k + '-' + n.id} onClick={self.props.loadRecord.bind(self,n)} className={itemClassName}>
- <img src={nsdImg} />
+ <img
+ onError={self.handleImageError}
+ src={Utils.cleanImageDataURI(n.logo, self.getDescriptorTypeFromRecordType(n.type), n.logoId)}
+ />
<section id={n.id}>
<h1 title={n.name}>{n.name}</h1>
<h2>{n.type}</h2>
name: nsrs.name,
id: nsrs.id,
nsd_name: nsrs.nsd_name,
- type: 'nsr'
+ type: 'nsr',
+ logo: nsrs.nsd && nsrs.nsd.logo,
+ logoId: nsrs.nsd && nsrs.nsd && nsrs.nsd.id
});
// Scaled VNFRs
sgInstance['vnfrs'] && sgInstance['vnfrs'].map((vnfr, vnfrIndex) => {
scaledVnfrs.push(vnfr);
+ let vnfrObj = _.findWhere(nsrs.vnfrs, {id: vnfr});
scaledVnfNav.vnfr.push({
- name: _.findWhere(nsrs.vnfrs, {id: vnfr})['short-name'],
+ name: vnfrObj['short-name'],
id: vnfr,
- type: 'vnfr'
+ type: 'vnfr',
+ logo: vnfrObj['vnfd'] && vnfrObj['vnfd']['logo'],
+ logoId: vnfrObj['vnfd'] && vnfrObj['vnfd']['id']
});
});
nav.push(scaledVnfNav);
nav.push({
name: vnfr["short-name"],
id: vnfr.id,
- type: 'vnfr'
+ type: 'vnfr',
+ logo: vnfr['vnfd'] && vnfr['vnfd']['logo'],
+ logoId: vnfr['vnfd'] && vnfr['vnfd']['id']
});
}
});