1 import React from 'react';
2 import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
3 import Button from 'react-bootstrap/lib/Button.js';
4 import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
5 import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx';
6 import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx';
7 import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
8 import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
9 import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
10 import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx';
11 import i18n from 'nfvo-utils/i18n/i18n.js';
13 import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues} from './LicenseAgreementConstants.js';
16 const LicenseAgreementPropType = React.PropTypes.shape({
17 id: React.PropTypes.string,
18 name: React.PropTypes.string,
19 description: React.PropTypes.string,
20 requirementsAndConstrains: React.PropTypes.string,
21 licenseTerm: React.PropTypes.object,
22 featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string)
25 class LicenseAgreementEditorView extends React.Component {
28 data: LicenseAgreementPropType,
29 previousData: LicenseAgreementPropType,
30 isReadOnlyMode: React.PropTypes.bool,
31 onDataChanged: React.PropTypes.func.isRequired,
32 onSubmit: React.PropTypes.func.isRequired,
33 onCancel: React.PropTypes.func.isRequired,
35 selectedTab: React.PropTypes.number,
36 onTabSelect: React.PropTypes.func,
38 selectedFeatureGroupsButtonTab: React.PropTypes.number,
39 onFeatureGroupsButtonTabSelect: React.PropTypes.func,
40 featureGroupsList: DualListboxView.propTypes.availableList
43 static defaultProps = {
44 selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL,
45 selectedFeatureGroupsButtonTab: LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
50 localFeatureGroupsListFilter: ''
54 let {selectedTab, onTabSelect, isReadOnlyMode} = this.props;
59 onSubmit={ () => this.submit() }
60 onReset={ () => this.props.onCancel() }
62 isReadOnlyMode={isReadOnlyMode}
63 className='license-agreement-form'>
64 <ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}>
65 {this.renderGeneralTab()}
66 {this.renderFeatureGroupsTab()}
73 const {data: licenseAgreement, previousData: previousLicenseAgreement} = this.props;
74 this.props.onSubmit({licenseAgreement, previousLicenseAgreement});
78 let {data = {}, onDataChanged} = this.props;
79 let {name, description, requirementsAndConstrains, licenseTerm} = data;
82 eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
83 title={i18n('General')}>
84 <div className='license-agreement-form-row'>
85 <div className='license-agreement-form-col'>
87 onChange={name => onDataChanged({name})}
90 name='license-agreement-name'
91 validations={{maxLength: 25, required: true}}
94 onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains})}
95 label={i18n('Requirements and Constraints')}
96 value={requirementsAndConstrains}
97 name='license-agreement-requirements-and-constraints'
98 validations={{maxLength: 1000}}
102 onChange={description => onDataChanged({description})}
103 label={i18n('Description')}
105 name='license-agreement-description'
106 validations={{maxLength: 1000, required: true}}
109 <div className='license-agreement-form-row'>
111 onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}})}
112 selectedEnum={licenseTerm && licenseTerm.choice}
113 validations={{required: true}}
115 label={i18n('License Term')}
116 values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}/>
122 renderFeatureGroupsTab() {
123 let {onFeatureGroupsButtonTabSelect, selectedFeatureGroupsButtonTab, featureGroupsList} = this.props;
124 if (featureGroupsList.length > 0) {
127 eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
128 title={i18n('Feature Groups')}>
131 this.renderFeatureGroupsButtonTab(
132 LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS,
133 selectedFeatureGroupsButtonTab,
134 i18n('Associated Feature Groups'),
135 onFeatureGroupsButtonTabSelect
139 this.renderFeatureGroupsButtonTab(
140 LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
141 selectedFeatureGroupsButtonTab,
142 i18n('Available Feature Groups'),
143 onFeatureGroupsButtonTabSelect
147 {this.renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab)}
153 eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
154 title={i18n('Feature Groups')}>
155 <p>{i18n('There is no available feature groups')}</p>
161 renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab) {
162 const {featureGroupsList = [], data: {featureGroupsIds = []}} = this.props;
163 const {localFeatureGroupsListFilter} = this.state;
164 let selectedFeatureGroups = featureGroupsIds.map(featureGroupId => featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId));
166 const dualBoxFilterTitle = {
167 left: i18n('Available Feature Groups'),
168 right: i18n('Selected Feature Groups')
171 switch (selectedFeatureGroupsButtonTab) {
172 case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS:
173 if (!selectedFeatureGroups.length) {
175 <div className='no-items-msg'>
176 {i18n('There are currently no feature groups associated with this license agreement. Click "Available Feature Groups" to associate.')}
180 if (featureGroupsList.length) {
183 className='thinner-list'
184 filterValue={localFeatureGroupsListFilter}
185 onFilter={localFeatureGroupsListFilter => this.setState({localFeatureGroupsListFilter})}>
186 {this.filterAssociatedFeatureGroupsList(selectedFeatureGroups).map(featureGroup => this.renderAssociatedFeatureGroupListItem(featureGroup))}
191 case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS:
194 filterTitle={dualBoxFilterTitle}
195 selectedValuesList={this.props.data.featureGroupsIds}
196 availableList={this.props.featureGroupsList}
197 onChange={ selectedValuesList => this.props.onDataChanged( { featureGroupsIds: selectedValuesList } )}/>
202 renderFeatureGroupsButtonTab(buttonTab, selectedButtonTab, title, onClick) {
203 const isSelected = buttonTab === selectedButtonTab;
206 className='button-tab'
208 onClick={() => !isSelected && onClick(buttonTab)}>
214 renderAssociatedFeatureGroupListItem({id, name, entitlementPoolsIds = [], licenseKeyGroupsIds = []}) {
215 const {onDataChanged, data: {featureGroupsIds}, isReadOnlyMode} = this.props;
219 onDelete={() => onDataChanged({featureGroupsIds: featureGroupsIds.filter(featureGroupId => featureGroupId !== id)})}
220 isReadOnlyMode={isReadOnlyMode}>
221 <div className='name'>{name}</div>
222 <div className='inner-objects-count'>{
224 'Entitlement Pools({entitlementPoolsCounter}), License Key Groups({licenseKeyGroupsCount})',
226 entitlementPoolsCounter: entitlementPoolsIds.length,
227 licenseKeyGroupsCount: licenseKeyGroupsIds.length
231 </ListEditorViewItem>
235 filterAssociatedFeatureGroupsList(featureGroupsList) {
236 let {localFeatureGroupsListFilter} = this.state;
237 if (localFeatureGroupsListFilter) {
238 const filter = new RegExp(escape(localFeatureGroupsListFilter), 'i');
239 return featureGroupsList.filter(({name}) => name.match(filter));
242 return featureGroupsList;
247 export default LicenseAgreementEditorView;