aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace
diff options
context:
space:
mode:
authorMurali-P <murali.p@huawei.com>2018-03-29 17:46:39 +0530
committerVitaly Emporopulo <Vitaliy.Emporopulo@amdocs.com>2018-04-30 13:51:11 +0000
commit72d62fb1aaaaeaed462083e232f3571b3bde6b08 (patch)
tree0691b2378b76270b7b7dbd8e32aff2afe895042f /openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace
parentdb69b87869091b774d6d87f3b6a9155d34d26b12 (diff)
Integrate VNF Repository in Beijing release
Migrate the code Change-Id: Ifccacf83634af32b034fd9c413e68f894f06d2f7 Issue-ID: VNFSDK-155 Signed-off-by: Murali-P <murali.p@huawei.com>
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImport.js41
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportActionHelper.js180
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportConstants.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportReducer.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/vnfMarketPlace/VNFImportView.jsx309
5 files changed, 582 insertions, 0 deletions
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 <span>{action}</span>;
+ }
+ return (
+ <span>
+ <SVGIcon
+ name="download"
+ color="positive"
+ onClick={() => {
+ downloadCSAR(id, currSoftwareProduct);
+ }}
+ />
+ </span>
+ );
+}
+
+function VNFSortableCellHeader({
+ isHeader,
+ data,
+ isDes,
+ onSort,
+ activeSortColumn
+}) {
+ //TODO check icon sdc-ui
+ if (isHeader) {
+ if (activeSortColumn === data) {
+ return (
+ <span
+ className="vnf-table-header"
+ onClick={() => {
+ onSort(activeSortColumn);
+ }}>
+ <span>{data}</span>
+ <span
+ className={`header-sort-arrow ${isDes ? 'up' : 'down'}`}
+ />
+ </span>
+ );
+ } else {
+ return (
+ <span
+ className="vnf-table-header"
+ onClick={() => {
+ activeSortColumn = data;
+ onSort(activeSortColumn);
+ }}>
+ <span>{data}</span>
+ </span>
+ );
+ }
+ }
+ return (
+ <span className="vnf-table-cell">
+ <span>{data}</span>
+ </span>
+ );
+}
+
+export function VNFItemList({
+ vnf,
+ isHeader,
+ isDes,
+ onSort,
+ activeSortColumn,
+ downloadCSAR,
+ selectTableRow,
+ selectedRow,
+ currentSoftwareProduct
+}) {
+ let { csarId, name, version, provider, shortDesc, action } = vnf;
+ return (
+ <li
+ className={`vnfBrowse-list-item ${isHeader ? 'header' : ''} ${
+ csarId === selectedRow ? 'selectedRow' : ''
+ }`}
+ data-test-id="vnfBrowse-list-item"
+ onClick={() => {
+ selectTableRow(csarId);
+ }}>
+ <div
+ className="table-cell vnftable-name"
+ data-test-id="vnftable-name">
+ <VNFSortableCellHeader
+ isHeader={isHeader}
+ data={name}
+ isDes={isDes}
+ onSort={activeSort => {
+ onSort('name', activeSort);
+ }}
+ activeSortColumn={activeSortColumn}
+ />
+ </div>
+ <div
+ className="table-cell vnftable-version"
+ data-test-id="vnftable-version">
+ <VNFSortableCellHeader
+ isHeader={isHeader}
+ data={version}
+ isDes={isDes}
+ onSort={activeSort => {
+ onSort('version', activeSort);
+ }}
+ activeSortColumn={activeSortColumn}
+ />
+ </div>
+ <div
+ className="table-cell vnftable-provider"
+ data-test-id="vnftable-provider">
+ <VNFSortableCellHeader
+ isHeader={isHeader}
+ data={provider}
+ isDes={isDes}
+ onSort={activeSort => {
+ onSort('provider', activeSort);
+ }}
+ activeSortColumn={activeSortColumn}
+ />
+ </div>
+ <div
+ className="table-cell vnftable-shortDesc"
+ data-test-id="vnftable-shortDesc">
+ <VNFSortableCellHeader
+ isHeader={isHeader}
+ data={shortDesc}
+ isDes={isDes}
+ onSort={activeSort => {
+ onSort('shortDesc', activeSort);
+ }}
+ activeSortColumn={activeSortColumn}
+ />
+ </div>
+ <div
+ className="table-cell vnftable-action"
+ data-test-id="vnftable-action">
+ <VNFAction
+ isHeader={isHeader}
+ action={action}
+ downloadCSAR={downloadCSAR}
+ id={csarId}
+ currSoftwareProduct={currentSoftwareProduct}
+ />
+ </div>
+ </li>
+ );
+}
+
+class VNFImportView extends React.Component {
+ state = {
+ localFilter: '',
+ sortDescending: true,
+ sortCrit: 'name',
+ activeSortColumn: 'Name',
+ selectedRow: ''
+ };
+
+ render() {
+ let { onCancel, onSubmit, currentSoftwareProduct } = this.props;
+
+ return (
+ <div className="vnf-creation-page">
+ <GridSection className="vnf-grid-section">
+ <GridItem colSpan="4">
+ <ListEditorView
+ title={i18n('VNF List Title')}
+ filterValue={this.state.localFilter}
+ onFilter={filter =>
+ this.setState({ localFilter: filter })
+ }>
+ <VNFItemList
+ isHeader={true}
+ vnf={{
+ csarId: 0,
+ name: i18n('VNF Header Name'),
+ version: i18n('VNF Header Version'),
+ provider: i18n('VNF Header Vendor'),
+ shortDesc: i18n('VNF Header Desc'),
+ action: i18n('VNF Header Action')
+ }}
+ isDes={this.state.sortDescending}
+ onSort={(sortCriteria, activeSortCol) =>
+ 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 => (
+ <VNFItemList
+ key={vnf.id}
+ vnf={vnf}
+ downloadCSAR={this.downloadCSAR}
+ selectTableRow={selID => {
+ this.setState({ selectedRow: selID });
+ this.selectTableRow(selID);
+ }}
+ selectedRow={this.state.selectedRow}
+ currentSoftwareProduct={
+ currentSoftwareProduct
+ }
+ />
+ ))}
+ </ListEditorView>
+ </GridItem>
+ <GridItem colSpan="4">
+ <div className="vnf-modal">
+ <Button
+ className="vnf-submit"
+ type="button"
+ btnType="default"
+ onClick={() =>
+ onSubmit(
+ this.state.selectedRow,
+ currentSoftwareProduct
+ )
+ }>
+ {i18n('OK')}
+ </Button>
+ <Button
+ className="Cancel"
+ type="button"
+ btnType="outline"
+ onClick={onCancel}>
+ {i18n('Cancel')}
+ </Button>
+ </div>
+ </GridItem>
+ </GridSection>
+ </div>
+ );
+ }
+
+ 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;