diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools')
9 files changed, 797 insertions, 0 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js new file mode 100644 index 0000000000..631597a5b0 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; +import Configuration from 'sdc-app/config/Configuration.js'; +import {actionTypes as entitlementPoolsActionTypes } from './EntitlementPoolsConstants.js'; +import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; + +function baseUrl(licenseModelId) { + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/entitlement-pools`; +} + +function fetchEntitlementPoolsList(licenseModelId, version) { + let versionQuery = version ? `?version=${version}` : ''; + return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); +} + +function postEntitlementPool(licenseModelId, entitlementPool) { + return RestAPIUtil.create(baseUrl(licenseModelId), { + name: entitlementPool.name, + description: entitlementPool.description, + thresholdValue: entitlementPool.thresholdValue, + thresholdUnits: entitlementPool.thresholdUnits, + entitlementMetric: entitlementPool.entitlementMetric, + increments: entitlementPool.increments, + aggregationFunction: entitlementPool.aggregationFunction, + operationalScope: entitlementPool.operationalScope, + time: entitlementPool.time, + manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber + }); +} + + +function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool) { + return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${entitlementPool.id}`, { + name: entitlementPool.name, + description: entitlementPool.description, + thresholdValue: entitlementPool.thresholdValue, + thresholdUnits: entitlementPool.thresholdUnits, + entitlementMetric: entitlementPool.entitlementMetric, + increments: entitlementPool.increments, + aggregationFunction: entitlementPool.aggregationFunction, + operationalScope: entitlementPool.operationalScope, + time: entitlementPool.time, + manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber + }); +} + +function deleteEntitlementPool(licenseModelId, entitlementPoolId) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${entitlementPoolId}`); +} + + +export default { + fetchEntitlementPoolsList(dispatch, {licenseModelId, version}) { + return fetchEntitlementPoolsList(licenseModelId, version).then(response => dispatch({ + type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_LIST_LOADED, + response + })); + }, + + openEntitlementPoolsEditor(dispatch, {entitlementPool} = {}) { + dispatch({ + type: entitlementPoolsActionTypes.entitlementPoolsEditor.OPEN, + entitlementPool + }); + }, + + deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId}) { + return deleteEntitlementPool(licenseModelId, entitlementPoolId).then(() => { + dispatch({ + type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL, + entitlementPoolId + }); + }); + }, + + entitlementPoolsEditorDataChanged(dispatch, {deltaData}) { + dispatch({ + type: entitlementPoolsActionTypes.entitlementPoolsEditor.DATA_CHANGED, + deltaData + }); + }, + + closeEntitlementPoolsEditor(dispatch) { + dispatch({ + type: entitlementPoolsActionTypes.entitlementPoolsEditor.CLOSE + }); + }, + + saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}) { + if (previousEntitlementPool) { + return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool).then(() => { + dispatch({ + type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL, + entitlementPool + }); + }); + } + else { + return postEntitlementPool(licenseModelId, entitlementPool).then(response => { + dispatch({ + type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL, + entitlementPool: { + ...entitlementPool, + id: response.value + } + }); + }); + } + }, + + hideDeleteConfirm(dispatch) { + dispatch({ + type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM, + entitlementPoolToDelete: false + }); + }, + openDeleteEntitlementPoolConfirm(dispatch, {entitlementPool}) { + dispatch({ + type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_DELETE_CONFIRM, + entitlementPoolToDelete: entitlementPool + }); + }, + + switchVersion(dispatch, {licenseModelId, version}) { + LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => { + this.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}); + }); + } +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx new file mode 100644 index 0000000000..04f038f5f0 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import {connect} from 'react-redux'; +import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx'; +import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +function renderMsg(entitlementPoolToDelete) { + let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : ''; + let msg = i18n('Are you sure you want to delete "{poolName}"?', {poolName}); + let subMsg = entitlementPoolToDelete + && entitlementPoolToDelete.referencingFeatureGroups + && entitlementPoolToDelete.referencingFeatureGroups.length > 0 ? + i18n('This entitlement pool is associated with one or more feature groups') : + ''; + return ( + <div> + <p>{msg}</p> + <p>{subMsg}</p> + </div> + ); +}; + +const mapStateToProps = ({licenseModel: {entitlementPool}}, {licenseModelId}) => { + let {entitlementPoolToDelete} = entitlementPool; + const show = entitlementPoolToDelete !== false; + return { + show, + title: 'Warning!', + type: 'warning', + msg: renderMsg(entitlementPoolToDelete), + confirmationDetails: {entitlementPoolToDelete, licenseModelId} + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onConfirmed: ({entitlementPoolToDelete, licenseModelId}) => { + EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, { + licenseModelId, + entitlementPoolId: entitlementPoolToDelete.id + }); + EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch); + }, + onDeclined: () => { + EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch); + } + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView); + diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js new file mode 100644 index 0000000000..8a855076f3 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js @@ -0,0 +1,112 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import keyMirror from 'nfvo-utils/KeyMirror.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +export const actionTypes = keyMirror({ + + ENTITLEMENT_POOLS_LIST_LOADED: null, + ADD_ENTITLEMENT_POOL: null, + EDIT_ENTITLEMENT_POOL: null, + DELETE_ENTITLEMENT_POOL: null, + ENTITLEMENT_POOLS_DELETE_CONFIRM: null, + + entitlementPoolsEditor: { + OPEN: null, + CLOSE: null, + DATA_CHANGED: null, + } + +}); + +export const enums = keyMirror({ + SELECTED_FEATURE_GROUP_TAB: { + GENERAL: 1, + ENTITLEMENT_POOLS: 2, + LICENCE_KEY_GROUPS: 3 + }, + SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: { + ASSOCIATED_ENTITLEMENT_POOLS: 1, + AVAILABLE_ENTITLEMENT_POOLS: 2 + } +}); + +export const defaultState = { + ENTITLEMENT_POOLS_EDITOR_DATA: { + entitlementMetric: {choice: '', other: ''}, + aggregationFunction: {choice: '', other: ''}, + operationalScope: {choices: [], other: ''}, + time: {choice: '', other: ''} + } +}; + +export const thresholdUnitType = { + ABSOLUTE: 'Absolute', + PERCENTAGE: 'Percentage' +}; + +export const optionsInputValues = { + OPERATIONAL_SCOPE: [ + {enum: '', title: i18n('please select…')}, + {enum: 'Network_Wide', title: 'Network Wide'}, + {enum: 'Availability_Zone', title: 'Availability Zone'}, + {enum: 'Data_Center', title: 'Data Center'}, + {enum: 'Tenant', title: 'Tenant'}, + {enum: 'VM', title: 'VM'}, + {enum: 'CPU', title: 'CPU'}, + {enum: 'Core', title: 'Core'} + ], + TIME: [ + {enum: '', title: i18n('please select…')}, + {enum: 'Hour', title: 'Hour'}, + {enum: 'Day', title: 'Day'}, + {enum: 'Month', title: 'Month'} + ], + AGGREGATE_FUNCTION: [ + {enum: '', title: i18n('please select…')}, + {enum: 'Peak', title: 'Peak'}, + {enum: 'Average', title: 'Average'} + ], + ENTITLEMENT_METRIC: [ + {enum: '', title: i18n('please select…')}, + {enum: 'Software_Instances_Count', title: 'Software Instances'}, + {enum: 'Core', title: 'Core'}, + {enum: 'CPU', title: 'CPU'}, + {enum: 'Trunks', title: 'Trunks'}, + {enum: 'User', title: 'User'}, + {enum: 'Subscribers', title: 'Subscribers'}, + {enum: 'Tenants', title: 'Tenants'}, + {enum: 'Tokens', title: 'Tokens'}, + {enum: 'Seats', title: 'Seats'}, + {enum: 'Units_TB', title: 'Units-TB'}, + {enum: 'Units_GB', title: 'Units-GB'}, + {enum: 'Units_MB', title: 'Units-MB'} + ], + THRESHOLD_UNITS: [ + {enum: '', title: i18n('please select…')}, + {enum: thresholdUnitType.ABSOLUTE, title: 'Absolute'}, + {enum: thresholdUnitType.PERCENTAGE, title: '%'} + ] +}; + + + + diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js new file mode 100644 index 0000000000..d5bd07e929 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {connect} from 'react-redux'; +import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js'; +import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx'; + +const mapStateToProps = ({licenseModel: {entitlementPool}}) => { + + + let {data} = entitlementPool.entitlementPoolEditor; + + let previousData; + const entitlementPoolId = data ? data.id : null; + if(entitlementPoolId) { + previousData = entitlementPool.entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId); + } + + return { + data, + previousData + }; +}; + +const mapActionsToProps = (dispatch, {licenseModelId}) => { + return { + onDataChanged: deltaData => EntitlementPoolsActionHelper.entitlementPoolsEditorDataChanged(dispatch, {deltaData}), + onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch), + onSubmit: ({previousEntitlementPool, entitlementPool}) => { + EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch); + EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}); + } + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsEditorView); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js new file mode 100644 index 0000000000..86e97ecf8d --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {actionTypes, defaultState} from './EntitlementPoolsConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case actionTypes.entitlementPoolsEditor.OPEN: + return { + ...state, + data: action.entitlementPool ? {...action.entitlementPool} : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA + }; + case actionTypes.entitlementPoolsEditor.DATA_CHANGED: + return { + ...state, + data: { + ...state.data, + ...action.deltaData + } + }; + case actionTypes.entitlementPoolsEditor.CLOSE: + return {}; + default: + return state; + } + +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx new file mode 100644 index 0000000000..77c5a12e03 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx @@ -0,0 +1,167 @@ +import React from 'react'; + + +import i18n from 'nfvo-utils/i18n/i18n.js'; + +import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx'; +import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx'; +import {optionsInputValues as EntitlementPoolsOptionsInputValues, thresholdUnitType} from './EntitlementPoolsConstants.js'; +import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; + + +const EntitlementPoolPropType = React.PropTypes.shape({ + id: React.PropTypes.string, + name: React.PropTypes.string, + description: React.PropTypes.string, + manufacturerReferenceNumber: React.PropTypes.string, + operationalScope: React.PropTypes.shape({ + choices: React.PropTypes.array, + other: React.PropTypes.string + }), + aggregationFunction: React.PropTypes.shape({ + choice: React.PropTypes.string, + other: React.PropTypes.string + }), + increments: React.PropTypes.string, + time: React.PropTypes.shape({ + choice: React.PropTypes.string, + other: React.PropTypes.string + }), + entitlementMetric: React.PropTypes.shape({ + choice: React.PropTypes.string, + other: React.PropTypes.string + }) +}); + +class EntitlementPoolsEditorView extends React.Component { + + static propTypes = { + data: EntitlementPoolPropType, + previousData: EntitlementPoolPropType, + isReadOnlyMode: React.PropTypes.bool, + onDataChanged: React.PropTypes.func.isRequired, + onSubmit: React.PropTypes.func.isRequired, + onCancel: React.PropTypes.func.isRequired + }; + + static defaultProps = { + data: {} + }; + + render() { + let {data = {}, onDataChanged, isReadOnlyMode} = this.props; + let { + name, description, manufacturerReferenceNumber, operationalScope, aggregationFunction, thresholdUnits, thresholdValue, + increments, time, entitlementMetric} = data; + let thresholdValueValidation = thresholdUnits === thresholdUnitType.PERCENTAGE ? {numeric: true, required: true, maxValue: 100} : {numeric: true, required: true}; + let timeValidation = time && time.choice === optionInputOther.OTHER ? {numeric: true, required: true} : {required: true}; + + return ( + <ValidationForm + ref='validationForm' + hasButtons={true} + onSubmit={ () => this.submit() } + onReset={ () => this.props.onCancel() } + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + className='entitlement-pools-form'> + <div className='entitlement-pools-form-row'> + <ValidationInput + onChange={name => onDataChanged({name})} + label={i18n('Name')} + value={name} + validations={{maxLength: 120, required: true}} + type='text'/> + + <ValidationInput + isMultiSelect={true} + onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})} + onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})} + multiSelectedEnum={operationalScope && operationalScope.choices} + label={i18n('Operational Scope')} + otherValue={operationalScope && operationalScope.other} + validations={{required: true}} + values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}/> + + </div> + <div className='entitlement-pools-form-row'> + <ValidationInput + onChange={description => onDataChanged({description})} + label={i18n('Description')} + value={description} + validations={{maxLength: 1000, required: true}} + type='textarea'/> + <div className='entitlement-pools-form-row-group'> + <div className='entitlement-pools-form-row'> + <ValidationInput + onEnumChange={thresholdUnits => onDataChanged({thresholdUnits})} + selectedEnum={thresholdUnits} + label={i18n('Threshold Value')} + type='select' + values={EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS} + validations={{required: true}}/> + <ValidationInput + className='entitlement-pools-form-row-threshold-value' + onChange={thresholdValue => onDataChanged({thresholdValue})} + value={thresholdValue} + validations={thresholdValueValidation} + type='text'/> + </div> + + <ValidationInput + onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}})} + onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER, other: entitlementMetric}})} + selectedEnum={entitlementMetric && entitlementMetric.choice} + otherValue={entitlementMetric && entitlementMetric.other} + label={i18n('Entitlement Metric')} + validations={{required: true}} + values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC}/> + <ValidationInput + onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}})} + onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER, other: aggregationFunction}})} + selectedEnum={aggregationFunction && aggregationFunction.choice} + otherValue={aggregationFunction && aggregationFunction.other} + validations={{required: true}} + label={i18n('Aggregate Function')} + values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION}/> + + </div> + </div> + <div className='entitlement-pools-form-row'> + + <ValidationInput + onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber})} + label={i18n('Manufacturer Reference Number')} + value={manufacturerReferenceNumber} + validations={{maxLength: 100, required: true}} + type='text'/> + + <ValidationInput + onEnumChange={time => onDataChanged({time:{choice: time, other: ''}})} + onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER, other: time}})} + selectedEnum={time && time.choice} + otherValue={time && time.other} + validations={timeValidation} + label={i18n('Time')} + values={EntitlementPoolsOptionsInputValues.TIME}/> + </div> + <div className='entitlement-pools-form-row'> + <ValidationInput + onChange={increments => onDataChanged({increments})} + label={i18n('Increments')} + value={increments} + validations={{maxLength: 120}} + type='text'/> + + </div> + </ValidationForm> + ); + } + + submit() { + const {data: entitlementPool, previousData: previousEntitlementPool} = this.props; + this.props.onSubmit({entitlementPool, previousEntitlementPool}); + } +} + +export default EntitlementPoolsEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js new file mode 100644 index 0000000000..4b21a2fea8 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {connect} from 'react-redux'; +import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js'; +import EntitlementPoolsListEditorView from './EntitlementPoolsListEditorView.jsx'; +import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; + +const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) => { + let {entitlementPoolsList} = entitlementPool; + let {data} = entitlementPool.entitlementPoolEditor; + + let {vendorName} = licenseModelEditor.data; + let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data); + + return { + vendorName, + entitlementPoolsList, + isReadOnlyMode, + isDisplayModal: Boolean(data), + isModalInEditMode: Boolean(data && data.id), + }; +}; + +const mapActionsToProps = (dispatch, {licenseModelId}) => { + return { + onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch), + onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool}), + onDeleteEntitlementPool: entitlementPool => EntitlementPoolsActionHelper.openDeleteEntitlementPoolConfirm(dispatch, { + licenseModelId, + entitlementPool + }) + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(EntitlementPoolsListEditorView); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx new file mode 100644 index 0000000000..52df102503 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx @@ -0,0 +1,132 @@ +import React from 'react'; + +import i18n from 'nfvo-utils/i18n/i18n.js'; +import Modal from 'nfvo-components/modal/Modal.jsx'; +import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; +import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; + +import EntitlementPoolsEditor from './EntitlementPoolsEditor.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; +import {optionsInputValues} from './EntitlementPoolsConstants'; +import EntitlementPoolsConfirmationModal from './EntitlementPoolsConfirmationModal.jsx'; + + +class EntitlementPoolsListEditorView extends React.Component { + static propTypes = { + vendorName: React.PropTypes.string, + licenseModelId: React.PropTypes.string.isRequired, + entitlementPoolsList: React.PropTypes.array, + isReadOnlyMode: React.PropTypes.bool.isRequired, + isDisplayModal: React.PropTypes.bool, + isModalInEditMode: React.PropTypes.bool, + onAddEntitlementPoolClick: React.PropTypes.func, + onEditEntitlementPoolClick: React.PropTypes.func, + onDeleteEntitlementPool: React.PropTypes.func, + }; + + static defaultProps = { + entitlementPoolsList: [] + }; + + state = { + localFilter: '' + }; + + render() { + let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; + let {onAddEntitlementPoolClick} = this.props; + const {localFilter} = this.state; + + return ( + <div className='entitlement-pools-list-editor'> + <ListEditorView + title={i18n('Entitlement Pools for {vendorName} License Model', {vendorName})} + plusButtonTitle={i18n('Add Entitlement Pool')} + onAdd={onAddEntitlementPoolClick} + filterValue={localFilter} + onFilter={filter => this.setState({localFilter: filter})} + isReadOnlyMode={isReadOnlyMode}> + {this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))} + </ListEditorView> + <Modal show={isDisplayModal} bsSize='large' animation={true} className='entitlement-pools-modal'> + <Modal.Header> + <Modal.Title>{`${isModalInEditMode ? i18n('Edit Entitlement Pool') : i18n('Create New Entitlement Pool')}`}</Modal.Title> + </Modal.Header> + <Modal.Body> + { + isDisplayModal && ( + <EntitlementPoolsEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/> + ) + } + </Modal.Body> + </Modal> + + <EntitlementPoolsConfirmationModal licenseModelId={licenseModelId}/> + </div> + ); + } + + filterList() { + let {entitlementPoolsList} = this.props; + let {localFilter} = this.state; + if(localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return entitlementPoolsList.filter(({name = '', description = ''}) => { + return escape(name).match(filter) || escape(description).match(filter); + }); + } + else { + return entitlementPoolsList; + } + } + + renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode) { + let {id, name, description, thresholdValue, thresholdUnits, entitlementMetric, aggregationFunction, + manufacturerReferenceNumber, time} = entitlementPool; + let {onEditEntitlementPoolClick, onDeleteEntitlementPool} = this.props; + return ( + <ListEditorItemView + key={id} + onSelect={() => onEditEntitlementPoolClick(entitlementPool)} + onDelete={() => onDeleteEntitlementPool(entitlementPool)} + className='list-editor-item-view' + isReadOnlyMode={isReadOnlyMode}> + <div className='list-editor-item-view-field'> + <div className='title'>{i18n('Name')}</div> + <div className='text name'>{name}</div> + </div> + + <div className='list-editor-item-view-field'> + <div className='title'>{i18n('Entitlement')}</div> + <div className='entitlement-parameters'>{`${this.extractValue(aggregationFunction)} ${this.extractValue(entitlementMetric)} per ${this.extractValue(time)}`}</div> + <div className='entitlement-pools-count'>{`${thresholdValue ? thresholdValue : ''} ${this.extractUnits(thresholdUnits)}`}</div> + </div> + + <div className='list-editor-item-view-field'> + <div className='title'>{i18n('Manufacturer Reference Number')}</div> + <div className='text contract-number'>{manufacturerReferenceNumber}</div> + </div> + + <div className='list-editor-item-view-field'> + <div className='title'>{i18n('Description')}</div> + <div className='text description'>{description}</div> + </div> + </ListEditorItemView> + ); + } + + + + extractUnits(units) { + if (units === undefined) {return '';} //TODO fix it later + return units === 'Absolute' ? '' : '%'; + } + + extractValue(item) { + if (item === undefined) {return '';} //TODO fix it later + + return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : ''; + } +} + +export default EntitlementPoolsListEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js new file mode 100644 index 0000000000..63e351fce7 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +import {actionTypes} from './EntitlementPoolsConstants'; +export default (state = [], action) => { + switch (action.type) { + case actionTypes.ENTITLEMENT_POOLS_LIST_LOADED: + return [...action.response.results]; + case actionTypes.ADD_ENTITLEMENT_POOL: + return [...state, action.entitlementPool]; + case actionTypes.EDIT_ENTITLEMENT_POOL: + const indexForEdit = state.findIndex(entitlementPool => entitlementPool.id === action.entitlementPool.id); + return [...state.slice(0, indexForEdit), action.entitlementPool, ...state.slice(indexForEdit + 1)]; + case actionTypes.DELETE_ENTITLEMENT_POOL: + return state.filter(entitlementPool => entitlementPool.id !== action.entitlementPoolId); + default: + return state; + } +}; |