From 72d62fb1aaaaeaed462083e232f3571b3bde6b08 Mon Sep 17 00:00:00 2001 From: Murali-P Date: Thu, 29 Mar 2018 17:46:39 +0530 Subject: Integrate VNF Repository in Beijing release Migrate the code Change-Id: Ifccacf83634af32b034fd9c413e68f894f06d2f7 Issue-ID: VNFSDK-155 Signed-off-by: Murali-P --- .../softwareProduct/vnfMarketPlace/VNFImport.js | 41 +++ .../vnfMarketPlace/VNFImportActionHelper.js | 180 ++++++++++++ .../vnfMarketPlace/VNFImportConstants.js | 21 ++ .../vnfMarketPlace/VNFImportReducer.js | 31 +++ .../vnfMarketPlace/VNFImportView.jsx | 309 +++++++++++++++++++++ 5 files changed, 582 insertions(+) create mode 100644 openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImport.js create mode 100644 openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportActionHelper.js create mode 100644 openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportConstants.js create mode 100644 openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportReducer.js create mode 100644 openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportView.jsx (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace') diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImport.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImport.js new file mode 100644 index 0000000000..19efab68c8 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImport.js @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { connect } from 'react-redux'; +import VNFImportView from './VNFImportView.jsx'; +import VNFImportActionHelper from './VNFImportActionHelper.js'; + +export const mapStateToProps = response => { + const { + softwareProduct: { VNFMarketPlaceImport: { vnfItems } } + } = response; + return { + vnfItems: vnfItems + }; +}; + +export const mapActionsToProps = dispatch => { + return { + onCancel: () => VNFImportActionHelper.resetData(dispatch), + onSubmit: (csarId, selectedVendor) => { + VNFImportActionHelper.uploadData(selectedVendor, csarId, dispatch); + } + }; +}; + +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(VNFImportView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportActionHelper.js new file mode 100644 index 0000000000..3843330449 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportActionHelper.js @@ -0,0 +1,180 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; +import Configuration from 'sdc-app/config/Configuration.js'; +import { + actionTypes as modalActionTypes, + modalSizes +} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; +import { actionTypes } from './VNFImportConstants.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +function baseUrl(selectedVendor) { + const restPrefix = Configuration.get('restPrefix'); + let vspId = selectedVendor.id; + let version = selectedVendor.version; + return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${ + version.id + }/vnfrepository`; +} + +function getVNFMarketplace(dispatch, currentSoftwareProduct) { + return RestAPIUtil.fetch(`${baseUrl(currentSoftwareProduct)}/vnfpackages`, { + isAnonymous: false + }) + .then(response => { + dispatch({ + type: actionTypes.OPEN, + response + }); + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.VNF_IMPORT, + title: i18n('Browse VNF'), + modalComponentProps: { + currentSoftwareProduct, + size: modalSizes.LARGE + } + } + }); + }) + .catch(error => { + let errMessage = error.responseJSON + ? error.responseJSON.message + : i18n('VNF import failed msg'); + + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('VNF import failed title'), + msg: errMessage, + cancelButtonText: i18n('Ok') + } + }); + }); +} + +function downloadCSARFile(csarId, currSoftwareProduct) { + let url = `${baseUrl(currSoftwareProduct)}/vnfpackage/${csarId}/download`; + return RestAPIUtil.fetch(url, { + dataType: 'binary', + isAnonymous: false + }); +} + +function getFileName(xhr, defaultFilename) { + let filename = ''; + let contentDisposition = + xhr && xhr.getResponseHeader('Content-Disposition') + ? xhr.getResponseHeader('Content-Disposition') + : ''; + let match = contentDisposition.match(/filename=(.*?)(;|$)/); + if (match) { + filename = match[1].replace(/['"]/g, ''); + } else { + filename = defaultFilename; + } + return filename; +} + +function uploadVNFData(csarId, currSoftwareProduct, dispatch) { + let softwareProductId = currSoftwareProduct.id; + let version = { id: currSoftwareProduct.version }; + + SoftwareProductActionHelper.uploadVNFFile(dispatch, { + csarId, + currSoftwareProduct, + failedNotificationTitle: i18n('Upload validation failed'), + softwareProductId, + version + }); +} + +function getTimestampString() { + let date = new Date(); + let z = n => (n < 10 ? '0' + n : n); + return `${date.getFullYear()}-${z(date.getMonth())}-${z( + date.getDate() + )}_${z(date.getHours())}-${z(date.getMinutes())}`; +} + +function showFileSaveDialog({ blob, xhr, defaultFilename, addTimestamp }) { + let filename = getFileName(xhr, defaultFilename); + + if (addTimestamp) { + filename = filename.replace( + /(^.*?)\.([^.]+$)/, + `$1_${getTimestampString()}.$2` + ); + } + + let link = document.createElement('a'); + + let url = URL.createObjectURL(blob.blob); + + link.href = url; + link.download = filename; + link.style.display = 'none'; + document.body.appendChild(link); + link.click(); + setTimeout(function() { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 0); +} + +const VNFImportActionHelper = { + open(dispatch, currentSoftwareProduct) { + getVNFMarketplace(dispatch, currentSoftwareProduct); + }, + + download(csarId, currSoftwareProduct) { + downloadCSARFile(csarId, currSoftwareProduct).then( + (blob, statusText, xhr) => + showFileSaveDialog({ + blob, + xhr, + defaultFilename: 'MyNewCSAR.csar', + addTimestamp: true + }) + ); + }, + + resetData(dispatch) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }); + + dispatch({ + type: actionTypes.RESET_DATA + }); + }, + + getVNFMarketplace(dispatch) { + return getVNFMarketplace(dispatch); + }, + + uploadData(currSoftwareProduct, csarId, dispatch) { + this.resetData(dispatch); + uploadVNFData(csarId, currSoftwareProduct, dispatch); + } +}; + +export default VNFImportActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportConstants.js new file mode 100644 index 0000000000..e4540dda3b --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportConstants.js @@ -0,0 +1,21 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import keyMirror from 'nfvo-utils/KeyMirror.js'; + +export const actionTypes = keyMirror({ + OPEN: null, + RESET_DATA: null +}); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportReducer.js new file mode 100644 index 0000000000..0f2638f7ed --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportReducer.js @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { actionTypes } from './VNFImportConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case actionTypes.OPEN: + return { + ...state, + showModal: true, + vnfItems: action.response + }; + case actionTypes.RESET_DATA: + return {}; + default: + return state; + } +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportView.jsx new file mode 100644 index 0000000000..3a90c8042f --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportView.jsx @@ -0,0 +1,309 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; +import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; +import Button from 'sdc-ui/lib/react/Button.js'; +import VNFImportActionHelper from '../vnfMarketPlace/VNFImportActionHelper.js'; + +function VNFAction({ + action, + isHeader, + downloadCSAR, + id, + currSoftwareProduct +}) { + if (isHeader) { + return {action}; + } + return ( + + { + downloadCSAR(id, currSoftwareProduct); + }} + /> + + ); +} + +function VNFSortableCellHeader({ + isHeader, + data, + isDes, + onSort, + activeSortColumn +}) { + //TODO check icon sdc-ui + if (isHeader) { + if (activeSortColumn === data) { + return ( + { + onSort(activeSortColumn); + }}> + {data} + + + ); + } else { + return ( + { + activeSortColumn = data; + onSort(activeSortColumn); + }}> + {data} + + ); + } + } + return ( + + {data} + + ); +} + +export function VNFItemList({ + vnf, + isHeader, + isDes, + onSort, + activeSortColumn, + downloadCSAR, + selectTableRow, + selectedRow, + currentSoftwareProduct +}) { + let { csarId, name, version, provider, shortDesc, action } = vnf; + return ( +
  • { + selectTableRow(csarId); + }}> +
    + { + onSort('name', activeSort); + }} + activeSortColumn={activeSortColumn} + /> +
    +
    + { + onSort('version', activeSort); + }} + activeSortColumn={activeSortColumn} + /> +
    +
    + { + onSort('provider', activeSort); + }} + activeSortColumn={activeSortColumn} + /> +
    +
    + { + onSort('shortDesc', activeSort); + }} + activeSortColumn={activeSortColumn} + /> +
    +
    + +
    +
  • + ); +} + +class VNFImportView extends React.Component { + state = { + localFilter: '', + sortDescending: true, + sortCrit: 'name', + activeSortColumn: 'Name', + selectedRow: '' + }; + + render() { + let { onCancel, onSubmit, currentSoftwareProduct } = this.props; + + return ( +
    + + + + this.setState({ localFilter: filter }) + }> + + this.setState({ + sortDescending: !this.state + .sortDescending, + sortCrit: sortCriteria, + activeSortColumn: activeSortCol + }) + } + activeSortColumn={this.state.activeSortColumn} + /> + {this.sortVNFItems( + this.filterVNFItems(), + this.state.sortDescending, + this.state.sortCrit + ).map(vnf => ( + { + this.setState({ selectedRow: selID }); + this.selectTableRow(selID); + }} + selectedRow={this.state.selectedRow} + currentSoftwareProduct={ + currentSoftwareProduct + } + /> + ))} + + + +
    + + +
    +
    +
    +
    + ); + } + + filterVNFItems() { + let { vnfItems } = this.props; + let { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return vnfItems.filter( + ({ name = '', provider = '', version = '', shortDesc = '' }) => + escape(name).match(filter) || + escape(provider).match(filter) || + escape(version).match(filter) || + escape(shortDesc).match(filter) + ); + } else { + return vnfItems; + } + } + + sortVNFItems(vnfItems, sortDesc, sortCrit) { + if (sortDesc) { + return vnfItems.sort((a, b) => { + if (a[sortCrit] < b[sortCrit]) { + return -1; + } else if (a[sortCrit] > b[sortCrit]) { + return 1; + } else { + return 0; + } + }); + } else { + return vnfItems.reverse(); + } + } + + downloadCSAR(id, currSoftwareProduct) { + VNFImportActionHelper.download(id, currSoftwareProduct); + } +} + +export default VNFImportView; -- cgit 1.2.3-korg