aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js160
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx43
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js66
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js60
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js54
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx247
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js59
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx126
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js37
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;
+ }
+};