diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies')
6 files changed, 416 insertions, 245 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 index 9888087800..1a0c66d70e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js @@ -13,25 +13,48 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductDependenciesView from './SoftwareProductDependenciesView.jsx'; import SoftwareProductDependenciesActionHelper from './SoftwareProductDependenciesActionHelper.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductDependencies, softwareProductComponents: {componentsList}} = softwareProduct; - return { - softwareProductDependencies: softwareProductDependencies, - componentsOptions: componentsList.map(component => ({value: component.id, label: component.displayName})) - }; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductDependencies, + softwareProductComponents: { componentsList } + } = softwareProduct; + return { + softwareProductDependencies: softwareProductDependencies, + componentsOptions: componentsList.map(component => ({ + value: component.id, + label: component.displayName + })) + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDataChanged: (item) => SoftwareProductDependenciesActionHelper.updateDependency(dispatch, {softwareProductId, version, item}), - onDeleteDependency: (item) => SoftwareProductDependenciesActionHelper.removeDependency(dispatch, {softwareProductId, version, item}), - onAddDependency: (item) => SoftwareProductDependenciesActionHelper.createDependency(dispatch, {softwareProductId, version, item}) - }; +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDataChanged: item => + SoftwareProductDependenciesActionHelper.updateDependency(dispatch, { + softwareProductId, + version, + item + }), + onDeleteDependency: item => + SoftwareProductDependenciesActionHelper.removeDependency(dispatch, { + softwareProductId, + version, + item + }), + onAddDependency: item => + SoftwareProductDependenciesActionHelper.createDependency(dispatch, { + softwareProductId, + version, + item + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDependenciesView); +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 index f04f8faf56..4bbcaa13d5 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js @@ -15,83 +15,99 @@ */ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {actionTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; +import { + actionTypes, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.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-dependencies`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependencies`; } function fetchDependencies(softwareProductId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } function addDepencency(softwareProductId, version, item) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { - sourceId: item.sourceId, - targetId: item.targetId, - relationType: item.relationType - }); + return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { + sourceId: item.sourceId, + targetId: item.targetId, + relationType: item.relationType + }); } - function updateDepencency(softwareProductId, version, item) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${item.id}`, - { - sourceId: item.sourceId, - targetId: item.targetId, - relationType: item.relationType - }); + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version)}/${item.id}`, + { + sourceId: item.sourceId, + targetId: item.targetId, + relationType: item.relationType + } + ); } function removeDependency(softwareProductId, version, item) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${item.id}`); + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version)}/${item.id}` + ); } - const SoftwareProductDependenciesActionHelper = { - updateDependency(dispatch, {softwareProductId, version, item}) { - // if change was made on existing item - we will update the server and refresh the list - // if change was made on the 'new' row - we will only fire the event - if (item.id !== NEW_RULE_TEMP_ID) { - return updateDepencency(softwareProductId, version, item).then(() => { - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - } else { - dispatch({ - type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY, - item: item - }); - } - }, + updateDependency(dispatch, { softwareProductId, version, item }) { + // if change was made on existing item - we will update the server and refresh the list + // if change was made on the 'new' row - we will only fire the event + if (item.id !== NEW_RULE_TEMP_ID) { + return updateDepencency(softwareProductId, version, item).then( + () => { + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + } + ); + } else { + dispatch({ + type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY, + item: item + }); + } + }, - createDependency(dispatch, {softwareProductId, version, item}) { - // removing the temp id - delete item.id; - // creating the new dependency - return addDepencency(softwareProductId, version, item).then(() => { - dispatch({ - type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY - }); - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - }, + createDependency(dispatch, { softwareProductId, version, item }) { + // removing the temp id + delete item.id; + // creating the new dependency + return addDepencency(softwareProductId, version, item).then(() => { + dispatch({ + type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY + }); + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + }); + }, - removeDependency(dispatch, {softwareProductId, version, item}) { - return removeDependency(softwareProductId, version, item).then( () => { - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - }, + removeDependency(dispatch, { softwareProductId, version, item }) { + return removeDependency(softwareProductId, version, item).then(() => { + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + }); + }, - fetchDependencies(dispatch, {softwareProductId, version}) { - return fetchDependencies(softwareProductId, version).then( response => { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, - dependenciesList : response.results - }); - }); - } + fetchDependencies(dispatch, { softwareProductId, version }) { + return fetchDependencies(softwareProductId, version).then(response => { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, + dependenciesList: response.results + }); + }); + } }; 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 index c25561da17..32c7387ca2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js @@ -16,17 +16,17 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null, - ADD_SOFTWARE_PRODUCT_DEPENDENCY: null, - UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null + SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null, + ADD_SOFTWARE_PRODUCT_DEPENDENCY: null, + UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null }); export const relationTypes = { - DEPENDS_ON: 'dependsOn' + DEPENDS_ON: 'dependsOn' }; export const relationTypesOptions = [ - {value: relationTypes.DEPENDS_ON, label: 'Depends On'} + { value: relationTypes.DEPENDS_ON, label: 'Depends On' } ]; -export const NEW_RULE_TEMP_ID = 'newRuleTempId';
\ No newline at end of file +export const NEW_RULE_TEMP_ID = 'newRuleTempId'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js index 3edd3b899a..6e028b1ff2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js @@ -1,4 +1,3 @@ - /*! * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * @@ -15,32 +14,47 @@ * permissions and limitations under the License. */ -import {actionTypes, relationTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; -import {checkCyclesAndMarkDependencies} from './SoftwareProductDependenciesUtils.js'; +import { + actionTypes, + relationTypes, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.js'; +import { checkCyclesAndMarkDependencies } from './SoftwareProductDependenciesUtils.js'; -let newRowObject = {id: NEW_RULE_TEMP_ID, targetId: null, sourceId: null, relationType: relationTypes.DEPENDS_ON}; +let newRowObject = { + id: NEW_RULE_TEMP_ID, + targetId: null, + sourceId: null, + relationType: relationTypes.DEPENDS_ON +}; -export default (state = [Object.assign({}, newRowObject) ], action) => { - switch (action.type) { - case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: - // copying the entity with the data for the row that is in the 'add' mode - let newDependency = state.find(dependency => dependency.id === NEW_RULE_TEMP_ID); - action.dependenciesList.push(newDependency); - // returning list from the server with our 'new entity' row - return checkCyclesAndMarkDependencies(action.dependenciesList); - case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY : - // resetting the entity with the data for the 'add' mode for a new entity - let newArray = state.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID); - newArray.push(Object.assign({}, newRowObject)); - return newArray; - case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY : - // we really only need this for the 'new' row since we need to change the state to get - // everything updated - let updateArrayIndex = state.findIndex(dependency => dependency.id === NEW_RULE_TEMP_ID); - let updateArray = state.slice(); - updateArray.splice(updateArrayIndex, 1, action.item); - return checkCyclesAndMarkDependencies(updateArray); - default: - return state; - } +export default (state = [Object.assign({}, newRowObject)], action) => { + switch (action.type) { + case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: + // copying the entity with the data for the row that is in the 'add' mode + let newDependency = state.find( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + action.dependenciesList.push(newDependency); + // returning list from the server with our 'new entity' row + return checkCyclesAndMarkDependencies(action.dependenciesList); + case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY: + // resetting the entity with the data for the 'add' mode for a new entity + let newArray = state.filter( + dependency => dependency.id !== NEW_RULE_TEMP_ID + ); + newArray.push(Object.assign({}, newRowObject)); + return newArray; + case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: + // we really only need this for the 'new' row since we need to change the state to get + // everything updated + let updateArrayIndex = state.findIndex( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + let updateArray = state.slice(); + updateArray.splice(updateArrayIndex, 1, action.item); + return checkCyclesAndMarkDependencies(updateArray); + 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 index 94d21bd49d..8d5aaf864e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js @@ -16,49 +16,77 @@ 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}; +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 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}); - } - } + 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 - })); + 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 index ed92de7bb1..3ea1f2d5cc 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx @@ -20,111 +20,201 @@ 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, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; +import { + relationTypesOptions, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.js'; - -const TableActionRow = ({onAction, actionIcon, showAction, dependency, sourceOptions, targetOptions, onDataChanged}) => { - return ( - <SelectActionTableRow - key={dependency.id} - onAction={onAction} - overlayMsg={i18n('There is a loop between selections')} - hasError={dependency.hasCycle} - hasErrorIndication - showAction={showAction} - actionIcon={actionIcon}> - <SelectActionTableCell - options={sourceOptions} - selected={dependency.sourceId} - placeholder={i18n('Select VFC...')} - clearable={false} - onChange={newVal => { - dependency.sourceId = newVal; - onDataChanged(dependency); - }} /> - <SelectActionTableCell options={relationTypesOptions} selected={dependency.relationType} clearable={false}/> - <SelectActionTableCell - placeholder={i18n('Select VFC...')} - options={targetOptions} - selected={dependency.targetId} - clearable={false} - onChange={newVal => { - dependency.targetId = newVal; - onDataChanged(dependency); - }} /> - </SelectActionTableRow> - ); +const TableActionRow = ({ + onAction, + actionIcon, + showAction, + dependency, + sourceOptions, + targetOptions, + onDataChanged +}) => { + return ( + <SelectActionTableRow + key={dependency.id} + onAction={onAction} + overlayMsg={i18n('There is a loop between selections')} + hasError={dependency.hasCycle} + hasErrorIndication + showAction={showAction} + actionIcon={actionIcon}> + <SelectActionTableCell + options={sourceOptions} + selected={dependency.sourceId} + placeholder={i18n('Select VFC...')} + clearable={false} + onChange={newVal => { + dependency.sourceId = newVal; + onDataChanged(dependency); + }} + /> + <SelectActionTableCell + options={relationTypesOptions} + selected={dependency.relationType} + clearable={false} + /> + <SelectActionTableCell + placeholder={i18n('Select VFC...')} + options={targetOptions} + selected={dependency.targetId} + clearable={false} + onChange={newVal => { + dependency.targetId = newVal; + onDataChanged(dependency); + }} + /> + </SelectActionTableRow> + ); }; - 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); - } - }); - } + 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) + ); + } + }); + } - render() { - let {componentsOptions, softwareProductDependencies, onDataChanged, onAddDependency, onDeleteDependency, isReadOnlyMode} = this.props; - 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]; - } - }); - let depList = softwareProductDependencies.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID); - let newDependency = softwareProductDependencies.find(dependency => dependency.id === NEW_RULE_TEMP_ID); - return ( - <div className='software-product-dependencies'> - <div className='page-title'>{i18n('Dependencies')}</div> - <SelectActionTable - columns={[i18n('Source'), i18n('Relation Type'), i18n('Target')]} - numOfIcons={2} - isReadOnlyMode={isReadOnlyMode}> - {!isReadOnlyMode && <TableActionRow - key={newDependency.id} - actionIcon='plusCircle' - onAction={() => onAddDependency(newDependency)} - dependency={newDependency} - componentsOptions={componentsOptions} - sourceToTargetMapping={sourceToTargetMapping} - onDataChanged={onDataChanged} - sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})} - targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})} - showAction={newDependency.targetId !== null && newDependency.relationType !== null && newDependency.sourceId !== null}/> } - {depList.map(dependency => ( - <TableActionRow - key={dependency.id} - actionIcon='trashO' - onAction={() => onDeleteDependency(dependency)} - dependency={dependency} - componentsOptions={componentsOptions} - sourceToTargetMapping={sourceToTargetMapping} - sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})} - targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})} - onDataChanged={onDataChanged} - showAction={true}/> - ))} - </SelectActionTable> - </div> - ); - } + 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, + onDeleteDependency, + isReadOnlyMode + } = this.props; + 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]; + } + }); + let depList = softwareProductDependencies.filter( + dependency => dependency.id !== NEW_RULE_TEMP_ID + ); + let newDependency = softwareProductDependencies.find( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + return ( + <div className="software-product-dependencies"> + <div className="page-title">{i18n('Dependencies')}</div> + <SelectActionTable + columns={[ + i18n('Source'), + i18n('Relation Type'), + i18n('Target') + ]} + numOfIcons={2} + isReadOnlyMode={isReadOnlyMode}> + {!isReadOnlyMode && ( + <TableActionRow + key={newDependency.id} + actionIcon="plusCircle" + onAction={() => onAddDependency(newDependency)} + dependency={newDependency} + componentsOptions={componentsOptions} + sourceToTargetMapping={sourceToTargetMapping} + onDataChanged={onDataChanged} + sourceOptions={this.filterSources({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: newDependency.sourceId, + selectedTargetId: newDependency.targetId + })} + targetOptions={this.filterTargets({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: newDependency.sourceId, + selectedTargetId: newDependency.targetId + })} + showAction={ + newDependency.targetId !== null && + newDependency.relationType !== null && + newDependency.sourceId !== null + } + /> + )} + {depList.map(dependency => ( + <TableActionRow + key={dependency.id} + actionIcon="trashO" + onAction={() => onDeleteDependency(dependency)} + dependency={dependency} + componentsOptions={componentsOptions} + sourceToTargetMapping={sourceToTargetMapping} + sourceOptions={this.filterSources({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: dependency.sourceId, + selectedTargetId: dependency.targetId + })} + targetOptions={this.filterTargets({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: dependency.sourceId, + selectedTargetId: dependency.targetId + })} + onDataChanged={onDataChanged} + showAction={true} + /> + ))} + </SelectActionTable> + </div> + ); + } } |