diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement')
9 files changed, 852 insertions, 0 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js new file mode 100644 index 0000000000..9616b60b76 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js @@ -0,0 +1,160 @@ +/*- + * ============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 licenseAgreementActionTypes} from './LicenseAgreementConstants.js'; +import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.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}/license-agreements`; +} + +function fetchLicenseAgreementList(licenseModelId, version) { + let versionQuery = version ? `?version=${version}` : ''; + return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); +} + +function postLicenseAgreement(licenseModelId, licenseAgreement) { + return RestAPIUtil.create(baseUrl(licenseModelId), { + name: licenseAgreement.name, + description: licenseAgreement.description, + licenseTerm: licenseAgreement.licenseTerm, + requirementsAndConstrains: licenseAgreement.requirementsAndConstrains, + addedFeatureGroupsIds: licenseAgreement.featureGroupsIds + }); +} + +function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement) { + const {featureGroupsIds = []} = licenseAgreement; + const {featureGroupsIds: prevFeatureGroupsIds = []} = previousLicenseAgreement; + return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseAgreement.id}`, { + name: licenseAgreement.name, + description: licenseAgreement.description, + licenseTerm: licenseAgreement.licenseTerm, + requirementsAndConstrains: licenseAgreement.requirementsAndConstrains, + addedFeatureGroupsIds: featureGroupsIds.filter(featureGroupId => prevFeatureGroupsIds.indexOf(featureGroupId) === -1), + removedFeatureGroupsIds: prevFeatureGroupsIds.filter(prevFeatureGroupsId => featureGroupsIds.indexOf(prevFeatureGroupsId) === -1) + }); +} + +function deleteLicenseAgreement(licenseModelId, licenseAgreementId) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseAgreementId}`); +} + +export default { + + fetchLicenseAgreementList(dispatch, {licenseModelId, version}) { + return fetchLicenseAgreementList(licenseModelId, version).then(response => dispatch({ + type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED, + response + })); + }, + + openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}) { + FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId}); + dispatch({ + type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN, + licenseAgreement + }); + }, + + licenseAgreementEditorDataChanged(dispatch, {deltaData}) { + dispatch({ + type: licenseAgreementActionTypes.licenseAgreementEditor.DATA_CHANGED, + deltaData + }); + }, + + closeLicenseAgreementEditor(dispatch) { + dispatch({ + type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE + }); + }, + + + saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement}) { + if (previousLicenseAgreement) { + return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement).then(() => { + dispatch({ + type: licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT, + licenseAgreement + }); + }); + } + else { + return postLicenseAgreement(licenseModelId, licenseAgreement).then(response => { + dispatch({ + type: licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT, + licenseAgreement: { + ...licenseAgreement, + id: response.value + } + }); + }); + } + }, + + deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId}) { + return deleteLicenseAgreement(licenseModelId, licenseAgreementId).then(() => { + dispatch({ + type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT, + licenseAgreementId + }); + }); + }, + + selectLicenseAgreementEditorTab(dispatch, {tab}) { + dispatch({ + type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_TAB, + tab + }); + }, + + selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}) { + dispatch({ + type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB, + buttonTab + }); + }, + + hideDeleteConfirm(dispatch) { + dispatch({ + type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM, + licenseAgreementToDelete: false + }); + }, + + openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement} ) { + dispatch({ + type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM, + licenseAgreementToDelete: licenseAgreement + }); + }, + + switchVersion(dispatch, {licenseModelId, version}) { + LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => { + this.fetchLicenseAgreementList(dispatch, {licenseModelId, version}); + }); + } +}; + diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx new file mode 100644 index 0000000000..42f2407696 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import {connect} from 'react-redux'; +import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx'; +import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +function renderMsg(licenseAgreementToDelete) { + let name = licenseAgreementToDelete ? licenseAgreementToDelete.name : ''; + let msg = i18n('Are you sure you want to delete "{name}"?', {name}); + return( + <div> + <p>{msg}</p> + </div> + ); +}; + +const mapStateToProps = ({licenseModel: {licenseAgreement}}, {licenseModelId}) => { + let {licenseAgreementToDelete} = licenseAgreement; + const show = licenseAgreementToDelete !== false; + return { + show, + title: 'Warning!', + type: 'warning', + msg: renderMsg(licenseAgreementToDelete), + confirmationDetails: {licenseAgreementToDelete, licenseModelId} + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onConfirmed: ({licenseAgreementToDelete, licenseModelId}) => { + + LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreementToDelete.id}); + LicenseAgreementActionHelper.hideDeleteConfirm(dispatch); + }, + onDeclined: () => { + LicenseAgreementActionHelper.hideDeleteConfirm(dispatch); + } + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView); + diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js new file mode 100644 index 0000000000..af5c454e22 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js @@ -0,0 +1,66 @@ +/*- + * ============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({ + LICENSE_AGREEMENT_LIST_LOADED: null, + ADD_LICENSE_AGREEMENT: null, + EDIT_LICENSE_AGREEMENT: null, + DELETE_LICENSE_AGREEMENT: null, + LICENSE_AGREEMENT_DELETE_CONFIRM: null, + + licenseAgreementEditor: { + OPEN: null, + CLOSE: null, + DATA_CHANGED: null, + SELECT_TAB: null, + SELECT_FEATURE_GROUPS_BUTTONTAB: null, + } + +}); + +export const enums = keyMirror({ + SELECTED_LICENSE_AGREEMENT_TAB: { + GENERAL: 1, + FEATURE_GROUPS: 2 + }, + + SELECTED_FEATURE_GROUPS_BUTTONTAB: { + ASSOCIATED_FEATURE_GROUPS: 1, + AVAILABLE_FEATURE_GROUPS: 2 + } +}); + +export const defaultState = { + LICENSE_AGREEMENT_EDITOR_DATA: { + licenseTerm: {choice: '', other: ''} + } +}; + +export const optionsInputValues = { + LICENSE_MODEL_TYPE: [ + {enum: '', title: i18n('please select…')}, + {enum: 'Fixed_Term', title: 'Fixed Term'}, + {enum: 'Perpetual', title: 'Perpetual'}, + {enum: 'Unlimited', title: 'Unlimited'} + ] +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js new file mode 100644 index 0000000000..6a3e4dbc73 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js @@ -0,0 +1,60 @@ +/*- + * ============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 LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js'; +import LicenseAgreementEditorView from './LicenseAgreementEditorView.jsx'; + +export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}) => { + + + let {data, selectedTab, selectedFeatureGroupsButtonTab} = licenseAgreement.licenseAgreementEditor; + + let previousData; + const licenseAgreementId = data ? data.id : null; + if(licenseAgreementId) { + previousData = licenseAgreement.licenseAgreementList.find(licenseAgreement => licenseAgreement.id === licenseAgreementId); + } + + const {featureGroupsList = []} = featureGroup; + + return { + data, + previousData, + selectedTab, + selectedFeatureGroupsButtonTab, + featureGroupsList + }; +}; + +export const mapActionsToProps = (dispatch, {licenseModelId}) => { + return { + onDataChanged: deltaData => LicenseAgreementActionHelper.licenseAgreementEditorDataChanged(dispatch, {deltaData}), + onTabSelect: tab => LicenseAgreementActionHelper.selectLicenseAgreementEditorTab(dispatch, {tab}), + onFeatureGroupsButtonTabSelect: buttonTab => LicenseAgreementActionHelper.selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}), + onCancel: () => LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch), + onSubmit: ({previousLicenseAgreement, licenseAgreement}) => { + LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch); + LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement}); + } + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementEditorView); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js new file mode 100644 index 0000000000..74e2f6e8c1 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js @@ -0,0 +1,54 @@ +/*- + * ============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 './LicenseAgreementConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case actionTypes.licenseAgreementEditor.OPEN: + return { + ...state, + data: action.licenseAgreement ? { ...action.licenseAgreement } : defaultState.LICENSE_AGREEMENT_EDITOR_DATA + }; + case actionTypes.licenseAgreementEditor.DATA_CHANGED: + return { + ...state, + data: { + ...state.data, + ...action.deltaData + } + }; + case actionTypes.licenseAgreementEditor.CLOSE: + return {}; + case actionTypes.licenseAgreementEditor.SELECT_TAB: + return { + ...state, + selectedTab: action.tab + }; + case actionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB: + return { + ...state, + selectedFeatureGroupsButtonTab: action.buttonTab + }; + default: + return state; + } + +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx new file mode 100644 index 0000000000..b21f943fed --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx @@ -0,0 +1,247 @@ +import React from 'react'; +import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js'; +import Button from 'react-bootstrap/lib/Button.js'; +import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx'; +import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx'; +import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx'; +import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx'; +import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx'; +import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; +import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx'; +import i18n from 'nfvo-utils/i18n/i18n.js'; + +import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues} from './LicenseAgreementConstants.js'; + + +const LicenseAgreementPropType = React.PropTypes.shape({ + id: React.PropTypes.string, + name: React.PropTypes.string, + description: React.PropTypes.string, + requirementsAndConstrains: React.PropTypes.string, + licenseTerm: React.PropTypes.object, + featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string) +}); + +class LicenseAgreementEditorView extends React.Component { + + static propTypes = { + data: LicenseAgreementPropType, + previousData: LicenseAgreementPropType, + isReadOnlyMode: React.PropTypes.bool, + onDataChanged: React.PropTypes.func.isRequired, + onSubmit: React.PropTypes.func.isRequired, + onCancel: React.PropTypes.func.isRequired, + + selectedTab: React.PropTypes.number, + onTabSelect: React.PropTypes.func, + + selectedFeatureGroupsButtonTab: React.PropTypes.number, + onFeatureGroupsButtonTabSelect: React.PropTypes.func, + featureGroupsList: DualListboxView.propTypes.availableList + }; + + static defaultProps = { + selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL, + selectedFeatureGroupsButtonTab: LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS, + data: {} + }; + + state = { + localFeatureGroupsListFilter: '' + }; + + render() { + let {selectedTab, onTabSelect, isReadOnlyMode} = this.props; + return ( + <ValidationForm + ref='validationForm' + hasButtons={true} + onSubmit={ () => this.submit() } + onReset={ () => this.props.onCancel() } + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + className='license-agreement-form'> + <ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}> + {this.renderGeneralTab()} + {this.renderFeatureGroupsTab()} + </ValidationTabs> + </ValidationForm> + ); + } + + submit() { + const {data: licenseAgreement, previousData: previousLicenseAgreement} = this.props; + this.props.onSubmit({licenseAgreement, previousLicenseAgreement}); + } + + renderGeneralTab() { + let {data = {}, onDataChanged} = this.props; + let {name, description, requirementsAndConstrains, licenseTerm} = data; + return ( + <ValidationTab + eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL} + title={i18n('General')}> + <div className='license-agreement-form-row'> + <div className='license-agreement-form-col'> + <ValidationInput + onChange={name => onDataChanged({name})} + label={i18n('Name')} + value={name} + name='license-agreement-name' + validations={{maxLength: 25, required: true}} + type='text'/> + <ValidationInput + onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains})} + label={i18n('Requirements and Constraints')} + value={requirementsAndConstrains} + name='license-agreement-requirements-and-constraints' + validations={{maxLength: 1000}} + type='textarea'/> + </div> + <ValidationInput + onChange={description => onDataChanged({description})} + label={i18n('Description')} + value={description} + name='license-agreement-description' + validations={{maxLength: 1000, required: true}} + type='textarea'/> + </div> + <div className='license-agreement-form-row'> + <ValidationInput + onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}})} + selectedEnum={licenseTerm && licenseTerm.choice} + validations={{required: true}} + type='select' + label={i18n('License Term')} + values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}/> + </div> + </ValidationTab> + ); + } + + renderFeatureGroupsTab() { + let {onFeatureGroupsButtonTabSelect, selectedFeatureGroupsButtonTab, featureGroupsList} = this.props; + if (featureGroupsList.length > 0) { + return ( + <ValidationTab + eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS} + title={i18n('Feature Groups')}> + <ButtonGroup> + { + this.renderFeatureGroupsButtonTab( + LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS, + selectedFeatureGroupsButtonTab, + i18n('Associated Feature Groups'), + onFeatureGroupsButtonTabSelect + ) + } + { + this.renderFeatureGroupsButtonTab( + LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS, + selectedFeatureGroupsButtonTab, + i18n('Available Feature Groups'), + onFeatureGroupsButtonTabSelect + ) + } + </ButtonGroup> + {this.renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab)} + </ValidationTab> + ); + } else { + return ( + <ValidationTab + eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS} + title={i18n('Feature Groups')}> + <p>{i18n('There is no available feature groups')}</p> + </ValidationTab> + ); + } + } + + renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab) { + const {featureGroupsList = [], data: {featureGroupsIds = []}} = this.props; + const {localFeatureGroupsListFilter} = this.state; + let selectedFeatureGroups = featureGroupsIds.map(featureGroupId => featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId)); + + const dualBoxFilterTitle = { + left: i18n('Available Feature Groups'), + right: i18n('Selected Feature Groups') + }; + + switch (selectedFeatureGroupsButtonTab) { + case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS: + if (!selectedFeatureGroups.length) { + return ( + <div className='no-items-msg'> + {i18n('There are currently no feature groups associated with this license agreement. Click "Available Feature Groups" to associate.')} + </div> + ); + } + if (featureGroupsList.length) { + return ( + <ListEditorView + className='thinner-list' + filterValue={localFeatureGroupsListFilter} + onFilter={localFeatureGroupsListFilter => this.setState({localFeatureGroupsListFilter})}> + {this.filterAssociatedFeatureGroupsList(selectedFeatureGroups).map(featureGroup => this.renderAssociatedFeatureGroupListItem(featureGroup))} + </ListEditorView> + ); + } + return; + case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS: + return ( + <DualListboxView + filterTitle={dualBoxFilterTitle} + selectedValuesList={this.props.data.featureGroupsIds} + availableList={this.props.featureGroupsList} + onChange={ selectedValuesList => this.props.onDataChanged( { featureGroupsIds: selectedValuesList } )}/> + ); + } + } + + renderFeatureGroupsButtonTab(buttonTab, selectedButtonTab, title, onClick) { + const isSelected = buttonTab === selectedButtonTab; + return ( + <Button + className='button-tab' + active={isSelected} + onClick={() => !isSelected && onClick(buttonTab)}> + { title } + </Button> + ); + } + + renderAssociatedFeatureGroupListItem({id, name, entitlementPoolsIds = [], licenseKeyGroupsIds = []}) { + const {onDataChanged, data: {featureGroupsIds}, isReadOnlyMode} = this.props; + return ( + <ListEditorViewItem + key={id} + onDelete={() => onDataChanged({featureGroupsIds: featureGroupsIds.filter(featureGroupId => featureGroupId !== id)})} + isReadOnlyMode={isReadOnlyMode}> + <div className='name'>{name}</div> + <div className='inner-objects-count'>{ + i18n( + 'Entitlement Pools({entitlementPoolsCounter}), License Key Groups({licenseKeyGroupsCount})', + { + entitlementPoolsCounter: entitlementPoolsIds.length, + licenseKeyGroupsCount: licenseKeyGroupsIds.length + } + ) + }</div> + </ListEditorViewItem> + ); + } + + filterAssociatedFeatureGroupsList(featureGroupsList) { + let {localFeatureGroupsListFilter} = this.state; + if (localFeatureGroupsListFilter) { + const filter = new RegExp(escape(localFeatureGroupsListFilter), 'i'); + return featureGroupsList.filter(({name}) => name.match(filter)); + } + else { + return featureGroupsList; + } + } +} + +export default LicenseAgreementEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js new file mode 100644 index 0000000000..ca18bfab79 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js @@ -0,0 +1,59 @@ +/*- + * ============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 LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; +import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js'; +import LicenseAgreementListEditorView from './LicenseAgreementListEditorView.jsx'; +import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js'; + +const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) => { + let {licenseAgreementList} = licenseAgreement; + let {data} = licenseAgreement.licenseAgreementEditor; + let {vendorName} = licenseModelEditor.data; + + let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data); + + return { + vendorName, + licenseAgreementList, + isReadOnlyMode, + isDisplayModal: Boolean(data), + isModalInEditMode: Boolean(data && data.id) + }; +}; + +const mapActionsToProps = (dispatch, {licenseModelId}) => { + return { + onAddLicenseAgreementClick: () => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId}), + onEditLicenseAgreementClick: licenseAgreement => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}), + onDeleteLicenseAgreement: licenseAgreement => LicenseAgreementActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement}), + onCallVCAction: action => { + LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => { + LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId}); + }); + }, + switchLicenseModelVersion: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}), + onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch) + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(LicenseAgreementListEditorView); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx new file mode 100644 index 0000000000..4d7e704ba3 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx @@ -0,0 +1,126 @@ +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 LicenseAgreementEditor from './LicenseAgreementEditor.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; +import {optionsInputValues} from './LicenseAgreementConstants'; +import LicenseAgreementConfirmationModal from './LicenseAgreementConfirmationModal.jsx'; + + +class LicenseAgreementListEditorView extends React.Component { + static propTypes = { + vendorName: React.PropTypes.string, + licenseModelId: React.PropTypes.string.isRequired, + licenseAgreementList: React.PropTypes.array, + isReadOnlyMode: React.PropTypes.bool.isRequired, + isDisplayModal: React.PropTypes.bool, + isModalInEditMode: React.PropTypes.bool, + onAddLicenseAgreementClick: React.PropTypes.func, + onEditLicenseAgreementClick: React.PropTypes.func, + onDeleteLicenseAgreement: React.PropTypes.func, + onCallVCAction: React.PropTypes.func + }; + + static defaultProps = { + licenseAgreementList: [] + }; + + state = { + localFilter: '' + }; + + render() { + const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; + const {onAddLicenseAgreementClick} = this.props; + const {localFilter} = this.state; + + return ( + <div className='license-agreement-list-editor'> + <ListEditorView + title={i18n('License Agreements for {vendorName} License Model', {vendorName})} + plusButtonTitle={i18n('Add License Agreement')} + onAdd={onAddLicenseAgreementClick} + filterValue={localFilter} + onFilter={filter => this.setState({localFilter: filter})} + isReadOnlyMode={isReadOnlyMode}> + {this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode))} + </ListEditorView> + <Modal show={isDisplayModal} bsSize='large' animation={true} className='license-agreement-modal'> + <Modal.Header> + <Modal.Title>{`${isModalInEditMode ? i18n('Edit License Agreement') : i18n('Create New License Agreement')}`}</Modal.Title> + </Modal.Header> + <Modal.Body> + { + isDisplayModal && ( + <LicenseAgreementEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} /> + ) + } + </Modal.Body> + </Modal> + <LicenseAgreementConfirmationModal licenseModelId={licenseModelId}/> + + </div> + ); + } + + filterList() { + let {licenseAgreementList} = this.props; + let {localFilter} = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return licenseAgreementList.filter(({name = '', description = '', licenseTerm = ''}) => { + return escape(name).match(filter) || escape(description).match(filter) || escape(this.extractValue(licenseTerm)).match(filter); + }); + } + else { + return licenseAgreementList; + } + } + + renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode) { + let {id, name, description, licenseTerm, featureGroupsIds = []} = licenseAgreement; + let {onEditLicenseAgreementClick, onDeleteLicenseAgreement} = this.props; + return ( + <ListEditorItemView + key={id} + onSelect={() => onEditLicenseAgreementClick(licenseAgreement)} + onDelete={() => onDeleteLicenseAgreement(licenseAgreement)} + 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='list-editor-item-view-field-tight'> + <div className='title'>{i18n('Type')}</div> + <div className='text type'>{this.extractValue(licenseTerm)}</div> + </div> + <div className='list-editor-item-view-field-tight'> + <div className='title'>{i18n('Feature')}</div> + <div className='title'>{i18n('Groups')}</div> + <div className='feature-groups-count'>{featureGroupsIds.length}</div> + </div> + </div> + <div className='list-editor-item-view-field'> + <div className='title'>{i18n('Description')}</div> + <div className='text description'>{description}</div> + </div> + </ListEditorItemView> + ); + } + + 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 LicenseAgreementListEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js new file mode 100644 index 0000000000..5b5fa00df1 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js @@ -0,0 +1,37 @@ +/*- + * ============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 as licenseAgreementActionTypes} from './LicenseAgreementConstants'; + +export default (state = [], action) => { + switch (action.type) { + case licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED: + return [...action.response.results]; + case licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT: + return [...state, action.licenseAgreement]; + case licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT: + const indexForEdit = state.findIndex(licenseAgreement => licenseAgreement.id === action.licenseAgreement.id); + return [...state.slice(0, indexForEdit), action.licenseAgreement, ...state.slice(indexForEdit + 1)]; + case licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT: + return state.filter(licenseAgreement => licenseAgreement.id !== action.licenseAgreementId); + default: + return state; + } +}; |