aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies
diff options
context:
space:
mode:
authorAviZi <avi.ziv@amdocs.com>2017-06-09 02:39:56 +0300
committerAviZi <avi.ziv@amdocs.com>2017-06-09 02:39:56 +0300
commit280f8015d06af1f41a3ef12e8300801c7a5e0d54 (patch)
tree9c1d3978c04cd28068f02073038c936bb49ca9e0 /openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies
parentfd3821dad11780d33c5373d74c957c442489945e (diff)
[SDC-29] Amdocs OnBoard 1707 initial commit.
Change-Id: Ie4d12a3f574008b792899b368a0902a8b46b5370 Signed-off-by: AviZi <avi.ziv@amdocs.com>
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js40
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js58
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js29
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js64
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx98
6 files changed, 325 insertions, 0 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js
new file mode 100644
index 0000000000..9540d3f869
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js
@@ -0,0 +1,40 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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 SoftwareProductDependenciesView from './SoftwareProductDependenciesView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import SoftwareProductDependenciesActionHelper from './SoftwareProductDependenciesActionHelper.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+ let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductDependencies, softwareProductComponents: {componentsList}} = softwareProduct;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ return {
+ isReadOnlyMode,
+ softwareProductDependencies: softwareProductDependencies.length ? softwareProductDependencies : [{sourceId: '', targetId: '', relationType: 'dependsOn', id: 'fake'}],
+ componentsOptions: componentsList.map(component => ({value: component.id, label: component.name}))
+ };
+};
+
+const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
+ return {
+ onDataChanged: dependenciesList => SoftwareProductDependenciesActionHelper.updateDependencyList(dispatch, {dependenciesList}),
+ onAddDependency: () => SoftwareProductDependenciesActionHelper.addDependency(dispatch),
+ onSubmit: (dependenciesList) => SoftwareProductDependenciesActionHelper.saveDependencies(dispatch, {softwareProductId, version, dependenciesList})
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDependenciesView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js
new file mode 100644
index 0000000000..e47b33a577
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js
@@ -0,0 +1,58 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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} from './SoftwareProductDependenciesConstants.js';
+import uuid from 'uuid-js';
+
+function baseUrl(softwareProductId, version) {
+ const versionId = version.id;
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependency-model`;
+}
+
+function fetchDependency(softwareProductId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+}
+
+function postDependency(softwareProductId, version, dependenciesList) {
+ let modifedDependencyList = dependenciesList ? dependenciesList.filter(item => item.sourceId && item.targetId)
+ .map(item => ({sourceId: item.sourceId, targetId: item.targetId, relationType: item.relationType})) : [];
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {componentDependencyModels:modifedDependencyList});
+}
+
+const SoftwareProductDependenciesActionHelper = {
+ updateDependencyList(dispatch, {dependenciesList}) {
+ dispatch({type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, dependenciesList});
+ },
+ addDependency(dispatch) {
+ dispatch({type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY});
+ },
+ fetchDependencies(dispatch, {softwareProductId, version}) {
+ return fetchDependency(softwareProductId, version).then( response => {
+ const dependenciesList = response.results ? response.results.map(item => {return {...item, id: uuid.create().toString()};}) : [];
+ dispatch({
+ type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE,
+ dependenciesList
+ });
+ });
+ },
+ saveDependencies(dispatch, {softwareProductId, version, dependenciesList}) {
+ return postDependency(softwareProductId, version, dependenciesList);
+ }
+};
+
+export default SoftwareProductDependenciesActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js
new file mode 100644
index 0000000000..1f27ed8311
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js
@@ -0,0 +1,29 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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({
+ SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null,
+ ADD_SOFTWARE_PRODUCT_DEPENDENCY: null
+});
+
+export const relationTypes = {
+ DEPENDS_ON: 'dependsOn'
+};
+
+export const relationTypesOptions = [
+ {value: relationTypes.DEPENDS_ON, label: 'Depends On'}
+];
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js
new file mode 100644
index 0000000000..3fb479eedc
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js
@@ -0,0 +1,36 @@
+
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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, relationTypes} from './SoftwareProductDependenciesConstants.js';
+import {checkCyclesAndMarkDependencies} from './SoftwareProductDependenciesUtils.js';
+import uuid from 'uuid-js';
+
+export default (state = [], action) => {
+ switch (action.type) {
+ case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE:
+ return checkCyclesAndMarkDependencies(action.dependenciesList);
+ case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY:
+ return [...state, {
+ sourceId: null,
+ relationType: relationTypes.DEPENDS_ON,
+ targetId: null,
+ id: uuid.create()
+ }];
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js
new file mode 100644
index 0000000000..94d21bd49d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js
@@ -0,0 +1,64 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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 DirectedGraph from 'nfvo-utils/DirectedGraph.js';
+
+function findCycles(graph, node, id, visited = {}, visitedConnections = {}, recursionStack = {}, connectionsWithCycle = {}) {
+ visited[node] = true;
+ recursionStack[node] = true;
+ if (id) {
+ visitedConnections[id] = true;
+ }
+ for (let edge of graph.getEdges(node)) {
+ if (!visited[edge.target]) {
+ findCycles(graph, edge.target, edge.id, visited, visitedConnections, recursionStack, connectionsWithCycle);
+ } else if (recursionStack[edge.target]) {
+ visitedConnections[edge.id] = true;
+ for (let connection in visitedConnections) {
+ connectionsWithCycle[connection] = true;
+ }
+ }
+ }
+ recursionStack[node] = false;
+ return {visitedNodes: visited, connectionsWithCycle: connectionsWithCycle};
+}
+
+export function checkCyclesAndMarkDependencies(dependenciesList) {
+ let overallVisitedNodes = {};
+ let overallConnectionsWithCycles = {};
+
+ let g = new DirectedGraph();
+ for (let dependency of dependenciesList) {
+ if (dependency.sourceId !== null && dependency.targetId !== null) {
+ g.addEdge(dependency.sourceId, dependency.targetId, {id: dependency.id});
+ }
+ }
+
+ for (let node in g.nodes) {
+ if (!overallVisitedNodes.node) {
+ let {visitedNodes, connectionsWithCycle} = findCycles(g, node, undefined);
+ overallVisitedNodes = {...overallVisitedNodes, ...visitedNodes};
+ overallConnectionsWithCycles = {...overallConnectionsWithCycles, ...connectionsWithCycle};
+ }
+ }
+ return dependenciesList.map(dependency => (
+ {
+ ...dependency,
+ hasCycle: dependency.sourceId && dependency.targetId ?
+ overallConnectionsWithCycles.hasOwnProperty(dependency.id)
+ : undefined
+ }));
+}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
new file mode 100644
index 0000000000..da975a7be2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
@@ -0,0 +1,98 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * 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 i18n from 'nfvo-utils/i18n/i18n.js';
+
+import SelectActionTable from 'nfvo-components/table/SelectActionTable.jsx';
+import SelectActionTableRow from 'nfvo-components/table/SelectActionTableRow.jsx';
+import SelectActionTableCell from 'nfvo-components/table/SelectActionTableCell.jsx';
+import {relationTypesOptions} from './SoftwareProductDependenciesConstants.js';
+
+export default class SoftwareProductDependenciesView extends React.Component {
+ filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) {
+ let isInMap = sourceToTargetMapping.hasOwnProperty(selectedSourceId);
+ return componentsOptions.filter(component => {
+ if (component.value === selectedTargetId) {
+ return true;
+ } else {
+ return component.value !== selectedSourceId && (isInMap ? sourceToTargetMapping[selectedSourceId].indexOf(component.value) < 0 : true);
+ }
+ });
+ }
+
+ filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) {
+ return componentsOptions.filter(component => {
+ if (component.value === selectedSourceId) {
+ return true;
+ } else {
+ let isInMap = sourceToTargetMapping.hasOwnProperty(component.value);
+ return component.value !== selectedTargetId && (isInMap ? sourceToTargetMapping[component.value].indexOf(selectedTargetId) < 0 : true);
+ }
+ });
+ }
+
+ render() {
+ let {componentsOptions, softwareProductDependencies, onDataChanged, onAddDependency, isReadOnlyMode} = this.props;
+ let canAdd = softwareProductDependencies.length < componentsOptions.length * (componentsOptions.length - 1);
+ let sourceToTargetMapping = {};
+ softwareProductDependencies.map(dependency => {
+ let isInMap = sourceToTargetMapping.hasOwnProperty(dependency.sourceId);
+ if (dependency.targetId) {
+ sourceToTargetMapping[dependency.sourceId] = isInMap ? [...sourceToTargetMapping[dependency.sourceId], dependency.targetId] : [dependency.targetId];
+ }
+ });
+ return (
+ <div className='software-product-dependencies'>
+ <div className='software-product-dependencies-title'>{i18n('Dependencies')}</div>
+ <SelectActionTable
+ columns={['Source', 'Relation Type', 'Target']}
+ isReadOnlyMode={isReadOnlyMode}
+ onAdd={canAdd ? onAddDependency : undefined}
+ onAddItem={i18n('Add Rule')}>
+ {softwareProductDependencies.map(dependency => (
+ <SelectActionTableRow
+ key={dependency.id}
+ onDelete={() => onDataChanged(softwareProductDependencies.filter(currentDependency => currentDependency.id !== dependency.id))}
+ overlayMsg={i18n('There is a loop between selections')}
+ hasError={dependency.hasCycle}>
+ <SelectActionTableCell
+ options={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
+ selected={dependency.sourceId}
+ placeholder={i18n('Select VFC...')}
+ onChange={newSourceId => onDataChanged(softwareProductDependencies.map(currentDependency =>
+ ({...currentDependency, sourceId: currentDependency.id === dependency.id ? newSourceId : currentDependency.sourceId})
+ ))} />
+ <SelectActionTableCell options={relationTypesOptions} selected={dependency.relationType} clearable={false}/>
+ <SelectActionTableCell
+ placeholder={i18n('Select VFC...')}
+ options={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
+ selected={dependency.targetId}
+ onChange={newTargetId => onDataChanged(softwareProductDependencies.map(currentDependency =>
+ ({...currentDependency, targetId: currentDependency.id === dependency.id ? newTargetId : currentDependency.targetId})
+ ))} />
+ </SelectActionTableRow>
+ ))}
+ </SelectActionTable>
+ </div>
+ );
+ }
+
+ save() {
+ let {onSubmit, softwareProductDependencies} = this.props;
+ return onSubmit(softwareProductDependencies);
+ }
+}